[v4] drm/panel: add s6e3ha2 AMOLED panel driver

2015-05-29 Thread Hyungwon Hwang
This patch adds MIPI-DSI based S6E3HA2 panel driver. This panel has
1440x2560 resolution in 5.7-inch physical panel.

Signed-off-by: Donghwa Lee 
Signed-off-by: Hyungwon Hwang 
Cc: Inki Dae 
---
As Thierry Reding said in https://patchwork.kernel.org/patch/5714111/,
it can be confusing to check the result of a function call using a
variable which is not explicitly passed to function call. At the same
time, as Andrzej Hajda said, checking the result using the return value
in this driver makes the code too bloated. In the situation where many
simple function calls and the result checking for them are needed, I
thought that passing variable by reference with explicit variable is
the best.

Changes for v2:
- Fix errata in documentation and source code comments
Changes for v3:
- Remove the term LCD to clarify the sort of this panel
- Rename lcd-en-gpios to panel-en-gpios to clarify the sort of this panel
- Fix errata in documentation and source code comments
Changes for v4:
- Add support for brightness control
- Adjust the sequence of turning on/off
- Rename variable and properties for clarity
 .../devicetree/bindings/panel/samsung,s6e3ha2.txt  |  40 +
 drivers/gpu/drm/panel/Kconfig  |  11 +
 drivers/gpu/drm/panel/Makefile |   1 +
 drivers/gpu/drm/panel/panel-s6e3ha2.c  | 904 +
 4 files changed, 956 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/panel/samsung,s6e3ha2.txt
 create mode 100644 drivers/gpu/drm/panel/panel-s6e3ha2.c

diff --git a/Documentation/devicetree/bindings/panel/samsung,s6e3ha2.txt 
b/Documentation/devicetree/bindings/panel/samsung,s6e3ha2.txt
new file mode 100644
index 000..b8cacc0
--- /dev/null
+++ b/Documentation/devicetree/bindings/panel/samsung,s6e3ha2.txt
@@ -0,0 +1,40 @@
+Samsung S6E3HA2 5.7" 1440x2560 AMOLED panel
+
+Required properties:
+  - compatible: "samsung,s6e3ha2"
+  - reg: virtual channel number assigned to the panel
+  - vdd3-supply: core voltage supply
+  - vci-supply: voltage supply for analog circuits
+  - reset-gpio: GPIO spec for resetting
+  - enable-gpio: GPIO spec for enabling
+  - te-gpio: GPIO spec for receiving tearing effect synchronization signal
+  - display-timings: resolution, clock, timing information for the panel [1]
+
+[1]: Documentation/devicetree/bindings/video/display-timing.txt
+
+Example:
+
+panel at 0 {
+   compatible = "samsung,s6e3ha2";
+   reg = <0>;
+   vdd3-supply = <&ldo27_reg>;
+   vci-supply = <&ldo28_reg>;
+   reset-gpio = <&gpg0 0 GPIO_ACTIVE_LOW>;
+   enable-gpio = <&gpf1 5 GPIO_ACTIVE_HIGH>;
+   te-gpio = <&gpf1 3 GPIO_ACTIVE_LOW>;
+
+   display-timings {
+   timing-0 {
+   clock-frequency = <0>;
+   hactive = <1440>;
+   vactive = <2560>;
+   hfront-porch = <1>;
+   hback-porch = <1>;
+   hsync-len = <1>;
+   vfront-porch = <1>;
+   vback-porch = <15>;
+   vsync-len = <1>;
+   };
+   };
+};
+
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 6d64c7b..7833073 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -43,4 +43,15 @@ config DRM_PANEL_SHARP_LQ101R1SX01
  To compile this driver as a module, choose M here: the module
  will be called panel-sharp-lq101r1sx01.

+config DRM_PANEL_S6E3HA2
+   tristate "S6E3HA2 DSI command mode panel"
+   depends on OF
+   depends on BACKLIGHT_CLASS_DEVICE
+   depends on DRM_MIPI_DSI
+   select VIDEOMODE_HELPERS
+ Say Y here if you want to enable support for Samsung S6E3HA2
+ AMOLED panel module. This panel has a 1440x2560 resolution and
+ uses 32-bit RGB per pixel. It provides a 4 lane MIPI DSI interface
+ to the host.
+
 endmenu
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index 4b2a043..16ff312 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -2,3 +2,4 @@ obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o
 obj-$(CONFIG_DRM_PANEL_LD9040) += panel-ld9040.o
 obj-$(CONFIG_DRM_PANEL_S6E8AA0) += panel-s6e8aa0.o
 obj-$(CONFIG_DRM_PANEL_SHARP_LQ101R1SX01) += panel-sharp-lq101r1sx01.o
+obj-$(CONFIG_DRM_PANEL_S6E3HA2) += panel-s6e3ha2.o
diff --git a/drivers/gpu/drm/panel/panel-s6e3ha2.c 
b/drivers/gpu/drm/panel/panel-s6e3ha2.c
new file mode 100644
index 000..8cf5b7e
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-s6e3ha2.c
@@ -0,0 +1,904 @@
+/*
+ * MIPI-DSI based s6e3ha2 AMOLED 5.7 inch panel driver.
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd
+ *
+ * Donghwa Lee 
+ *
+ * This program is free software; you can redistribute it a

[PATCH 06/13] tests/exynos: add fimg2d event test

2015-11-02 Thread Hyungwon Hwang
On Fri, 30 Oct 2015 12:16:47 +0100
Tobias Jakobi  wrote:

> Hello Hyungwon,
> 
> first of all thanks for reviewing the series!
> 
> 
> 
> Hyungwon Hwang wrote:
> > On Tue, 22 Sep 2015 17:54:55 +0200
> > Tobias Jakobi  wrote:
> > 
> >> This tests async processing of G2D jobs. A separate thread is
> >> spawned to monitor the DRM fd for events and check whether a G2D
> >> job was completed.
> >>
> >> v2: Add GPLv2 header, argument handling and documentation.
> >> Test is only installed when requested.
> >> v3: Allocate G2D jobs with calloc which fixes 'busy' being
> >> potentially uninitialized. Also enable timeout for poll()
> >> in the monitor thread. This fixes pthread_join() not working
> >> because of poll() not returning.
> >>
> >> Signed-off-by: Tobias Jakobi 
> >> ---
> >>  tests/exynos/Makefile.am   |  11 +-
> >>  tests/exynos/exynos_fimg2d_event.c | 326
> >> + 2 files changed, 335
> >> insertions(+), 2 deletions(-) create mode 100644
> >> tests/exynos/exynos_fimg2d_event.c
> >>
> >> diff --git a/tests/exynos/Makefile.am b/tests/exynos/Makefile.am
> >> index e82d199..357d6b8 100644
> >> --- a/tests/exynos/Makefile.am
> >> +++ b/tests/exynos/Makefile.am
> >> @@ -20,16 +20,23 @@ endif
> >>  
> >>  if HAVE_INSTALL_TESTS
> >>  bin_PROGRAMS += \
> >> -  exynos_fimg2d_perf
> >> +  exynos_fimg2d_perf \
> >> +  exynos_fimg2d_event
> >>  else
> >>  noinst_PROGRAMS += \
> >> -  exynos_fimg2d_perf
> >> +  exynos_fimg2d_perf \
> >> +  exynos_fimg2d_event
> >>  endif
> >>  
> >>  exynos_fimg2d_perf_LDADD = \
> >>$(top_builddir)/libdrm.la \
> >>$(top_builddir)/exynos/libdrm_exynos.la
> >>  
> >> +exynos_fimg2d_event_LDADD = \
> >> +  $(top_builddir)/libdrm.la \
> >> +  $(top_builddir)/exynos/libdrm_exynos.la \
> >> +  -lpthread
> >> +
> >>  exynos_fimg2d_test_LDADD = \
> >>$(top_builddir)/libdrm.la \
> >>$(top_builddir)/libkms/libkms.la \
> >> diff --git a/tests/exynos/exynos_fimg2d_event.c
> >> b/tests/exynos/exynos_fimg2d_event.c new file mode 100644
> >> index 000..c03dcff
> >> --- /dev/null
> >> +++ b/tests/exynos/exynos_fimg2d_event.c
> >> @@ -0,0 +1,326 @@
> >> +/*
> >> + * Copyright (C) 2015 - Tobias Jakobi
> >> + *
> >> + * This is free software: you can redistribute it and/or modify
> >> + * it under the terms of the GNU General Public License as
> >> published
> >> + * by the Free Software Foundation, either version 2 of the
> >> License,
> >> + * or (at your option) any later version.
> >> + *
> >> + * It is distributed in the hope that it will be useful, but
> >> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> >> + * GNU General Public License for more details.
> >> + * You should have received a copy of the GNU General Public
> >> License
> >> + * along with it. If not, see <http://www.gnu.org/licenses/>.
> >> + */
> >> +
> >> +#include 
> >> +#include 
> >> +
> >> +#include 
> >> +#include 
> >> +#include 
> >> +#include 
> >> +
> >> +#include 
> >> +
> >> +#include 
> >> +
> >> +#include "exynos_drm.h"
> >> +#include "exynos_drmif.h"
> >> +#include "exynos_fimg2d.h"
> >> +
> >> +struct g2d_job {
> >> +  unsigned int id;
> >> +  unsigned int busy;
> >> +};
> >> +
> >> +struct exynos_evhandler {
> >> +  struct pollfd fds;
> >> +  struct exynos_event_context evctx;
> >> +};
> >> +
> >> +struct threaddata {
> >> +  unsigned int stop;
> >> +  struct exynos_device *dev;
> >> +  struct exynos_evhandler evhandler;
> >> +};
> >> +
> >> +static void g2d_event_handler(int fd, unsigned int cmdlist_no,
> >> unsigned int tv_sec,
> >> +  unsigned
> >> int tv_usec, void *user_data) +{
> >> +  struct g2d_job *job = user_data;
> >> +
> >> +  fprintf(stderr, "info: g2d job (id = %u, cmdlist number =
> >> 

[PATCH 07/13] tests/exynos: use XRGB8888 for framebuffer

2015-11-02 Thread Hyungwon Hwang
On Fri, 30 Oct 2015 12:17:02 +0100
Tobias Jakobi  wrote:

> Hello Hyungwon,
> 
> 
> Hyungwon Hwang wrote:
> > On Tue, 22 Sep 2015 17:54:56 +0200
> > Tobias Jakobi  wrote:
> > 
> >> This matches the G2D color mode that is used in the entire code.
> >> The previous (incorrect) RGBA would only work since the
> >> Exynos mixer did its configuration based on the bpp, and not
> >> based on the actual pixelformat.
> >>
> >> Signed-off-by: Tobias Jakobi 
> >> ---
> >>  tests/exynos/exynos_fimg2d_test.c | 2 +-
> >>  1 file changed, 1 insertion(+), 1 deletion(-)
> >>
> >> diff --git a/tests/exynos/exynos_fimg2d_test.c
> >> b/tests/exynos/exynos_fimg2d_test.c index 8794dac..dfb00a0 100644
> >> --- a/tests/exynos/exynos_fimg2d_test.c
> >> +++ b/tests/exynos/exynos_fimg2d_test.c
> >> @@ -675,7 +675,7 @@ int main(int argc, char **argv)
> >>offsets[0] = 0;
> >>  
> >>ret = drmModeAddFB2(dev->fd, screen_width, screen_height,
> >> -      DRM_FORMAT_RGBA, handles,
> >> +  DRM_FORMAT_XRGB, handles,
> >>pitches, offsets, &fb_id, 0);
> > 
> > Reviewed-by: Hyungwon Hwang 
> > 
> > Nice catch. It's right, if there was no previous setting for source
> > image color mode. But I think it could be the source image color
> > mode was set by another application before when this test runs. So
> > I think the code which sets the source image color mode must be
> > added.
> I think you misunderstand something here. First of all settings from
> anither application using DRM don't carry over.
> 
> The point for this change is that all used G2D image structures have
> the color_mode field set to G2D_COLOR_FMT_ARGB | G2D_ORDER_AXRGB.
> So the G2D is operating on ARGB pixel data.
> 
> However the framebuffer is set to DRM_FORMAT_RGBA, which obviously
> is wrong since this is not the type of data we put into the
> framebuffer.

Oh. That's right. I misunderstanded the code. This patch is absolutely
right.

Best regards,
Hyungwon Hwang

> 
> 
> With best wishes,
> Tobias
> 
> 
> > 
> > Best regards,
> > Hyungwon Hwang
> > 
> > 
> >>if (ret < 0)
> >>goto err_destroy_buffer;
> > 
> 



[PATCH 08/13] exynos: fimg2d: add g2d_set_direction

2015-11-02 Thread Hyungwon Hwang
On Fri, 30 Oct 2015 18:14:23 +0100
Tobias Jakobi  wrote:

> Tobias Jakobi wrote:
> > Hello Hyungwon,
> > 
> > 
> > Hyungwon Hwang wrote:
> >> On Tue, 22 Sep 2015 17:54:57 +0200
> >> Tobias Jakobi  wrote:
> >>
> >>> This allows setting the two direction registers, which specify how
> >>> the engine blits pixels. This can be used for overlapping blits,
> >>> which happen e.g. when 'moving' a rectangular region inside a
> >>> fixed buffer.
> >>
> >> Code itself looks good. But as I know, direction registers are
> >> related with flip, not moving. Isn't it? I am not that much
> >> familiar with G2D. Please let me know if I am wrong.
> > that's correct, you can use the direction registers to implement
> > flipping operations.
> > 
> > However what they really do is to change the operation direction of
> > the G2D engine. So you can manage how the engine traverses through
> > pixel rows and column (either in forward or in backward direction).
> > 
> > Normally this doesn't matter, like it doesn't matter if you memcpy()
> > from one buffer to another when there is no intersection of the
> > buffers. However if the two buffers overlap then you have to be
> > careful with the direction in which you traverse the buffer.
> > 
> > Now if you set the x-direction of the source G2D image to forward,
> > but the x-direction of the destination to backward, you get your
> > mentioned x-flipping.
> > 
> > The main purpose for g2d_move() is to be used e.g. in acceleration
> > code for the armsoc Xorg DDX. A common operation there is not move
> > pixel regions around in the same buffer.
> Sorry, this should read "...there is to move pixel regions...".

OK. I understood what you meant.

Reviewed-by: Hyungwon Hwang 


Best regards,
Hyungwon Hwang

> 
> 
> - Tobias
> 
> > 
> > 
> > With best wishes,
> > Tobias
> > 
> > 
> > P.S.: I think the Exynos user manual mentions flipping as one
> > example on how to use these registers. But like I said above, it's
> > just one way to use it.
> > 
> > 
> > 
> > 
> >>
> >> Best regards,
> >> Hyungwon Hwang
> >>
> >>>
> >>> Signed-off-by: Tobias Jakobi 
> >>> ---
> >>>  exynos/exynos_fimg2d.c | 13 +
> >>>  exynos/exynos_fimg2d.h | 38
> >>> ++ 2 files changed, 51
> >>> insertions(+)
> >>>
> >>> diff --git a/exynos/exynos_fimg2d.c b/exynos/exynos_fimg2d.c
> >>> index e997d4b..4d5419c 100644
> >>> --- a/exynos/exynos_fimg2d.c
> >>> +++ b/exynos/exynos_fimg2d.c
> >>> @@ -242,6 +242,19 @@ static void g2d_add_base_addr(struct
> >>> g2d_context *ctx, struct g2d_image *img, }
> >>>  
> >>>  /*
> >>> + * g2d_set_direction - setup direction register (useful for
> >>> overlapping blits).
> >>> + *
> >>> + * @ctx: a pointer to g2d_context structure.
> >>> + * @dir: a pointer to the g2d_direction_val structure.
> >>> + */
> >>> +static void g2d_set_direction(struct g2d_context *ctx,
> >>> + const union g2d_direction_val *dir)
> >>> +{
> >>> + g2d_add_cmd(ctx, SRC_MASK_DIRECT_REG, dir->val[0]);
> >>> + g2d_add_cmd(ctx, DST_PAT_DIRECT_REG, dir->val[1]);
> >>> +}
> >>> +
> >>> +/*
> >>>   * g2d_reset - reset fimg2d hardware.
> >>>   *
> >>>   * @ctx: a pointer to g2d_context structure.
> >>> diff --git a/exynos/exynos_fimg2d.h b/exynos/exynos_fimg2d.h
> >>> index c6b58ac..9eee7c0 100644
> >>> --- a/exynos/exynos_fimg2d.h
> >>> +++ b/exynos/exynos_fimg2d.h
> >>> @@ -189,6 +189,11 @@ enum e_g2d_exec_flag {
> >>>   G2D_EXEC_FLAG_ASYNC = (1 << 0)
> >>>  };
> >>>  
> >>> +enum e_g2d_dir_mode {
> >>> + G2D_DIR_MODE_POSITIVE = 0,
> >>> + G2D_DIR_MODE_NEGATIVE = 1
> >>> +};
> >>> +
> >>>  union g2d_point_val {
> >>>   unsigned int val;
> >>>   struct {
> >>> @@ -269,6 +274,39 @@ union g2d_blend_func_val {
> >>>   } data;
> >>>  };
> >>>  
> >>> +union g2d_direction_val {
> >>> + unsigned int val[2];
> >>> + struct {
> >>> + /* SRC_MSK_DI

[PATCH 09/13] exynos/fimg2d: add g2d_move

2015-11-09 Thread Hyungwon Hwang
Hello Tobias,

I was in vacation last week, so I could run your code today. I found
that what g2d_move() does is actually copying not moving, because the
operation does not clear the previous area. Would it be possible to
generalize g2d_copy() works better, so it could works well in case of
the src buffer and dst buffer being same. If it is possible, I think it
would be better way to do that. If it is not, at least chaning the
function name is needed. I tested it on my Odroid U3 board.

Best regards,
Hyungwon Hwang

On Tue, 22 Sep 2015 17:54:58 +0200
Tobias Jakobi  wrote:

> We already have g2d_copy() which implements G2D copy
> operations from one buffer to another. However we can't
> do a overlapping copy operation in one buffer.
> 
> Add g2d_move() which acts like the standard memmove()
> and properly handles overlapping copies.
> 
> Signed-off-by: Tobias Jakobi 
> ---
>  exynos/exynos_fimg2d.c | 94
> ++
> exynos/exynos_fimg2d.h |  3 ++ 2 files changed, 97 insertions(+)
> 
> diff --git a/exynos/exynos_fimg2d.c b/exynos/exynos_fimg2d.c
> index 4d5419c..8703629 100644
> --- a/exynos/exynos_fimg2d.c
> +++ b/exynos/exynos_fimg2d.c
> @@ -540,6 +540,100 @@ g2d_copy(struct g2d_context *ctx, struct
> g2d_image *src, }
>  
>  /**
> + * g2d_move - move content inside single buffer.
> + *   Similar to 'memmove' this moves a rectangular region
> + *   of the provided buffer to another location (the source
> + *   and destination region potentially overlapping).
> + *
> + * @ctx: a pointer to g2d_context structure.
> + * @img: a pointer to g2d_image structure providing
> + *   buffer information.
> + * @src_x: x position of source rectangle.
> + * @src_y: y position of source rectangle.
> + * @dst_x: x position of destination rectangle.
> + * @dst_y: y position of destination rectangle.
> + * @w: width of rectangle to move.
> + * @h: height of rectangle to move.
> + */
> +int
> +g2d_move(struct g2d_context *ctx, struct g2d_image *img,
> + unsigned int src_x, unsigned int src_y,
> + unsigned int dst_x, unsigned dst_y, unsigned int w,
> + unsigned int h)
> +{
> + union g2d_rop4_val rop4;
> + union g2d_point_val pt;
> + union g2d_direction_val dir;
> + unsigned int src_w, src_h, dst_w, dst_h;
> +
> + src_w = w;
> + src_h = h;
> + if (src_x + img->width > w)
> + src_w = img->width - src_x;
> + if (src_y + img->height > h)
> + src_h = img->height - src_y;
> +
> + dst_w = w;
> + dst_h = w;
> + if (dst_x + img->width > w)
> + dst_w = img->width - dst_x;
> + if (dst_y + img->height > h)
> + dst_h = img->height - dst_y;
> +
> + w = MIN(src_w, dst_w);
> + h = MIN(src_h, dst_h);
> +
> + if (w == 0 || h == 0) {
> + fprintf(stderr, MSG_PREFIX "invalid width or
> height.\n");
> + return -EINVAL;
> + }
> +
> + if (g2d_check_space(ctx, 13, 2))
> + return -ENOSPC;
> +
> + g2d_add_cmd(ctx, DST_SELECT_REG, G2D_SELECT_MODE_BGCOLOR);
> + g2d_add_cmd(ctx, SRC_SELECT_REG, G2D_SELECT_MODE_NORMAL);
> +
> + g2d_add_cmd(ctx, DST_COLOR_MODE_REG, img->color_mode);
> + g2d_add_cmd(ctx, SRC_COLOR_MODE_REG, img->color_mode);
> +
> + g2d_add_base_addr(ctx, img, g2d_dst);
> + g2d_add_base_addr(ctx, img, g2d_src);
> +
> + g2d_add_cmd(ctx, DST_STRIDE_REG, img->stride);
> + g2d_add_cmd(ctx, SRC_STRIDE_REG, img->stride);
> +
> + dir.val[0] = dir.val[1] = 0;
> +
> + if (dst_x >= src_x)
> + dir.data.src_x_direction = dir.data.dst_x_direction
> = 1;
> + if (dst_y >= src_y)
> + dir.data.src_y_direction = dir.data.dst_y_direction
> = 1; +
> + g2d_set_direction(ctx, &dir);
> +
> + pt.data.x = src_x;
> + pt.data.y = src_y;
> + g2d_add_cmd(ctx, SRC_LEFT_TOP_REG, pt.val);
> + pt.data.x = src_x + w;
> + pt.data.y = src_y + h;
> + g2d_add_cmd(ctx, SRC_RIGHT_BOTTOM_REG, pt.val);
> +
> + pt.data.x = dst_x;
> + pt.data.y = dst_y;
> + g2d_add_cmd(ctx, DST_LEFT_TOP_REG, pt.val);
> + pt.data.x = dst_x + w;
> + pt.data.y = dst_y + h;
> + g2d_add_cmd(ctx, DST_RIGHT_BOTTOM_REG, pt.val);
> +
> + rop4.val = 0;
> + rop4.data.unmasked_rop3 = G2D_ROP3_SRC;
> + g2d_add_cmd(ctx, ROP4_REG, rop4.val);
> +
> + return g2d_flush(ctx);
> +}
> +
> +/**
>   * g2d_copy_with_scale - copy contents in source buffer to
> destination buffer
>   *   scaling up or down properly.
>   *
> di

[PATCH 10/13] tests/exynos: add test for g2d_move

2015-11-09 Thread Hyungwon Hwang
Hello,

I think this patch should update .gitignore, not for adding the built
binary to untracked file list.

But without it, it looks good to me, and I tested it on my Odroid U3
board.

Tested-by: Hyungwon Hwang 
Reviewed-by: Hyungwon Hwang 

Best regards,
Hyungwon Hwang


On Tue, 22 Sep 2015 17:54:59 +0200
Tobias Jakobi  wrote:

> To check if g2d_move() works properly we create a small checkerboard
> pattern in the center of the screen and then shift this pattern
> around with g2d_move(). The pattern should be properly preserved
> by the operation.
> 
> Signed-off-by: Tobias Jakobi 
> ---
>  tests/exynos/exynos_fimg2d_test.c | 132
> ++ 1 file changed, 132
> insertions(+)
> 
> diff --git a/tests/exynos/exynos_fimg2d_test.c
> b/tests/exynos/exynos_fimg2d_test.c index dfb00a0..797fb6e 100644
> --- a/tests/exynos/exynos_fimg2d_test.c
> +++ b/tests/exynos/exynos_fimg2d_test.c
> @@ -313,6 +313,130 @@ fail:
>   return ret;
>  }
>  
> +static int g2d_move_test(struct exynos_device *dev,
> + struct exynos_bo *tmp,
> + struct exynos_bo *buf,
> + enum e_g2d_buf_type type)
> +{
> + struct g2d_context *ctx;
> + struct g2d_image img = {0}, tmp_img = {0};
> + unsigned int img_w, img_h, count;
> + int cur_x, cur_y;
> + void *checkerboard;
> + int ret;
> +
> + static const struct g2d_step {
> + int x, y;
> + } steps[] = {
> + { 1,  0}, { 0,  1},
> + {-1,  0}, { 0, -1},
> + { 1,  1}, {-1, -1},
> + { 1, -1}, {-1,  1},
> + { 2,  1}, { 1,  2},
> + {-2, -1}, {-1, -2},
> + { 2, -1}, { 1, -2},
> + {-2,  1}, {-1,  2}
> + };
> + static const unsigned int num_steps =
> + sizeof(steps) / sizeof(struct g2d_step);
> +
> + ctx = g2d_init(dev->fd);
> + if (!ctx)
> + return -EFAULT;
> +
> + img.bo[0] = buf->handle;
> +
> + /* create pattern of half the screen size */
> + checkerboard = create_checkerboard_pattern(screen_width /
> 64, screen_height / 64, 32);
> + if (!checkerboard) {
> + ret = -EFAULT;
> + goto fail;
> + }
> +
> + img_w = (screen_width / 64) * 32;
> + img_h = (screen_height / 64) * 32;
> +
> + switch (type) {
> + case G2D_IMGBUF_GEM:
> + memcpy(tmp->vaddr, checkerboard, img_w * img_h * 4);
> + tmp_img.bo[0] = tmp->handle;
> + break;
> + case G2D_IMGBUF_USERPTR:
> + tmp_img.user_ptr[0].userptr = (unsigned
> long)checkerboard;
> + tmp_img.user_ptr[0].size = img_w * img_h * 4;
> + break;
> + case G2D_IMGBUF_COLOR:
> + default:
> + ret = -EFAULT;
> + goto fail;
> + }
> +
> + /* solid fill framebuffer with white color */
> + img.width = screen_width;
> + img.height = screen_height;
> + img.stride = screen_width * 4;
> + img.buf_type = G2D_IMGBUF_GEM;
> + img.color_mode = G2D_COLOR_FMT_ARGB | G2D_ORDER_AXRGB;
> + img.color = 0x;
> +
> + /* put checkerboard pattern in the center of the framebuffer
> */
> + cur_x = (screen_width - img_w) / 2;
> + cur_y = (screen_height - img_h) / 2;
> + tmp_img.width = img_w;
> + tmp_img.height = img_h;
> + tmp_img.stride = img_w * 4;
> + tmp_img.buf_type = type;
> + tmp_img.color_mode = G2D_COLOR_FMT_ARGB |
> G2D_ORDER_AXRGB; +
> + ret = g2d_solid_fill(ctx, &img, 0, 0, screen_width,
> screen_height) ||
> + g2d_copy(ctx, &tmp_img, &img, 0, 0, cur_x, cur_y,
> img_w, img_h); +
> + if (!ret)
> + ret = g2d_exec(ctx);
> + if (ret < 0)
> + goto fail;
> +
> + printf("move test with %s.\n",
> + type == G2D_IMGBUF_GEM ? "gem" : "userptr");
> +
> + srand(time(NULL));
> + for (count = 0; count < 256; ++count) {
> + const struct g2d_step *s;
> +
> + /* select step and validate it */
> + while (1) {
> + s = &steps[random() % num_steps];
> +
> + if (cur_x + s->x < 0 || cur_y + s->y < 0 ||
> + cur_x + img_w + s->x >= screen_width
> ||
> + cur_y + img_h + s->y >=
> screen_height)
> + continue;
> + else
> + break;

[PATCH v4] tests/exynos: add fimg2d performance analysis

2015-11-09 Thread Hyungwon Hwang
Hello,

I think this patch should update .gitignore, not for adding the built
binary to untracked file list.

Also, I want to make clear about the purpose of this test program. What
do you want to get after this test? This program runs G2D with
randomly chosen number of pixel and shows the elapsed time to do
that. I run it on my board. But I could not find any meaning of the
test. If you just want to know the execution time of solid fill, what
about get the width and height from user and run the same tests
iteratively for more accurate result? Or at least, increasing number of
pixels?


Best regards,
Hyungwon Hwang


On Mon, 02 Nov 2015 10:52:09 +0100
Tobias Jakobi  wrote:

> Currently only fast solid color clear performance is measured.
> A large buffer is allocated and solid color clear operations
> are executed on it with randomly chosen properties (position
> and size of the region, clear color). Execution time is
> measured and output together with the amount of pixels
> processed.
> 
> The 'simple' variant only executes one G2D command buffer at
> a time, while the 'multi' variant executes multiple ones. This
> can be used to measure setup/exec overhead.
> 
> The test also serves a stability check. If clocks/voltages are
> too high or low respectively, the test quickly reveals this.
> 
> v2: Add GPLv2 header, argument handling and documentation.
> Tool is only installed when requested.
> v3: Free images array in fimg2d_perf_multi() as pointed out
> by Hyungwon Hwang.
> v4: Include header for error numbers (fixes build).
> 
> Signed-off-by: Tobias Jakobi 
> ---
>  tests/exynos/Makefile.am  |  19 ++-
>  tests/exynos/exynos_fimg2d_perf.c | 327
> ++ 2 files changed, 344
> insertions(+), 2 deletions(-) create mode 100644
> tests/exynos/exynos_fimg2d_perf.c
> 
> diff --git a/tests/exynos/Makefile.am b/tests/exynos/Makefile.am
> index b21d016..e82d199 100644
> --- a/tests/exynos/Makefile.am
> +++ b/tests/exynos/Makefile.am
> @@ -5,16 +5,31 @@ AM_CFLAGS = \
>   -I $(top_srcdir)/exynos \
>   -I $(top_srcdir)
>  
> +bin_PROGRAMS =
> +noinst_PROGRAMS =
> +
>  if HAVE_LIBKMS
>  if HAVE_INSTALL_TESTS
> -bin_PROGRAMS = \
> +bin_PROGRAMS += \
>   exynos_fimg2d_test
>  else
> -noinst_PROGRAMS = \
> +noinst_PROGRAMS += \
>   exynos_fimg2d_test
>  endif
>  endif
>  
> +if HAVE_INSTALL_TESTS
> +bin_PROGRAMS += \
> + exynos_fimg2d_perf
> +else
> +noinst_PROGRAMS += \
> + exynos_fimg2d_perf
> +endif
> +
> +exynos_fimg2d_perf_LDADD = \
> + $(top_builddir)/libdrm.la \
> + $(top_builddir)/exynos/libdrm_exynos.la
> +
>  exynos_fimg2d_test_LDADD = \
>   $(top_builddir)/libdrm.la \
>   $(top_builddir)/libkms/libkms.la \
> diff --git a/tests/exynos/exynos_fimg2d_perf.c
> b/tests/exynos/exynos_fimg2d_perf.c new file mode 100644
> index 000..1699bba
> --- /dev/null
> +++ b/tests/exynos/exynos_fimg2d_perf.c
> @@ -0,0 +1,327 @@
> +/*
> + * Copyright (C) 2015 - Tobias Jakobi
> + *
> + * This is free software: you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published
> + * by the Free Software Foundation, either version 2 of the License,
> + * or (at your option) any later version.
> + *
> + * It is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + * You should have received a copy of the GNU General Public License
> + * along with it. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include 
> +
> +#include "exynos_drm.h"
> +#include "exynos_drmif.h"
> +#include "exynos_fimg2d.h"
> +
> +static int output_mathematica = 0;
> +
> +static int fimg2d_perf_simple(struct exynos_bo *bo, struct
> g2d_context *ctx,
> + unsigned buf_width, unsigned buf_height,
> unsigned iterations) +{
> + struct timespec tspec = { 0 };
> + struct g2d_image img = { 0 };
> +
> + unsigned long long g2d_time;
> + unsigned i;
> + int ret = 0;
> +
> + img.width = buf_width;
> + img.height = buf_height;
> + img.stride = buf_width * 4;
> + img.color_mode = G2D_COLOR_FMT_ARGB | G2D_ORDER_AXRGB;
> + img.buf_type = G2D_IMGBUF_GEM;
> + img.bo[0] = bo->handle;
> +
> + srand(time(NULL));
> +
> + printf("starting simple G2D performance test\n");
&g

[PATCH v4] tests/exynos: add fimg2d performance analysis

2015-11-10 Thread Hyungwon Hwang
Hello Tobias,

On Mon, 09 Nov 2015 10:47:13 +0100
Tobias Jakobi  wrote:

> Hello Hyungwon,
> 
> 
> Hyungwon Hwang wrote:
> > Hello,
> > 
> > I think this patch should update .gitignore, not for adding the
> > built binary to untracked file list.
> Thanks!
> 
> 
> > Also, I want to make clear about the purpose of this test program.
> > What do you want to get after this test? This program runs G2D with
> > randomly chosen number of pixel and shows the elapsed time to do
> > that. I run it on my board. But I could not find any meaning of the
> > test. If you just want to know the execution time of solid fill,
> > what about get the width and height from user and run the same tests
> > iteratively for more accurate result? Or at least, increasing
> > number of pixels?
> The test is to measure the dependency between amount of pixels the G2D
> has to process and the amount of time for the G2D to process such
> pixels.
> 
> It's exactly what a performance test should do, measure the time it
> takes for a certain workload to complete.
> 
> In particular the test wants to answer the question if the dependency
> stated above is of linear type.
> 
> Of course it's not, since we have setup time, so at least it should be
> affine linear. But even that is not true, since you see subtle
> 'branching' when doing high density plots (that's why I added export
> of the data to Mathematica).
> 
> 
> What you ask for (user input) is in fact already implemented. The user
> can specify the buffer width and height, which in turn limits the size
> of the rectangle that is solid filled.
> 
> If you want smaller rectangles filled, decrease buffer width and
> height, if you want bigger ones filled, increase.
> 
> 
> The second purpose is to stress test the G2D, as already indicated in
> the commit description. The G2D can be overclocked quite a lot under
> certain conditions. With increase MIF/INT voltages I can run it with
> 400MHz instead of the 200MHz defaults. The application can now be used
> to check stability. E.g. if voltages are too low the system can
> quickly lock-up.
> 
> In particular one could also check how processing time depends on the
> clock rate of the G2D. One interesting question here is how memory
> bandwidth limits us.
> 
> 
> 
> With best wishes,
> Tobias

Yes. I agree with the broad view. Please see the below, I run the test
2 times in a row.

root at localhost:~# ./exynos_fimg2d_perf  -i 10 -w 1024 -h 1024   
exynos/fimg2d: G2D version (4.1).
starting simple G2D performance test
buffer width = 1024, buffer height = 1024, iterations = 10
num_pixels = 136000, usecs = 236000
num_pixels = 8492, usecs = 47083
num_pixels = 100688, usecs = 200042
num_pixels = 141312, usecs = 216667
num_pixels = 39962, usecs = 92708
num_pixels = 95046, usecs = 156542
num_pixels = 2562, usecs = 34666
num_pixels = 176485, usecs = 326916
num_pixels = 17760, usecs = 56625
num_pixels = 1625, usecs = 31833
starting multi G2D performance test (batch size = 3)
buffer width = 1024, buffer height = 1024, iterations = 10
num_pixels = 245180, usecs = 385083
num_pixels = 276320, usecs = 398625
num_pixels = 196807, usecs = 35
num_pixels = 305540, usecs = 420458
num_pixels = 65978, usecs = 120250
num_pixels = 265028, usecs = 379417
num_pixels = 139079, usecs = 213667
num_pixels = 24970, usecs = 67625
num_pixels = 46808, usecs = 114125
num_pixels = 100804, usecs = 179750
root at localhost:~# ./exynos_fimg2d_perf  -i 10 -w 1024 -h 1024 
exynos/fimg2d: G2D version (4.1).
starting simple G2D performance test
buffer width = 1024, buffer height = 1024, iterations = 10
num_pixels = 18676, usecs = 95541
num_pixels = 117056, usecs = 218875
num_pixels = 80784, usecs = 137209
num_pixels = 427, usecs = 33209
num_pixels = 238044, usecs = 403041
num_pixels = 4392, usecs = 37709
num_pixels = 19880, usecs = 59750
num_pixels = 3666, usecs = 36542
num_pixels = 4630, usecs = 36166
num_pixels = 70834, usecs = 125917
starting multi G2D performance test (batch size = 3)
buffer width = 1024, buffer height = 1024, iterations = 10
num_pixels = 216516, usecs = 347042
num_pixels = 242863, usecs = 422417
num_pixels = 28176, usecs = 72292
num_pixels = 110713, usecs = 179167
num_pixels = 292266, usecs = 431750
num_pixels = 274127, usecs = 392833
num_pixels = 291659, usecs = 415875
num_pixels = 140202, usecs = 218833
num_pixels = 122400, usecs = 193084
num_pixels = 168647, usecs = 251375

As you said, I can adjust the buffer width and height. But because the
program choose the number of pixel to process randomly, I can't compare
the result after I modified something (clock, or something else like
you mentioned). Also I can figure out the tendency between the number
of pixels and the processing time after I draw the graph. But it is too

[PATCH 09/13] exynos/fimg2d: add g2d_move

2015-11-10 Thread Hyungwon Hwang
Hello Tobias,

On Mon, 09 Nov 2015 10:47:02 +0100
Tobias Jakobi  wrote:

> Hello Hyungwon,
> 
> 
> Hyungwon Hwang wrote:
> > Hello Tobias,
> > 
> > I was in vacation last week, so I could run your code today. I found
> > that what g2d_move() does is actually copying not moving, because
> > the operation does not clear the previous area.
> I choose g2d_move() because we also have memcpy() and memmove() in
> libc. Like in libc 'moving' memory doesn't actually move it, like you
> would move a real object, since it's undefined what 'empty' memory
> should be.
> 
> The same applies here. It's not defined what 'empty' areas of the
> buffer should be.
> 
> 
> > Would it be possible to
> > generalize g2d_copy() works better, so it could works well in case
> > of the src buffer and dst buffer being same.
> I think this would break g2d_copy() backward compatibility.
> 
> I also want the user to explicitly request this. The user should make
> sure what requirements he has for the buffers in question. Are the
> buffers disjoint or not?
> 
> 
> > If it is possible, I think it
> > would be better way to do that. If it is not, at least chaning the
> > function name is needed. I tested it on my Odroid U3 board.
> I don't have a strong opinion on the naming. Any recommendations?
> 
> I still think the naming is fine though, since it mirrors libc's
> naming. And the user is supposed to read the documentation anyway.

> 
> 
> 
> With best wishes,
> Tobias

In that manner following glibc, I agree that the naming is reasonable.
I commented like that previously, because at the first time when I run
the test, I think that the result seems like a bug. The test program
said that it was a move test, but the operation seemed copying. It
would be just OK if it is well documented or printed when runs the test
that the test does not do anything about the previous area
intentionally.


BRs,
Hyungwon Hwang

> 
> > 
> > Best regards,
> > Hyungwon Hwang
> > 
> > On Tue, 22 Sep 2015 17:54:58 +0200
> > Tobias Jakobi  wrote:
> > 
> >> We already have g2d_copy() which implements G2D copy
> >> operations from one buffer to another. However we can't
> >> do a overlapping copy operation in one buffer.
> >>
> >> Add g2d_move() which acts like the standard memmove()
> >> and properly handles overlapping copies.
> >>
> >> Signed-off-by: Tobias Jakobi 
> >> ---
> >>  exynos/exynos_fimg2d.c | 94
> >> ++
> >> exynos/exynos_fimg2d.h |  3 ++ 2 files changed, 97 insertions(+)
> >>
> >> diff --git a/exynos/exynos_fimg2d.c b/exynos/exynos_fimg2d.c
> >> index 4d5419c..8703629 100644
> >> --- a/exynos/exynos_fimg2d.c
> >> +++ b/exynos/exynos_fimg2d.c
> >> @@ -540,6 +540,100 @@ g2d_copy(struct g2d_context *ctx, struct
> >> g2d_image *src, }
> >>  
> >>  /**
> >> + * g2d_move - move content inside single buffer.
> >> + *Similar to 'memmove' this moves a rectangular region
> >> + *of the provided buffer to another location (the source
> >> + *and destination region potentially overlapping).
> >> + *
> >> + * @ctx: a pointer to g2d_context structure.
> >> + * @img: a pointer to g2d_image structure providing
> >> + *buffer information.
> >> + * @src_x: x position of source rectangle.
> >> + * @src_y: y position of source rectangle.
> >> + * @dst_x: x position of destination rectangle.
> >> + * @dst_y: y position of destination rectangle.
> >> + * @w: width of rectangle to move.
> >> + * @h: height of rectangle to move.
> >> + */
> >> +int
> >> +g2d_move(struct g2d_context *ctx, struct g2d_image *img,
> >> +  unsigned int src_x, unsigned int src_y,
> >> +  unsigned int dst_x, unsigned dst_y, unsigned int
> >> w,
> >> +  unsigned int h)
> >> +{
> >> +  union g2d_rop4_val rop4;
> >> +  union g2d_point_val pt;
> >> +  union g2d_direction_val dir;
> >> +  unsigned int src_w, src_h, dst_w, dst_h;
> >> +
> >> +  src_w = w;
> >> +  src_h = h;
> >> +  if (src_x + img->width > w)
> >> +  src_w = img->width - src_x;
> >> +  if (src_y + img->height > h)
> >> +  src_h = img->height - src_y;
> >> +
> >> +  dst_w = w;
> >> +  dst_h = w;
> >> +  if (dst_x + img

[PATCH v4] tests/exynos: add fimg2d performance analysis

2015-11-11 Thread Hyungwon Hwang
On Tue, 10 Nov 2015 14:23:51 +0100
Tobias Jakobi  wrote:

> Hello Hyungwon,
> 
> 
> Hyungwon Hwang wrote:
> > Hello Tobias,
> > 
> > On Mon, 09 Nov 2015 10:47:13 +0100
> > Tobias Jakobi  wrote:
> > 
> >> Hello Hyungwon,
> >>
> >>
> >> Hyungwon Hwang wrote:
> >>> Hello,
> >>>
> >>> I think this patch should update .gitignore, not for adding the
> >>> built binary to untracked file list.
> >> Thanks!
> >>
> >>
> >>> Also, I want to make clear about the purpose of this test program.
> >>> What do you want to get after this test? This program runs G2D
> >>> with randomly chosen number of pixel and shows the elapsed time
> >>> to do that. I run it on my board. But I could not find any
> >>> meaning of the test. If you just want to know the execution time
> >>> of solid fill, what about get the width and height from user and
> >>> run the same tests iteratively for more accurate result? Or at
> >>> least, increasing number of pixels?
> >> The test is to measure the dependency between amount of pixels the
> >> G2D has to process and the amount of time for the G2D to process
> >> such pixels.
> >>
> >> It's exactly what a performance test should do, measure the time it
> >> takes for a certain workload to complete.
> >>
> >> In particular the test wants to answer the question if the
> >> dependency stated above is of linear type.
> >>
> >> Of course it's not, since we have setup time, so at least it
> >> should be affine linear. But even that is not true, since you see
> >> subtle 'branching' when doing high density plots (that's why I
> >> added export of the data to Mathematica).
> >>
> >>
> >> What you ask for (user input) is in fact already implemented. The
> >> user can specify the buffer width and height, which in turn limits
> >> the size of the rectangle that is solid filled.
> >>
> >> If you want smaller rectangles filled, decrease buffer width and
> >> height, if you want bigger ones filled, increase.
> >>
> >>
> >> The second purpose is to stress test the G2D, as already indicated
> >> in the commit description. The G2D can be overclocked quite a lot
> >> under certain conditions. With increase MIF/INT voltages I can run
> >> it with 400MHz instead of the 200MHz defaults. The application can
> >> now be used to check stability. E.g. if voltages are too low the
> >> system can quickly lock-up.
> >>
> >> In particular one could also check how processing time depends on
> >> the clock rate of the G2D. One interesting question here is how
> >> memory bandwidth limits us.
> >>
> >>
> >>
> >> With best wishes,
> >> Tobias
> > 
> > Yes. I agree with the broad view. Please see the below, I run the
> > test 2 times in a row.
> > 
> > root at localhost:~# ./exynos_fimg2d_perf  -i 10 -w 1024 -h 1024   
> > exynos/fimg2d: G2D version (4.1).
> > starting simple G2D performance test
> > buffer width = 1024, buffer height = 1024, iterations = 10
> > num_pixels = 136000, usecs = 236000
> > num_pixels = 8492, usecs = 47083
> > num_pixels = 100688, usecs = 200042
> > num_pixels = 141312, usecs = 216667
> > num_pixels = 39962, usecs = 92708
> > num_pixels = 95046, usecs = 156542
> > num_pixels = 2562, usecs = 34666
> > num_pixels = 176485, usecs = 326916
> > num_pixels = 17760, usecs = 56625
> > num_pixels = 1625, usecs = 31833
> > starting multi G2D performance test (batch size = 3)
> > buffer width = 1024, buffer height = 1024, iterations = 10
> > num_pixels = 245180, usecs = 385083
> > num_pixels = 276320, usecs = 398625
> > num_pixels = 196807, usecs = 35
> > num_pixels = 305540, usecs = 420458
> > num_pixels = 65978, usecs = 120250
> > num_pixels = 265028, usecs = 379417
> > num_pixels = 139079, usecs = 213667
> > num_pixels = 24970, usecs = 67625
> > num_pixels = 46808, usecs = 114125
> > num_pixels = 100804, usecs = 179750
> > root at localhost:~# ./exynos_fimg2d_perf  -i 10 -w 1024 -h 1024 
> > exynos/fimg2d: G2D version (4.1).
> > starting simple G2D performance test
> > buffer width = 1024, buffer height = 1024, iterations = 10
> > num_pixels = 18676, usecs = 95541
> > num_pixels = 117056, usecs = 218875
> > num_pixels = 80784, usecs = 137209
> > num_pixels = 427, usecs

[PATCH 09/13] exynos/fimg2d: add g2d_move

2015-11-11 Thread Hyungwon Hwang
Hello Tobias,

On Tue, 10 Nov 2015 14:24:11 +0100
Tobias Jakobi  wrote:

> Hello Hyungwon,
> 
> 
> Hyungwon Hwang wrote:
> > Hello Tobias,
> > 
> > On Mon, 09 Nov 2015 10:47:02 +0100
> > Tobias Jakobi  wrote:
> > 
> >> Hello Hyungwon,
> >>
> >>
> >> Hyungwon Hwang wrote:
> >>> Hello Tobias,
> >>>
> >>> I was in vacation last week, so I could run your code today. I
> >>> found that what g2d_move() does is actually copying not moving,
> >>> because the operation does not clear the previous area.
> >> I choose g2d_move() because we also have memcpy() and memmove() in
> >> libc. Like in libc 'moving' memory doesn't actually move it, like
> >> you would move a real object, since it's undefined what 'empty'
> >> memory should be.
> >>
> >> The same applies here. It's not defined what 'empty' areas of the
> >> buffer should be.
> >>
> >>
> >>> Would it be possible to
> >>> generalize g2d_copy() works better, so it could works well in case
> >>> of the src buffer and dst buffer being same.
> >> I think this would break g2d_copy() backward compatibility.
> >>
> >> I also want the user to explicitly request this. The user should
> >> make sure what requirements he has for the buffers in question.
> >> Are the buffers disjoint or not?
> >>
> >>
> >>> If it is possible, I think it
> >>> would be better way to do that. If it is not, at least chaning the
> >>> function name is needed. I tested it on my Odroid U3 board.
> >> I don't have a strong opinion on the naming. Any recommendations?
> >>
> >> I still think the naming is fine though, since it mirrors libc's
> >> naming. And the user is supposed to read the documentation anyway.
> > 
> >>
> >>
> >>
> >> With best wishes,
> >> Tobias
> > 
> > In that manner following glibc, I agree that the naming is
> > reasonable.
> well, that was just my way of thinking. But I guess most people have
> experience using the libc, so the naming should look at least
> 'familiar'.
> 
> 
> 
> > I commented like that previously, because at the first time when I
> > run the test, I think that the result seems like a bug. The test
> > program said that it was a move test, but the operation seemed
> > copying.
> Ok, so just that I understand this correctly. Your issue is with the
> commit the description of the test or with the commit description of
> the patch that introduces g2d_move()?
> 
> Because I don't see what you point out in the test commit description:
> 
> "
> tests/exynos: add test for g2d_move
> 
> To check if g2d_move() works properly we create a small checkerboard
> pattern in the center of the screen and then shift this pattern
> around with g2d_move(). The pattern should be properly preserved
> by the operation.
> "
> 
> I intentionally avoid to write "...move this pattern around...", so
> instead I choose "shift".
> 
> I'm not a native speaker, so I'm clueless how to formulate this in a
> more clear way.

I'm also not a native speaker, so maybe I could not figure out the
subtle difference between move and shift. I just thought that 'shift'
was just the synonym of 'move'.

> 
> 
> > It
> > would be just OK if it is well documented or printed when runs the
> > test that the test does not do anything about the previous area
> > intentionally.
> I could add solid fills of the 'empty' areas after each move()
> operation. Would that be more in line what you think the test should
> do?

No. Because g2d_move() is to g2d_copy() what memmove() is to memcpy(),
the current implementation seems enough.

What about change 'move' to 'copy' in the function description?

* g2d_move - copy content inside single buffer.
* Similar to 'memmove' this copies a rectangular region
* of the provided buffer to another location (the source
* and destination region potentially overlapping)

Best regards,
Hyungwon Hwang

> 
> 
> With best wishes,
> Tobias
> 
> 
> 
> 
> > 
> > 
> > BRs,
> > Hyungwon Hwang
> > 
> --
> To unsubscribe from this list: send the line "unsubscribe
> linux-samsung-soc" in the body of a message to
> majordomo at vger.kernel.org More majordomo info at
> http://vger.kernel.org/majordomo-info.html



[PATCH 2/6] xf86drmMode: separate drmModeAtomicCommit() and drmModeAtomicCleanup()

2015-08-19 Thread Hyungwon Hwang
This patch seprates the code, which sorts proprty sets and eliminates
duplicate properties, from drmModeAtomicCommit(). Now
drmModeAtomicCleanup() has to do the job before calling
drmModeAtomicCommit(), and drmModeAtomicCommit() just converts the cleaned
request to IOCTL argument.

Signed-off-by: Hyungwon Hwang 
---
 xf86drmMode.c | 72 +--
 xf86drmMode.h |  1 +
 2 files changed, 41 insertions(+), 32 deletions(-)

diff --git a/xf86drmMode.c b/xf86drmMode.c
index d4ed5c1..82c4c91 100644
--- a/xf86drmMode.c
+++ b/xf86drmMode.c
@@ -1303,10 +1303,39 @@ static int sort_req_list(const void *misc, const void 
*other)
return second->property_id - first->property_id;
 }

+void drmModeAtomicCleanup(drmModeAtomicReqPtr req)
+{
+   uint32_t last_obj_id = 0;
+   uint32_t i;
+
+   if (req->cursor == 0)
+   return;
+
+   /* Sort the list by object ID, then by property ID. */
+   qsort(req->items, req->cursor, sizeof(*req->items),
+ sort_req_list);
+
+   /* Eliminate duplicate property sets. */
+   for (i = 0; i < req->cursor; i++) {
+   if (req->items[i].object_id != last_obj_id)
+   last_obj_id = req->items[i].object_id;
+
+   if (i == req->cursor - 1)
+   continue;
+
+   if (req->items[i].object_id != req->items[i + 1].object_id ||
+   req->items[i].property_id != req->items[i + 1].property_id)
+   continue;
+
+   memmove(&req->items[i], &req->items[i + 1],
+   (req->cursor - i - 1) * sizeof(*req->items));
+   req->cursor--;
+   }
+}
+
 int drmModeAtomicCommit(int fd, drmModeAtomicReqPtr req, uint32_t flags,
void *user_data)
 {
-   drmModeAtomicReqPtr sorted;
struct drm_mode_atomic atomic;
uint32_t *objs_ptr = NULL;
uint32_t *count_props_ptr = NULL;
@@ -1320,33 +1349,13 @@ int drmModeAtomicCommit(int fd, drmModeAtomicReqPtr 
req, uint32_t flags,
if (req->cursor == 0)
return 0;

-   sorted = drmModeAtomicDuplicate(req);
-   if (sorted == NULL)
-   return -ENOMEM;
-
memclear(atomic);

-   /* Sort the list by object ID, then by property ID. */
-   qsort(sorted->items, sorted->cursor, sizeof(*sorted->items),
- sort_req_list);
-
-   /* Now the list is sorted, eliminate duplicate property sets. */
-   for (i = 0; i < sorted->cursor; i++) {
-   if (sorted->items[i].object_id != last_obj_id) {
+   for (i = 0; i < req->cursor; i++) {
+   if (req->items[i].object_id != last_obj_id) {
atomic.count_objs++;
-   last_obj_id = sorted->items[i].object_id;
+   last_obj_id = req->items[i].object_id;
}
-
-   if (i == sorted->cursor - 1)
-   continue;
-
-   if (sorted->items[i].object_id != sorted->items[i + 
1].object_id ||
-   sorted->items[i].property_id != sorted->items[i + 
1].property_id)
-   continue;
-
-   memmove(&sorted->items[i], &sorted->items[i + 1],
-   (sorted->cursor - i - 1) * sizeof(*sorted->items));
-   sorted->cursor--;
}

objs_ptr = drmMalloc(atomic.count_objs * sizeof objs_ptr[0]);
@@ -1361,28 +1370,28 @@ int drmModeAtomicCommit(int fd, drmModeAtomicReqPtr 
req, uint32_t flags,
goto out;
}

-   props_ptr = drmMalloc(sorted->cursor * sizeof props_ptr[0]);
+   props_ptr = drmMalloc(req->cursor * sizeof props_ptr[0]);
if (!props_ptr) {
errno = ENOMEM;
goto out;
}

-   prop_values_ptr = drmMalloc(sorted->cursor * sizeof prop_values_ptr[0]);
+   prop_values_ptr = drmMalloc(req->cursor * sizeof prop_values_ptr[0]);
if (!prop_values_ptr) {
errno = ENOMEM;
goto out;
}

-   for (i = 0, last_obj_id = 0; i < sorted->cursor; i++) {
-   if (sorted->items[i].object_id != last_obj_id) {
+   for (i = 0, last_obj_id = 0; i < req->cursor; i++) {
+   if (req->items[i].object_id != last_obj_id) {
obj_idx++;
-   objs_ptr[obj_idx] = sorted->items[i].object_id;
+   objs_ptr[obj_idx] = req->items[i].object_id;
last_obj_id = objs_ptr[obj_idx];
}

count_props_ptr[obj_idx]++;
-   props_ptr[i] = sorted->items[i].property_id;
-   prop_values_ptr[i] = sorted->items[i].value;
+   props_ptr[i] =

[PATCH 1/6] xf86drmMode: remove the trailing white spaces

2015-08-19 Thread Hyungwon Hwang
This patch removes the trailing white spaces.

Signed-off-by: Hyungwon Hwang 
---
 xf86drmMode.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/xf86drmMode.c b/xf86drmMode.c
index fc19504..d4ed5c1 100644
--- a/xf86drmMode.c
+++ b/xf86drmMode.c
@@ -879,7 +879,7 @@ int drmHandleEvent(int fd, drmEventContextPtr evctx)
int len, i;
struct drm_event *e;
struct drm_event_vblank *vblank;
-   
+
/* The DRM read semantics guarantees that we always get only
 * complete events. */

@@ -899,7 +899,7 @@ int drmHandleEvent(int fd, drmEventContextPtr evctx)
break;
vblank = (struct drm_event_vblank *) e;
evctx->vblank_handler(fd,
- vblank->sequence, 
+ vblank->sequence,
  vblank->tv_sec,
  vblank->tv_usec,
  U642VOID (vblank->user_data));
-- 
2.4.3



[PATCH 4/6] modetest: remove the trailing white spaces

2015-08-19 Thread Hyungwon Hwang
This patch removes the trailing white spaces.

Signed-off-by: Hyungwon Hwang 
---
 tests/modetest/modetest.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
index 4eb9eac..43bd06f 100644
--- a/tests/modetest/modetest.c
+++ b/tests/modetest/modetest.c
@@ -1251,7 +1251,7 @@ static void test_page_flip(struct device *dev, struct 
pipe_arg *pipes, unsigned
evctx.version = DRM_EVENT_CONTEXT_VERSION;
evctx.vblank_handler = NULL;
evctx.page_flip_handler = page_flip_handler;
-   
+
while (1) {
 #if 0
struct pollfd pfd[2];
@@ -1565,7 +1565,7 @@ int main(int argc, char **argv)
if (parse_connector(&pipe_args[count], optarg) < 0)
usage(argv[0]);

-   count++;  
+   count++;
break;
case 'C':
test_cursor = 1;
-- 
2.4.3



[PATCH 5/6] modetest: add atomic modeset support

2015-08-19 Thread Hyungwon Hwang
This patch adds support for atomic modeset. Using -a option, user can
make modeset to use DRM_IOCTL_MODE_ATOMIC instead of legacy IOCTLs.
Also, by using -W option, user can set the value of each object's property.

Signed-off-by: Hyungwon Hwang 
---
 tests/modetest/modetest.c | 237 +++---
 1 file changed, 204 insertions(+), 33 deletions(-)

diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
index 43bd06f..bf9222d 100644
--- a/tests/modetest/modetest.c
+++ b/tests/modetest/modetest.c
@@ -1433,15 +1433,21 @@ static int parse_property(struct property_arg *p, const 
char *arg)

 static void usage(char *name)
 {
-   fprintf(stderr, "usage: %s [-cDdefMPpsCvw]\n", name);
+   fprintf(stderr, "usage: %s [-acDdefMPpsCvwW]\n", name);
+   fprintf(stderr, "\tA: supported in atomic modeset\n");
+   fprintf(stderr, "\tL: supported in legacy modeset\n");

-   fprintf(stderr, "\n Query options:\n\n");
+   fprintf(stderr, "\n Query options: [AL]\n\n");
fprintf(stderr, "\t-c\tlist connectors\n");
fprintf(stderr, "\t-e\tlist encoders\n");
fprintf(stderr, "\t-f\tlist framebuffers\n");
fprintf(stderr, "\t-p\tlist CRTCs and planes (pipes)\n");

-   fprintf(stderr, "\n Test options:\n\n");
+   fprintf(stderr, "\n Atomic Test options: [A]\n\n");
+   fprintf(stderr, "\t-a\tuse atomic modeset\n");
+   fprintf(stderr, "\t-W ::\tset property\n");
+
+   fprintf(stderr, "\n Legacy test options: [L]\n\n");
fprintf(stderr, "\t-P 
:x[++][*][@]\tset a plane\n");
fprintf(stderr, "\t-s 
[,][@]:[-][@]\tset 
a mode\n");
fprintf(stderr, "\t-C\ttest hw cursor\n");
@@ -1449,9 +1455,9 @@ static void usage(char *name)
fprintf(stderr, "\t-w ::\tset property\n");

fprintf(stderr, "\n Generic options:\n\n");
-   fprintf(stderr, "\t-d\tdrop master after mode set\n");
-   fprintf(stderr, "\t-M module\tuse the given driver\n");
-   fprintf(stderr, "\t-D device\tuse the given device\n");
+   fprintf(stderr, "\t-d\tdrop master after mode set [L]\n");
+   fprintf(stderr, "\t-M module\tuse the given driver [AL]\n");
+   fprintf(stderr, "\t-D device\tuse the given device [AL]\n");

fprintf(stderr, "\n\tDefault is to dump all info.\n");
exit(0);
@@ -1484,7 +1490,154 @@ static int cursor_supported(void)
return 1;
 }

-static char optstr[] = "cdD:efM:P:ps:Cvw:";
+static int parse_atomic_args(drmModeAtomicReqPtr req, const char *p)
+{
+   uint32_t object_id, property_id;
+   uint64_t value;
+
+   if (sscanf(p, "%u:%u:%llu", &object_id, &property_id, &value) != 3)
+   return -1;
+
+   drmModeAtomicAddProperty(req, object_id, property_id, value);
+
+   return 0;
+}
+
+static uint32_t get_atomic_plane_prop_id(struct resources *res, uint32_t 
obj_id,
+   const char 
*name)
+{
+   drmModePropertyRes *props_info;
+   struct plane *plane;
+   unsigned int i, j;
+
+   for (i = 0; i < res->plane_res->count_planes; i++) {
+   plane = &res->planes[i];
+   if (plane->plane->plane_id != obj_id)
+   continue;
+
+   for (j = 0; j < plane->props->count_props; j++) {
+   props_info = plane->props_info[j];
+   if (!strcmp(props_info->name, name))
+   return props_info->prop_id;
+   }
+   }
+
+   return 0;
+}
+
+static uint64_t get_atomic_plane_prop_value_in_request(drmModeAtomicReqPtr req,
+   struct resources *res, uint32_t obj_id, const char 
*name)
+{
+   uint32_t prop_id, i;
+   drmModeAtomicReqItemPtr item;
+
+   prop_id = get_atomic_plane_prop_id(res, obj_id, name);
+
+   for (i = 0; i < req->cursor; i++) {
+   item = &req->items[i];
+
+   if (item->object_id != obj_id)
+   continue;
+
+   if (item->property_id != prop_id)
+   continue;
+
+   return item->value;
+   }
+
+   return -1;
+}
+
+static bool is_atomic_obj_in_request(drmModeAtomicReqPtr req,
+   uint32_t obj_id)
+{
+   unsigned int i;
+
+   for (i = 0; i < req->cursor; i++)
+   if (req->items[i].object_id == obj_id)
+   return true;
+
+   return false;
+}
+
+static int allocate_fb(struct device *dev, drmModeAtomicReqPtr req, struct 
resources *res,
+  

[PATCH 6/6] modetest: add atomic page flip support

2015-08-19 Thread Hyungwon Hwang
This patch adds support for atomic page flip. User can specify -W option
with the plane id for testing atomic page flipping.

Signed-off-by: Hyungwon Hwang 
---
 tests/modetest/modetest.c | 150 +-
 1 file changed, 147 insertions(+), 3 deletions(-)

diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
index bf9222d..d1b7dc4 100644
--- a/tests/modetest/modetest.c
+++ b/tests/modetest/modetest.c
@@ -719,6 +719,10 @@ struct pipe_arg {
struct timeval start;

int swap_count;
+
+   /* for atomic modeset */
+   uint32_t plane_id;
+   uint32_t fb_obj_id;
 };

 struct plane_arg {
@@ -1446,6 +1450,7 @@ static void usage(char *name)
fprintf(stderr, "\n Atomic Test options: [A]\n\n");
fprintf(stderr, "\t-a\tuse atomic modeset\n");
fprintf(stderr, "\t-W ::\tset property\n");
+   fprintf(stderr, "\t-V \ttest vsynced page 
flipping\n");

fprintf(stderr, "\n Legacy test options: [L]\n\n");
fprintf(stderr, "\t-P 
:x[++][*][@]\tset a plane\n");
@@ -1637,7 +1642,137 @@ static void atomic_modeset(struct device *dev, 
drmModeAtomicReqPtr req,
drmModeAtomicCommit(dev->fd, req, flags, NULL);
 }

-static char optstr[] = "acdD:efM:P:ps:Cvw:W:";
+static void
+atomic_page_flip_handler(int fd, unsigned int frame,
+   unsigned int sec, unsigned int usec, void *data)
+{
+   static drmModeAtomicReqPtr req = NULL;
+   unsigned int new_fb_id;
+   struct timeval end;
+   struct pipe_arg *pipe;
+   double t;
+   uint32_t flags = 0;
+
+   pipe = (struct pipe_arg *)(unsigned long)data;
+
+   if (pipe->current_fb_id == pipe->fb_id[0])
+   new_fb_id = pipe->fb_id[1];
+   else
+   new_fb_id = pipe->fb_id[0];
+
+   pipe->current_fb_id = new_fb_id;
+   pipe->swap_count++;
+
+   req = drmModeAtomicAlloc();
+
+   drmModeAtomicAddProperty(req, pipe->plane_id, pipe->fb_obj_id, 
new_fb_id);
+
+   flags = DRM_MODE_PAGE_FLIP_EVENT;
+   drmModeAtomicCommit(fd, req, flags, pipe);
+
+   if (pipe->swap_count == 60) {
+   gettimeofday(&end, NULL);
+   t = end.tv_sec + end.tv_usec * 1e-6 -
+   (pipe->start.tv_sec + pipe->start.tv_usec * 1e-6);
+   fprintf(stderr, "freq: %.02fHz\n", pipe->swap_count / t);
+   pipe->swap_count = 0;
+   pipe->start = end;
+   }
+
+   drmModeAtomicFree(req);
+}
+
+static int atomic_test_page_flip(struct device *dev, drmModeAtomicReqPtr req,
+   struct resources *res, unsigned int plane_id)
+{
+   struct bo *other_bo;
+   unsigned int other_fb_id;
+   struct pipe_arg *pipe = NULL;
+   drmEventContext evctx;
+   uint32_t flags = 0, fb_obj_id = 0, pixel_format;
+   uint64_t width, height;
+   int ret;
+
+   if (!is_atomic_obj_in_request(req, plane_id))
+   return -1;
+
+   fb_obj_id = get_atomic_plane_prop_id(res, plane_id, "FB_ID");
+   if (!fb_obj_id)
+   return -1;
+
+   width = get_atomic_plane_prop_value_in_request(req, res,
+   plane_id, "SRC_W");
+   height = get_atomic_plane_prop_value_in_request(req, res,
+   plane_id, "SRC_H");
+   pixel_format = DRM_FORMAT_XRGB;
+
+   ret = allocate_fb(dev, req, res, width, height, pixel_format,
+   PATTERN_TILES, &other_bo, &other_fb_id);
+   if (ret < 0)
+   return ret;
+
+   ret = drmModeAtomicAddProperty(req, plane_id, fb_obj_id,
+   other_fb_id);
+   if (ret < 0)
+   goto err;
+
+   if (!fb_obj_id) {
+   fprintf(stderr, "page flipping requires at least one plane 
setting.\n");
+   return -1;
+   }
+
+   pipe = drmMalloc(sizeof *pipe);
+
+   gettimeofday(&pipe->start, NULL);
+   pipe->swap_count = 0;
+   pipe->plane_id = plane_id;
+   pipe->fb_obj_id = fb_obj_id;
+   pipe->fb_id[0] = dev->mode.fb_id;
+   pipe->fb_id[1] = other_fb_id;
+   pipe->current_fb_id = other_fb_id;
+
+   flags = DRM_MODE_PAGE_FLIP_EVENT;
+
+   ret = drmModeAtomicCommit(dev->fd, req, flags, pipe);
+   if (ret < 0)
+   goto err_rmfb;
+
+   memset(&evctx, 0, sizeof evctx);
+   evctx.version = DRM_EVENT_CONTEXT_VERSION;
+   evctx.vblank_handler = NULL;
+   evctx.page_flip_handler = atomic_page_flip_handler;
+
+   while (1) {
+   struct timeval timeout = { .tv_sec = 3, .tv_usec = 0 };
+   fd_set fds;
+   int ret;
+
+   FD_ZERO(&fds);
+   FD_SET(0, &fds);
+   FD_SET(dev->fd, &am

[PATCH 3/6] xf86drmMode: Make atomic request structures visible

2015-08-19 Thread Hyungwon Hwang
This patch makes 'struct _drmModeAtomicReqItem' and 'struct
_drmModeAtomicReq' visible from outside. This is needed for userspace
applications to use those structures when calling drmModeAtomicCommit().

Signed-off-by: Hyungwon Hwang 
---
 xf86drmMode.c | 14 --
 xf86drmMode.h | 12 
 2 files changed, 12 insertions(+), 14 deletions(-)

diff --git a/xf86drmMode.c b/xf86drmMode.c
index 82c4c91..cf3fa21 100644
--- a/xf86drmMode.c
+++ b/xf86drmMode.c
@@ -1164,20 +1164,6 @@ int drmModeObjectSetProperty(int fd, uint32_t object_id, 
uint32_t object_type,
return DRM_IOCTL(fd, DRM_IOCTL_MODE_OBJ_SETPROPERTY, &prop);
 }

-typedef struct _drmModeAtomicReqItem drmModeAtomicReqItem, 
*drmModeAtomicReqItemPtr;
-
-struct _drmModeAtomicReqItem {
-   uint32_t object_id;
-   uint32_t property_id;
-   uint64_t value;
-};
-
-struct _drmModeAtomicReq {
-   uint32_t cursor;
-   uint32_t size_items;
-   drmModeAtomicReqItemPtr items;
-};
-
 drmModeAtomicReqPtr drmModeAtomicAlloc(void)
 {
drmModeAtomicReqPtr req;
diff --git a/xf86drmMode.h b/xf86drmMode.h
index fe14078..ec05ed8 100644
--- a/xf86drmMode.h
+++ b/xf86drmMode.h
@@ -485,6 +485,18 @@ extern int drmModeObjectSetProperty(int fd, uint32_t 
object_id,
uint64_t value);


+struct _drmModeAtomicReqItem {
+   uint32_t object_id;
+   uint32_t property_id;
+   uint64_t value;
+};
+typedef struct _drmModeAtomicReqItem drmModeAtomicReqItem, 
*drmModeAtomicReqItemPtr;
+
+struct _drmModeAtomicReq {
+   uint32_t cursor;
+   uint32_t size_items;
+   drmModeAtomicReqItemPtr items;
+};
 typedef struct _drmModeAtomicReq drmModeAtomicReq, *drmModeAtomicReqPtr;

 extern drmModeAtomicReqPtr drmModeAtomicAlloc(void);
-- 
2.4.3



[PATCH 1/2] drm/exynos: implement exynos_crtc_atomic_{begin/flush}

2015-08-20 Thread Hyungwon Hwang
All chagnes in CRTCs of Exynos are applied in H/W, only when the protection
for shadow register update is not enabled. Using these protection, every
change can be applied at once. Now exynos_crtc_atomic_{begin/flush} stops
or starts the update of shadow registers by calling each CRTC specific
atomic_{begin/flush}.

Signed-off-by: Hyungwon Hwang 
---
 drivers/gpu/drm/exynos/exynos_drm_crtc.c | 7 +++
 drivers/gpu/drm/exynos/exynos_drm_drv.h  | 6 ++
 2 files changed, 13 insertions(+)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c 
b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index c478997..0201b54 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -88,11 +88,18 @@ static void exynos_crtc_atomic_begin(struct drm_crtc *crtc,
WARN_ON(drm_crtc_vblank_get(crtc) != 0);
exynos_crtc->event = crtc->state->event;
}
+
+   if (exynos_crtc->ops->atomic_begin)
+   exynos_crtc->ops->atomic_begin(exynos_crtc);
 }

 static void exynos_crtc_atomic_flush(struct drm_crtc *crtc,
 struct drm_crtc_state *old_crtc_state)
 {
+   struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+
+   if (exynos_crtc->ops->atomic_flush)
+   exynos_crtc->ops->atomic_flush(exynos_crtc);
 }

 static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h 
b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index 6b8a30f..887922d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -95,6 +95,10 @@ struct exynos_drm_plane {
  * called from exynos-dp driver before powering up (with
  * 'enable' argument as true) and after powering down (with
  * 'enable' as false).
+ * @atomic_begin: stop the changes in the CRTC shadow registers to being
+ * updated the CRTC active registers
+ * @atomic_flush: start the changes in the CRTC shadow registers to being
+ * updated the CRTC active registers
  */
 struct exynos_drm_crtc;
 struct exynos_drm_crtc_ops {
@@ -113,6 +117,8 @@ struct exynos_drm_crtc_ops {
  struct exynos_drm_plane *plane);
void (*te_handler)(struct exynos_drm_crtc *crtc);
void (*clock_enable)(struct exynos_drm_crtc *crtc, bool enable);
+   void (*atomic_begin)(struct exynos_drm_crtc *crtc);
+   void (*atomic_flush)(struct exynos_drm_crtc *crtc);
 };

 /*
-- 
2.4.3



[PATCH 2/2] drm/exynos: implement atomic_{begin/flush} of FIMD and DECON

2015-08-20 Thread Hyungwon Hwang
Each CRTC's atomic_{begin/flush} must stop/start the update of shadow
registers to active register in the functions. This patch achieves these
purpose by moving the setting of protection bits to those functions from
{fimd/decon}_update_plane.

Signed-off-by: Hyungwon Hwang 
---
 drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 47 +---
 drivers/gpu/drm/exynos/exynos7_drm_decon.c| 47 
 drivers/gpu/drm/exynos/exynos_drm_fimd.c  | 51 ++-
 3 files changed, 103 insertions(+), 42 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c 
b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
index 484e312..fef0333 100644
--- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
@@ -31,6 +31,7 @@ struct decon_context {
struct drm_device   *drm_dev;
struct exynos_drm_crtc  *crtc;
struct exynos_drm_plane planes[WINDOWS_NR];
+   unsigned intupdated_plane;
void __iomem*addr;
struct clk  *clks[6];
unsigned intdefault_win;
@@ -204,17 +205,17 @@ static void decon_win_set_pixfmt(struct decon_context 
*ctx, unsigned int win,
writel(val, ctx->addr + DECON_WINCONx(win));
 }

-static void decon_shadow_protect_win(struct decon_context *ctx, int win,
-   bool protect)
+static void decon_shadow_protect_win(struct decon_context *ctx,
+   unsigned int win_bits, bool protect)
 {
u32 val;

val = readl(ctx->addr + DECON_SHADOWCON);

if (protect)
-   val |= SHADOWCON_Wx_PROTECT(win);
+   val |= win_bits;
else
-   val &= ~SHADOWCON_Wx_PROTECT(win);
+   val &= ~win_bits;

writel(val, ctx->addr + DECON_SHADOWCON);
 }
@@ -232,8 +233,6 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
if (ctx->suspended)
return;

-   decon_shadow_protect_win(ctx, win, true);
-
val = COORDINATE_X(plane->crtc_x) | COORDINATE_Y(plane->crtc_y);
writel(val, ctx->addr + DECON_VIDOSDxA(win));

@@ -265,15 +264,12 @@ static void decon_update_plane(struct exynos_drm_crtc 
*crtc,
val |= WINCONx_ENWIN_F;
writel(val, ctx->addr + DECON_WINCONx(win));

-   decon_shadow_protect_win(ctx, win, false);
-
/* standalone update */
val = readl(ctx->addr + DECON_UPDATE);
val |= STANDALONE_UPDATE_F;
writel(val, ctx->addr + DECON_UPDATE);

-   if (ctx->i80_if)
-   atomic_set(&ctx->win_updated, 1);
+   ctx->updated_plane |= SHADOWCON_Wx_PROTECT(win);
 }

 static void decon_disable_plane(struct exynos_drm_crtc *crtc,
@@ -286,14 +282,14 @@ static void decon_disable_plane(struct exynos_drm_crtc 
*crtc,
if (ctx->suspended)
return;

-   decon_shadow_protect_win(ctx, win, true);
+   decon_shadow_protect_win(ctx, SHADOWCON_Wx_PROTECT(win), true);

/* window disable */
val = readl(ctx->addr + DECON_WINCONx(win));
val &= ~WINCONx_ENWIN_F;
writel(val, ctx->addr + DECON_WINCONx(win));

-   decon_shadow_protect_win(ctx, win, false);
+   decon_shadow_protect_win(ctx, SHADOWCON_Wx_PROTECT(win), false);

/* standalone update */
val = readl(ctx->addr + DECON_UPDATE);
@@ -405,6 +401,31 @@ void decon_te_irq_handler(struct exynos_drm_crtc *crtc)
drm_crtc_handle_vblank(&ctx->crtc->base);
 }

+static void decon_begin(struct exynos_drm_crtc *crtc)
+{
+   struct decon_context *ctx = crtc->ctx;
+   int i;
+   unsigned int val = 0;
+
+   for (i = 0; i < WINDOWS_NR; i++)
+   val |= SHADOWCON_Wx_PROTECT(i);
+
+   /* protect windows */
+   decon_shadow_protect_win(ctx, val, true);
+}
+
+static void decon_flush(struct exynos_drm_crtc *crtc)
+{
+   struct decon_context *ctx = crtc->ctx;
+
+   if (ctx->updated_plane) {
+   decon_shadow_protect_win(ctx, ctx->updated_plane, false);
+
+   if (ctx->i80_if)
+   atomic_set(&ctx->win_updated, 1);
+   }
+}
+
 static void decon_clear_channels(struct exynos_drm_crtc *crtc)
 {
struct decon_context *ctx = crtc->ctx;
@@ -458,6 +479,8 @@ static struct exynos_drm_crtc_ops decon_crtc_ops = {
.update_plane   = decon_update_plane,
.disable_plane  = decon_disable_plane,
.te_handler = decon_te_irq_handler,
+   .atomic_begin   = decon_begin,
+   .atomic_flush   = decon_flush,
 };

 static int decon_bind(struct device *dev, struct device *master, void *data)
diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c 
b/drivers/gpu/drm/exynos/ex

[PATCH 2/6] xf86drmMode: separate drmModeAtomicCommit() and drmModeAtomicCleanup()

2015-08-21 Thread Hyungwon Hwang
Hi Emil,

On Thu, 20 Aug 2015 17:17:27 +0100
Emil Velikov  wrote:

> Hi Hyungwon,
> 
> On 19 August 2015 at 01:58, Hyungwon Hwang 
> wrote:
> > This patch seprates the code, which sorts proprty sets and
> > eliminates duplicate properties, from drmModeAtomicCommit(). Now
> > drmModeAtomicCleanup() has to do the job before calling
> > drmModeAtomicCommit(), and drmModeAtomicCommit() just converts the
> > cleaned request to IOCTL argument.
> >
> Afaict the commit message should say why we want this, rather than
> rewording what the patch does.
> 
> I'm not sure about the atomic status for wayland and others but this
> commit might cause issues there. Additionally, with this patch we'll
> send a lot of useless information to the kernel if one omits
> drmModeAtomicCleanup(). The kernel will likely discard it but still
> this doesn't seem like a good idea imho.

Yes. I agree that this change burdens the userspace application to use
API correctly. In my case, for modetest, the function of cleaning up
the request is needed, so I thought that this separation would be
needed. Overall, I agree with you. So I will drop this patch, and find
another way which is specific for modetest.

Thanks for your review.

Best regards,
Hyungwon Hwang

> 
> -Emil



[PATCH 3/6] xf86drmMode: Make atomic request structures visible

2015-08-21 Thread Hyungwon Hwang
Hi Emil,

On Thu, 20 Aug 2015 17:23:09 +0100
Emil Velikov  wrote:

> On 19 August 2015 at 01:58, Hyungwon Hwang 
> wrote:
> > This patch makes 'struct _drmModeAtomicReqItem' and 'struct
> > _drmModeAtomicReq' visible from outside. This is needed for
> > userspace applications to use those structures when calling
> > drmModeAtomicCommit().
> >
> Hmmm what is missing in the current API, that one needs direct access
> to the structs ? If we expose these to the user we'll be putting a
> (ABI) hedgehog down our pants (i.e. it might be ok, but will likely
> result in a very painful experience).

I also agree with you. I think I should drop this patch, and find
another way for modetest.

Thanks.

Best regards,
Hyungwon Hwang

> 
> Thanks
> Emil



[PATCH 2/6] xf86drmMode: separate drmModeAtomicCommit() and drmModeAtomicCleanup()

2015-08-21 Thread Hyungwon Hwang
Hi Pekka,

On Fri, 21 Aug 2015 09:42:26 +0300
Pekka Paalanen  wrote:

> On Fri, 21 Aug 2015 13:54:49 +0900
> Hyungwon Hwang  wrote:
> 
> > Hi Emil,
> > 
> > On Thu, 20 Aug 2015 17:17:27 +0100
> > Emil Velikov  wrote:
> > 
> > > Hi Hyungwon,
> > > 
> > > On 19 August 2015 at 01:58, Hyungwon Hwang
> > >  wrote:
> > > > This patch seprates the code, which sorts proprty sets and
> > > > eliminates duplicate properties, from drmModeAtomicCommit(). Now
> > > > drmModeAtomicCleanup() has to do the job before calling
> > > > drmModeAtomicCommit(), and drmModeAtomicCommit() just converts
> > > > the cleaned request to IOCTL argument.
> > > >
> > > Afaict the commit message should say why we want this, rather than
> > > rewording what the patch does.
> > > 
> > > I'm not sure about the atomic status for wayland and others but
> > > this commit might cause issues there. Additionally, with this
> > > patch we'll send a lot of useless information to the kernel if
> > > one omits drmModeAtomicCleanup(). The kernel will likely discard
> > > it but still this doesn't seem like a good idea imho.
> > 
> > Yes. I agree that this change burdens the userspace application to
> > use API correctly. In my case, for modetest, the function of
> > cleaning up the request is needed, so I thought that this
> > separation would be needed. Overall, I agree with you. So I will
> > drop this patch, and find another way which is specific for
> > modetest.
> 
> Hi,
> 
> why do you need that, exactly?

To make the buffer for plane, I needed to figure out the width and the
height which the user set which are in the request, but not applied to
the kernel yet. To get the value from the request, I thought cleaning
the request before I try to getting the value from the request was
needed because the user could set the different values for the same
property.

> 
> 
> Thanks,
> pq



[PATCH 3/6] xf86drmMode: Make atomic request structures visible

2015-08-21 Thread Hyungwon Hwang
Dear,

On Fri, 21 Aug 2015 09:44:42 +0300
Pekka Paalanen  wrote:

> On Fri, 21 Aug 2015 15:06:58 +0900
> Hyungwon Hwang  wrote:
> 
> > Hi Emil,
> > 
> > On Thu, 20 Aug 2015 17:23:09 +0100
> > Emil Velikov  wrote:
> > 
> > > On 19 August 2015 at 01:58, Hyungwon Hwang
> > >  wrote:
> > > > This patch makes 'struct _drmModeAtomicReqItem' and 'struct
> > > > _drmModeAtomicReq' visible from outside. This is needed for
> > > > userspace applications to use those structures when calling
> > > > drmModeAtomicCommit().
> 
> Yeah, this sounds like a very bad idea.

Yes. Making it visible was not good. But then I think that new API for
getting the value of a request item in the request which are not
applied to the kernel. Because for preparing the buffer, the userspace
program needs width and height which are in the request.

The program can get the value before making it as a request. In that
case, the program such as modetest, which does not understand what the
object id or propery id means, have to be modified to understand them
for extracting the needed value.

How do you think about it? Is modetest just a special program for
testing, and is this support not needed for another real program?

> 
> 
> Thanks,
> pq
> 
> > > >
> > > Hmmm what is missing in the current API, that one needs direct
> > > access to the structs ? If we expose these to the user we'll be
> > > putting a (ABI) hedgehog down our pants (i.e. it might be ok, but
> > > will likely result in a very painful experience).
> > 
> > I also agree with you. I think I should drop this patch, and find
> > another way for modetest.



[PATCH 3/3] modetest: add atomic page flip support

2015-08-26 Thread Hyungwon Hwang
This patch adds support for atomic page flip. User can specify -V option
with the plane id for testing atomic page flipping.
---
 tests/modetest/modetest.c | 153 --
 1 file changed, 149 insertions(+), 4 deletions(-)

diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
index 753a559..9bffa98 100644
--- a/tests/modetest/modetest.c
+++ b/tests/modetest/modetest.c
@@ -719,6 +719,10 @@ struct pipe_arg {
struct timeval start;

int swap_count;
+
+   /* for atomic modeset */
+   uint32_t plane_id;
+   uint32_t fb_obj_id;
 };

 struct plane_arg {
@@ -1444,7 +1448,7 @@ static int parse_property(struct property_arg *p, const 
char *arg)

 static void usage(char *name)
 {
-   fprintf(stderr, "usage: %s [-acDdefMPpsCvw]\n", name);
+   fprintf(stderr, "usage: %s [-acDdefMPpsCvVw]\n", name);
fprintf(stderr, "\tA: supported in atomic modeset\n");
fprintf(stderr, "\tL: supported in legacy modeset\n");

@@ -1459,6 +1463,7 @@ static void usage(char *name)

fprintf(stderr, "\n Atomic Test options: [A]\n\n");
fprintf(stderr, "\t-a\tuse atomic modeset\n");
+   fprintf(stderr, "\t-V \ttest vsynced page 
flipping\n");

fprintf(stderr, "\n Legacy test options: [L]\n\n");
fprintf(stderr, "\t-P 
:x[++][*][@]\tset a plane\n");
@@ -1627,7 +1632,138 @@ static void atomic_modeset(struct device *dev, 
drmModeAtomicReqPtr req,
drmModeAtomicCommit(dev->fd, req, flags, NULL);
 }

-static char optstr[] = "acdD:efM:P:ps:Cvw:";
+static void
+atomic_page_flip_handler(int fd, unsigned int frame,
+   unsigned int sec, unsigned int usec, void *data)
+{
+   static drmModeAtomicReqPtr req = NULL;
+   unsigned int new_fb_id;
+   struct timeval end;
+   struct pipe_arg *pipe;
+   double t;
+   uint32_t flags = 0;
+
+   pipe = (struct pipe_arg *)(unsigned long)data;
+
+   if (pipe->current_fb_id == pipe->fb_id[0])
+   new_fb_id = pipe->fb_id[1];
+   else
+   new_fb_id = pipe->fb_id[0];
+
+   pipe->current_fb_id = new_fb_id;
+   pipe->swap_count++;
+
+   req = drmModeAtomicAlloc();
+
+   drmModeAtomicAddProperty(req, pipe->plane_id, pipe->fb_obj_id, 
new_fb_id);
+
+   flags = DRM_MODE_PAGE_FLIP_EVENT;
+   drmModeAtomicCommit(fd, req, flags, pipe);
+
+   if (pipe->swap_count == 60) {
+   gettimeofday(&end, NULL);
+   t = end.tv_sec + end.tv_usec * 1e-6 -
+   (pipe->start.tv_sec + pipe->start.tv_usec * 1e-6);
+   fprintf(stderr, "freq: %.02fHz\n", pipe->swap_count / t);
+   pipe->swap_count = 0;
+   pipe->start = end;
+   }
+
+   drmModeAtomicFree(req);
+}
+
+static int atomic_test_page_flip(struct device *dev, drmModeAtomicReqPtr req,
+   struct resources *res, struct property_arg *prop_args,
+   unsigned int prop_count,unsigned int plane_id)
+{
+   struct bo *other_bo;
+   unsigned int other_fb_id;
+   struct pipe_arg *pipe = NULL;
+   drmEventContext evctx;
+   uint32_t flags = 0, fb_obj_id = 0, pixel_format;
+   uint64_t width, height;
+   int ret;
+
+   if (!is_obj_id_in_prop_args(prop_args, prop_count, plane_id))
+   return -1;
+
+   fb_obj_id = get_atomic_plane_prop_id(res, plane_id, "FB_ID");
+   if (!fb_obj_id)
+   return -1;
+
+   width = get_value_in_prop_args(prop_args, prop_count, plane_id,
+   "SRC_W");
+   height = get_value_in_prop_args(prop_args, prop_count, plane_id,
+   "SRC_H");
+   pixel_format = DRM_FORMAT_XRGB;
+
+   ret = allocate_fb(dev, req, res, width, height, pixel_format,
+   PATTERN_TILES, &other_bo, &other_fb_id);
+   if (ret < 0)
+   return ret;
+
+   ret = drmModeAtomicAddProperty(req, plane_id, fb_obj_id,
+   other_fb_id);
+   if (ret < 0)
+   goto err;
+
+   if (!fb_obj_id) {
+   fprintf(stderr, "page flipping requires at least one plane 
setting.\n");
+   return -1;
+   }
+
+   pipe = drmMalloc(sizeof *pipe);
+
+   gettimeofday(&pipe->start, NULL);
+   pipe->swap_count = 0;
+   pipe->plane_id = plane_id;
+   pipe->fb_obj_id = fb_obj_id;
+   pipe->fb_id[0] = dev->mode.fb_id;
+   pipe->fb_id[1] = other_fb_id;
+   pipe->current_fb_id = other_fb_id;
+
+   flags = DRM_MODE_PAGE_FLIP_EVENT;
+
+   ret = drmModeAtomicCommit(dev->fd, req, flags, pipe);
+   if (ret < 0)
+   goto err_rmfb;
+
+   memset(&evctx, 0, sizeof evctx);
+   evctx.version = DRM_EVENT_CONTEXT_VERSION;
+   evctx.vblank_handler = NULL;
+   evctx.page_flip_handler = atomic_page_flip_handler;
+
+   while (1) {
+   struct timeval timeout = { .tv_sec = 3, .tv_usec = 0 };
+  

[PATCH 1/3] modetest: introduce get_prop_info() for getting property id and type

2015-08-26 Thread Hyungwon Hwang
Modetest gets the property name from user to set it. So the name must be
converted to its id. Until now, this is done in the set_property(). But to
support atomic modeset in modetest, this logic should be separated from the
fuction, because atomic modeset and legacy modeset use different IOCTLs.

Signed-off-by: Hyungwon Hwang 
---
 tests/modetest/modetest.c | 31 +--
 1 file changed, 21 insertions(+), 10 deletions(-)

diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
index 43bd06f..b7f6d32 100644
--- a/tests/modetest/modetest.c
+++ b/tests/modetest/modetest.c
@@ -866,12 +866,11 @@ struct property_arg {
uint64_t value;
 };

-static void set_property(struct device *dev, struct property_arg *p)
+static int get_prop_info(struct resources *resources, struct property_arg *p,
+   char *obj_type)
 {
drmModeObjectProperties *props = NULL;
drmModePropertyRes **props_info = NULL;
-   const char *obj_type;
-   int ret;
int i;

p->obj_type = 0;
@@ -884,27 +883,27 @@ static void set_property(struct device *dev, struct 
property_arg *p)
if (obj->type->type##_id != p->obj_id)  
\
continue;   
\
p->obj_type = DRM_MODE_OBJECT_##Type;   
\
-   obj_type = #Type;   
\
+   obj_type = (char *)#Type;   
\
props = obj->props; 
\
props_info = obj->props_info;   
\
}   
\
} while(0)  
\

-   find_object(dev->resources, res, crtc, CRTC);
+   find_object(resources, res, crtc, CRTC);
if (p->obj_type == 0)
-   find_object(dev->resources, res, connector, CONNECTOR);
+   find_object(resources, res, connector, CONNECTOR);
if (p->obj_type == 0)
-   find_object(dev->resources, plane_res, plane, PLANE);
+   find_object(resources, plane_res, plane, PLANE);
if (p->obj_type == 0) {
fprintf(stderr, "Object %i not found, can't set property\n",
p->obj_id);
-   return;
+   return -1;
}

if (!props) {
fprintf(stderr, "%s %i has no properties\n",
obj_type, p->obj_id);
-   return;
+   return -1;
}

for (i = 0; i < (int)props->count_props; ++i) {
@@ -917,11 +916,23 @@ static void set_property(struct device *dev, struct 
property_arg *p)
if (i == (int)props->count_props) {
fprintf(stderr, "%s %i has no %s property\n",
obj_type, p->obj_id, p->name);
-   return;
+   return -1;
}

p->prop_id = props->props[i];

+   return 0;
+}
+
+static void set_property(struct device *dev, struct property_arg *p)
+{
+   int ret;
+   char *obj_type = NULL;
+
+   ret = get_prop_info(dev->resources, p, obj_type);
+   if (ret < 0)
+   return;
+
ret = drmModeObjectSetProperty(dev->fd, p->obj_id, p->obj_type,
   p->prop_id, p->value);
if (ret < 0)
-- 
2.4.3



[PATCH 2/3] modetest: add atomic modeset support

2015-08-26 Thread Hyungwon Hwang
This patch adds support for atomic modeset. Using -a option, user can
make modeset to use DRM_IOCTL_MODE_ATOMIC instead of legacy IOCTLs.
Also, by using -w option, user can set the property as before.

Signed-off-by: Hyungwon Hwang 
---
 tests/modetest/modetest.c | 221 +++---
 1 file changed, 187 insertions(+), 34 deletions(-)

diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
index b7f6d32..753a559 100644
--- a/tests/modetest/modetest.c
+++ b/tests/modetest/modetest.c
@@ -1444,25 +1444,32 @@ static int parse_property(struct property_arg *p, const 
char *arg)

 static void usage(char *name)
 {
-   fprintf(stderr, "usage: %s [-cDdefMPpsCvw]\n", name);
+   fprintf(stderr, "usage: %s [-acDdefMPpsCvw]\n", name);
+   fprintf(stderr, "\tA: supported in atomic modeset\n");
+   fprintf(stderr, "\tL: supported in legacy modeset\n");

-   fprintf(stderr, "\n Query options:\n\n");
+   fprintf(stderr, "\n Query options: [AL]\n\n");
fprintf(stderr, "\t-c\tlist connectors\n");
fprintf(stderr, "\t-e\tlist encoders\n");
fprintf(stderr, "\t-f\tlist framebuffers\n");
fprintf(stderr, "\t-p\tlist CRTCs and planes (pipes)\n");

-   fprintf(stderr, "\n Test options:\n\n");
+   fprintf(stderr, "\n Common Test options: [AL]\n\n");
+   fprintf(stderr, "\t-w ::\tset property\n");
+
+   fprintf(stderr, "\n Atomic Test options: [A]\n\n");
+   fprintf(stderr, "\t-a\tuse atomic modeset\n");
+
+   fprintf(stderr, "\n Legacy test options: [L]\n\n");
fprintf(stderr, "\t-P 
:x[++][*][@]\tset a plane\n");
fprintf(stderr, "\t-s 
[,][@]:[-][@]\tset 
a mode\n");
fprintf(stderr, "\t-C\ttest hw cursor\n");
fprintf(stderr, "\t-v\ttest vsynced page flipping\n");
-   fprintf(stderr, "\t-w ::\tset property\n");

fprintf(stderr, "\n Generic options:\n\n");
-   fprintf(stderr, "\t-d\tdrop master after mode set\n");
-   fprintf(stderr, "\t-M module\tuse the given driver\n");
-   fprintf(stderr, "\t-D device\tuse the given device\n");
+   fprintf(stderr, "\t-d\tdrop master after mode set [L]\n");
+   fprintf(stderr, "\t-M module\tuse the given driver [AL]\n");
+   fprintf(stderr, "\t-D device\tuse the given device [AL]\n");

fprintf(stderr, "\n\tDefault is to dump all info.\n");
exit(0);
@@ -1495,7 +1502,132 @@ static int cursor_supported(void)
return 1;
 }

-static char optstr[] = "cdD:efM:P:ps:Cvw:";
+static uint32_t is_obj_id_in_prop_args(struct property_arg *prop_args,
+   unsigned int prop_count, uint32_t obj_id)
+{
+   unsigned int i;
+
+   for (i = 0; i < prop_count; i++)
+   if (obj_id == prop_args[i].obj_id)
+   return true;
+
+   return false;
+}
+
+static int get_value_in_prop_args(struct property_arg *prop_args,
+   unsigned int prop_count, uint32_t obj_id,
+   const char *name)
+{
+   unsigned int i;
+
+   for (i = 0; i < prop_count; i++)
+   if (prop_args[i].obj_id == obj_id &&
+   !strcmp(prop_args[i].name, name))
+   return (int)prop_args[i].value;
+
+   return -1;
+}
+
+static uint32_t get_atomic_plane_prop_id(struct resources *res, uint32_t 
obj_id,
+   const char *name)
+{
+   drmModePropertyRes *props_info;
+   struct plane *plane;
+   unsigned int i, j;
+
+   for (i = 0; i < res->plane_res->count_planes; i++) {
+   plane = &res->planes[i];
+   if (plane->plane->plane_id != obj_id)
+   continue;
+
+   for (j = 0; j < plane->props->count_props; j++) {
+   props_info = plane->props_info[j];
+   if (!strcmp(props_info->name, name))
+   return props_info->prop_id;
+   }
+   }
+
+   return 0;
+}
+
+static int allocate_fb(struct device *dev, drmModeAtomicReqPtr req, struct 
resources *res,
+   uint32_t width, uint32_t height, uint32_t pixel_format,
+   int pattern, struct bo **bo, uint32_t *fb_id)
+{
+   uint32_t handles[4] = {0}, pitches[4] = {0}, offsets[4] = {0};
+   int ret;
+
+   *bo = bo_create(dev->fd, pixel_format, width, height,
+   handles, pitches, offsets, pattern);
+   if (*bo == NULL) {
+   fprintf(stderr, "failed to create bo (%ux%u): %s\n",
+  

[PATCH] drm/exynos: implement {prepare/cleanup}_plane of DECON

2015-08-27 Thread Hyungwon Hwang
Each CRTC's {prepare/cleanup}_plane must stop/start the update of shadow
registers to active register in the functions. This patch achieves these
purpose by moving the setting of protection bits to those functions from
decon_update_plane.

Signed-off-by: Hyungwon Hwang 
---
 drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 34 +--
 drivers/gpu/drm/exynos/exynos7_drm_decon.c| 30 ++-
 2 files changed, 51 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c 
b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
index 8d65e45..bd465ac 100644
--- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
@@ -219,6 +219,17 @@ static void decon_shadow_protect_win(struct decon_context 
*ctx, int win,
writel(val, ctx->addr + DECON_SHADOWCON);
 }

+static void decon_prepare_plane(struct exynos_drm_crtc *crtc,
+   struct exynos_drm_plane *plane)
+{
+   struct decon_context *ctx = crtc->ctx;
+
+   if (ctx->suspended)
+   return;
+
+   decon_shadow_protect_win(ctx, plane->zpos, true);
+}
+
 static void decon_update_plane(struct exynos_drm_crtc *crtc,
   struct exynos_drm_plane *plane)
 {
@@ -232,8 +243,6 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
if (ctx->suspended)
return;

-   decon_shadow_protect_win(ctx, win, true);
-
val = COORDINATE_X(plane->crtc_x) | COORDINATE_Y(plane->crtc_y);
writel(val, ctx->addr + DECON_VIDOSDxA(win));

@@ -265,15 +274,10 @@ static void decon_update_plane(struct exynos_drm_crtc 
*crtc,
val |= WINCONx_ENWIN_F;
writel(val, ctx->addr + DECON_WINCONx(win));

-   decon_shadow_protect_win(ctx, win, false);
-
/* standalone update */
val = readl(ctx->addr + DECON_UPDATE);
val |= STANDALONE_UPDATE_F;
writel(val, ctx->addr + DECON_UPDATE);
-
-   if (ctx->i80_if)
-   atomic_set(&ctx->win_updated, 1);
 }

 static void decon_disable_plane(struct exynos_drm_crtc *crtc,
@@ -301,6 +305,20 @@ static void decon_disable_plane(struct exynos_drm_crtc 
*crtc,
writel(val, ctx->addr + DECON_UPDATE);
 }

+static void decon_cleanup_plane(struct exynos_drm_crtc *crtc,
+   struct exynos_drm_plane *plane)
+{
+   struct decon_context *ctx = crtc->ctx;
+
+   if (ctx->suspended)
+   return;
+
+   decon_shadow_protect_win(ctx, plane->zpos, false);
+
+   if (ctx->i80_if)
+   atomic_set(&ctx->win_updated, 1);
+}
+
 static void decon_swreset(struct decon_context *ctx)
 {
unsigned int tries;
@@ -455,8 +473,10 @@ static struct exynos_drm_crtc_ops decon_crtc_ops = {
.enable_vblank  = decon_enable_vblank,
.disable_vblank = decon_disable_vblank,
.commit = decon_commit,
+   .prepare_plane  = decon_prepare_plane,
.update_plane   = decon_update_plane,
.disable_plane  = decon_disable_plane,
+   .cleanup_plane  = decon_cleanup_plane,
.te_handler = decon_te_irq_handler,
 };

diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c 
b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
index 7651499..d0edc56 100644
--- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
@@ -383,6 +383,17 @@ static void decon_shadow_protect_win(struct decon_context 
*ctx,
writel(val, ctx->regs + SHADOWCON);
 }

+static void decon_prepare_plane(struct exynos_drm_crtc *crtc,
+   struct exynos_drm_plane *plane)
+{
+   struct decon_context *ctx = crtc->ctx;
+
+   if (ctx->suspended)
+   return;
+
+   decon_shadow_protect_win(ctx, plane->zpos, true);
+}
+
 static void decon_update_plane(struct exynos_drm_crtc *crtc,
   struct exynos_drm_plane *plane)
 {
@@ -410,9 +421,6 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
 * is set.
 */

-   /* protect windows */
-   decon_shadow_protect_win(ctx, win, true);
-
/* buffer start address */
val = (unsigned long)plane->dma_addr[0];
writel(val, ctx->regs + VIDW_BUF_START(win));
@@ -510,14 +518,22 @@ static void decon_disable_plane(struct exynos_drm_crtc 
*crtc,
val &= ~WINCONx_ENWIN;
writel(val, ctx->regs + WINCON(win));

-   /* unprotect windows */
-   decon_shadow_protect_win(ctx, win, false);
-
val = readl(ctx->regs + DECON_UPDATE);
val |= DECON_UPDATE_STANDALONE_F;
writel(val, ctx->regs + DECON_UPDATE);
 }

+static void decon_cleanup_plane(struct exynos_drm_crtc *crtc,
+   struct ex

[PATCH v2] drm/exynos: implement atomic_{begin/flush} of DECON

2015-08-27 Thread Hyungwon Hwang
Each CRTC's atomic_{begin/flush} must stop/start the update of shadow
registers to active register in the functions. This patch achieves these
purpose by moving the setting of protection bits to those functions from
decon_update_plane.

v2: rebased to the branch exynos-drm-next

Signed-off-by: Hyungwon Hwang 
---
 drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 34 +--
 drivers/gpu/drm/exynos/exynos7_drm_decon.c| 30 ++-
 2 files changed, 51 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c 
b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
index 8d65e45..f24dc2d 100644
--- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
@@ -219,6 +219,17 @@ static void decon_shadow_protect_win(struct decon_context 
*ctx, int win,
writel(val, ctx->addr + DECON_SHADOWCON);
 }

+static void decon_atomic_begin(struct exynos_drm_crtc *crtc,
+   struct exynos_drm_plane *plane)
+{
+   struct decon_context *ctx = crtc->ctx;
+
+   if (ctx->suspended)
+   return;
+
+   decon_shadow_protect_win(ctx, plane->zpos, true);
+}
+
 static void decon_update_plane(struct exynos_drm_crtc *crtc,
   struct exynos_drm_plane *plane)
 {
@@ -232,8 +243,6 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
if (ctx->suspended)
return;

-   decon_shadow_protect_win(ctx, win, true);
-
val = COORDINATE_X(plane->crtc_x) | COORDINATE_Y(plane->crtc_y);
writel(val, ctx->addr + DECON_VIDOSDxA(win));

@@ -265,15 +274,10 @@ static void decon_update_plane(struct exynos_drm_crtc 
*crtc,
val |= WINCONx_ENWIN_F;
writel(val, ctx->addr + DECON_WINCONx(win));

-   decon_shadow_protect_win(ctx, win, false);
-
/* standalone update */
val = readl(ctx->addr + DECON_UPDATE);
val |= STANDALONE_UPDATE_F;
writel(val, ctx->addr + DECON_UPDATE);
-
-   if (ctx->i80_if)
-   atomic_set(&ctx->win_updated, 1);
 }

 static void decon_disable_plane(struct exynos_drm_crtc *crtc,
@@ -301,6 +305,20 @@ static void decon_disable_plane(struct exynos_drm_crtc 
*crtc,
writel(val, ctx->addr + DECON_UPDATE);
 }

+static void decon_atomic_flush(struct exynos_drm_crtc *crtc,
+   struct exynos_drm_plane *plane)
+{
+   struct decon_context *ctx = crtc->ctx;
+
+   if (ctx->suspended)
+   return;
+
+   decon_shadow_protect_win(ctx, plane->zpos, false);
+
+   if (ctx->i80_if)
+   atomic_set(&ctx->win_updated, 1);
+}
+
 static void decon_swreset(struct decon_context *ctx)
 {
unsigned int tries;
@@ -455,8 +473,10 @@ static struct exynos_drm_crtc_ops decon_crtc_ops = {
.enable_vblank  = decon_enable_vblank,
.disable_vblank = decon_disable_vblank,
.commit = decon_commit,
+   .atomic_begin   = decon_atomic_begin,
.update_plane   = decon_update_plane,
.disable_plane  = decon_disable_plane,
+   .atomic_flush   = decon_atomic_flush,
.te_handler = decon_te_irq_handler,
 };

diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c 
b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
index 7651499..c74e30e 100644
--- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
@@ -383,6 +383,17 @@ static void decon_shadow_protect_win(struct decon_context 
*ctx,
writel(val, ctx->regs + SHADOWCON);
 }

+static void decon_atomic_begin(struct exynos_drm_crtc *crtc,
+   struct exynos_drm_plane *plane)
+{
+   struct decon_context *ctx = crtc->ctx;
+
+   if (ctx->suspended)
+   return;
+
+   decon_shadow_protect_win(ctx, plane->zpos, true);
+}
+
 static void decon_update_plane(struct exynos_drm_crtc *crtc,
   struct exynos_drm_plane *plane)
 {
@@ -410,9 +421,6 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc,
 * is set.
 */

-   /* protect windows */
-   decon_shadow_protect_win(ctx, win, true);
-
/* buffer start address */
val = (unsigned long)plane->dma_addr[0];
writel(val, ctx->regs + VIDW_BUF_START(win));
@@ -510,14 +518,22 @@ static void decon_disable_plane(struct exynos_drm_crtc 
*crtc,
val &= ~WINCONx_ENWIN;
writel(val, ctx->regs + WINCON(win));

-   /* unprotect windows */
-   decon_shadow_protect_win(ctx, win, false);
-
val = readl(ctx->regs + DECON_UPDATE);
val |= DECON_UPDATE_STANDALONE_F;
writel(val, ctx->regs + DECON_UPDATE);
 }

+static void decon_atomic_flush(struct exynos_drm_crtc *crtc,
+  

[PATCH 2/2] exynos: remove DRM_EXYNOS_GEM_{MAP_OFFSET/MMAP} ioctls

2014-10-31 Thread Hyungwon Hwang
This patch removes the ioctls which are removed from the linux kernel.

Signed-off-by: Hyungwon Hwang 
---
 exynos/exynos_drm.h | 40 
 1 file changed, 40 deletions(-)

diff --git a/exynos/exynos_drm.h b/exynos/exynos_drm.h
index c3c6579..256c02f 100644
--- a/exynos/exynos_drm.h
+++ b/exynos/exynos_drm.h
@@ -47,38 +47,6 @@ struct drm_exynos_gem_create {
 };

 /**
- * A structure for getting buffer offset.
- *
- * @handle: a pointer to gem object created.
- * @pad: just padding to be 64-bit aligned.
- * @offset: relatived offset value of the memory region allocated.
- * - this value should be set by user.
- */
-struct drm_exynos_gem_map_off {
-   unsigned int handle;
-   unsigned int pad;
-   uint64_t offset;
-};
-
-/**
- * A structure for mapping buffer.
- *
- * @handle: a handle to gem object created.
- * @pad: just padding to be 64-bit aligned.
- * @size: memory size to be mapped.
- * @mapped: having user virtual address mmaped.
- * - this variable would be filled by exynos gem module
- * of kernel side with user virtual address which is allocated
- * by do_mmap().
- */
-struct drm_exynos_gem_mmap {
-   unsigned int handle;
-   unsigned int pad;
-   uint64_t size;
-   uint64_t mapped;
-};
-
-/**
  * A structure to gem information.
  *
  * @handle: a handle to gem object created.
@@ -164,8 +132,6 @@ struct drm_exynos_g2d_exec {
 };

 #define DRM_EXYNOS_GEM_CREATE  0x00
-#define DRM_EXYNOS_GEM_MAP_OFFSET  0x01
-#define DRM_EXYNOS_GEM_MMAP0x02
 /* Reserved 0x04 ~ 0x05 for exynos specific gem ioctl */
 #define DRM_EXYNOS_GEM_GET 0x04
 #define DRM_EXYNOS_VIDI_CONNECTION 0x07
@@ -178,12 +144,6 @@ struct drm_exynos_g2d_exec {
 #define DRM_IOCTL_EXYNOS_GEM_CREATEDRM_IOWR(DRM_COMMAND_BASE + \
DRM_EXYNOS_GEM_CREATE, struct drm_exynos_gem_create)

-#define DRM_IOCTL_EXYNOS_GEM_MAP_OFFSETDRM_IOWR(DRM_COMMAND_BASE + \
-   DRM_EXYNOS_GEM_MAP_OFFSET, struct drm_exynos_gem_map_off)
-
-#define DRM_IOCTL_EXYNOS_GEM_MMAP  DRM_IOWR(DRM_COMMAND_BASE + \
-   DRM_EXYNOS_GEM_MMAP, struct drm_exynos_gem_mmap)
-
 #define DRM_IOCTL_EXYNOS_GEM_GET   DRM_IOWR(DRM_COMMAND_BASE + \
DRM_EXYNOS_GEM_GET, struct drm_exynos_gem_info)

-- 
1.8.3.2



[PATCH 1/2] exynos: Don't use DRM_EXYNOS_GEM_{MAP_OFFSET/MMAP} ioctls

2014-10-31 Thread Hyungwon Hwang
The ioctl DRM_EXYNOS_GEM_MAP_OFFSET and DRM_EXYNOS_GEM_MMAP are removed from
the linux kernel. This patch modifies libdrm and libkms to use drm generic
ioctls instead of the removed ioctls.

Signed-off-by: Hyungwon Hwang 
---
 exynos/exynos_drm.c | 24 +---
 libkms/exynos.c |  7 ---
 2 files changed, 17 insertions(+), 14 deletions(-)

diff --git a/exynos/exynos_drm.c b/exynos/exynos_drm.c
index 4c7dd13..4cb6a6d 100644
--- a/exynos/exynos_drm.c
+++ b/exynos/exynos_drm.c
@@ -283,20 +283,22 @@ drm_public void *exynos_bo_map(struct exynos_bo *bo)
 {
if (!bo->vaddr) {
struct exynos_device *dev = bo->dev;
-   struct drm_exynos_gem_mmap req = {
-   .handle = bo->handle,
-   .size   = bo->size,
-   };
+   struct drm_mode_map_dumb arg;
+   void *map = NULL;
int ret;

-   ret = drmIoctl(dev->fd, DRM_IOCTL_EXYNOS_GEM_MMAP, &req);
-   if (ret) {
-   fprintf(stderr, "failed to mmap[%s].\n",
-   strerror(errno));
-   return NULL;
-   }
+   memset(&arg, 0, sizeof(arg));
+   arg.handle = bo->handle;
+
+   ret = drmIoctl(dev->fd, DRM_IOCTL_MODE_MAP_DUMB, &arg);
+   if (ret)
+   return ret;

-   bo->vaddr = (void *)(uintptr_t)req.mapped;
+   map = drm_mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
+   dev->fd, arg.offset);
+
+   if (map == MAP_FAILED)
+   return NULL;
}

return bo->vaddr;
diff --git a/libkms/exynos.c b/libkms/exynos.c
index 92e329c..1123482 100644
--- a/libkms/exynos.c
+++ b/libkms/exynos.c
@@ -25,6 +25,7 @@
 #include 
 #include "xf86drm.h"

+#include "libdrm.h"
 #include "exynos_drm.h"

 struct exynos_bo
@@ -124,7 +125,7 @@ static int
 exynos_bo_map(struct kms_bo *_bo, void **out)
 {
struct exynos_bo *bo = (struct exynos_bo *)_bo;
-   struct drm_exynos_gem_map_off arg;
+   struct drm_mode_map_dumb arg;
void *map = NULL;
int ret;

@@ -137,11 +138,11 @@ exynos_bo_map(struct kms_bo *_bo, void **out)
memset(&arg, 0, sizeof(arg));
arg.handle = bo->base.handle;

-   ret = drmCommandWriteRead(bo->base.kms->fd, DRM_EXYNOS_GEM_MAP_OFFSET, 
&arg, sizeof(arg));
+   ret = drmIoctl(bo->base.kms->fd, DRM_IOCTL_MODE_MAP_DUMB, &arg);
if (ret)
return ret;

-   map = mmap(0, bo->base.size, PROT_READ | PROT_WRITE, MAP_SHARED, 
bo->base.kms->fd, arg.offset);
+   map = drm_mmap(0, bo->base.size, PROT_READ | PROT_WRITE, MAP_SHARED, 
bo->base.kms->fd, arg.offset);
if (map == MAP_FAILED)
return -errno;

-- 
1.8.3.2



[PATCH] drm/exynos: dsi: remove the empty mode_valid callback

2015-04-02 Thread Hyungwon Hwang
Because the helper function which calls this callback checks whether
it is registered or not. It is not necessary if it does nothing.
So it would be better to remove the function for clarity.

Signed-off-by: Hyungwon Hwang 
---
 drivers/gpu/drm/exynos/exynos_drm_dsi.c | 7 ---
 1 file changed, 7 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c 
b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 05fe93d..0492715 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -1473,12 +1473,6 @@ static int exynos_dsi_get_modes(struct drm_connector 
*connector)
return 0;
 }

-static int exynos_dsi_mode_valid(struct drm_connector *connector,
-struct drm_display_mode *mode)
-{
-   return MODE_OK;
-}
-
 static struct drm_encoder *
 exynos_dsi_best_encoder(struct drm_connector *connector)
 {
@@ -1489,7 +1483,6 @@ exynos_dsi_best_encoder(struct drm_connector *connector)

 static struct drm_connector_helper_funcs exynos_dsi_connector_helper_funcs = {
.get_modes = exynos_dsi_get_modes,
-   .mode_valid = exynos_dsi_mode_valid,
.best_encoder = exynos_dsi_best_encoder,
 };

-- 
1.9.1



[PATCH 3/3] modetest: add atomic page flip support

2015-09-23 Thread Hyungwon Hwang
Dear Emil,

On Wed, 02 Sep 2015 01:43:41 +0100
Emil Velikov  wrote:

> On 26 August 2015 at 07:21, Hyungwon Hwang 
> wrote:
> > This patch adds support for atomic page flip. User can specify -V
> > option with the plane id for testing atomic page flipping.
> > ---
> >  tests/modetest/modetest.c | 153
> > -- 1 file changed, 149
> > insertions(+), 4 deletions(-)
> >
> > diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
> > index 753a559..9bffa98 100644
> > --- a/tests/modetest/modetest.c
> > +++ b/tests/modetest/modetest.c
> > @@ -719,6 +719,10 @@ struct pipe_arg {
> > struct timeval start;
> >
> > int swap_count;
> > +
> > +   /* for atomic modeset */
> > +   uint32_t plane_id;
> > +   uint32_t fb_obj_id;
> >  };
> >
> >  struct plane_arg {
> > @@ -1444,7 +1448,7 @@ static int parse_property(struct property_arg
> > *p, const char *arg)
> >
> >  static void usage(char *name)
> >  {
> > -   fprintf(stderr, "usage: %s [-acDdefMPpsCvw]\n", name);
> > +   fprintf(stderr, "usage: %s [-acDdefMPpsCvVw]\n", name);
> > fprintf(stderr, "\tA: supported in atomic modeset\n");
> > fprintf(stderr, "\tL: supported in legacy modeset\n");
> >
> > @@ -1459,6 +1463,7 @@ static void usage(char *name)
> >
> > fprintf(stderr, "\n Atomic Test options: [A]\n\n");
> > fprintf(stderr, "\t-a\tuse atomic modeset\n");
> > +   fprintf(stderr, "\t-V \ttest vsynced
> > page flipping\n");
> >
> > fprintf(stderr, "\n Legacy test options: [L]\n\n");
> > fprintf(stderr, "\t-P
> > :x[++][*][@]\tset a plane\n");
> > @@ -1627,7 +1632,138 @@ static void atomic_modeset(struct device
> > *dev, drmModeAtomicReqPtr req, drmModeAtomicCommit(dev->fd, req,
> > flags, NULL); }
> >
> > -static char optstr[] = "acdD:efM:P:ps:Cvw:";
> > +static void
> > +atomic_page_flip_handler(int fd, unsigned int frame,
> > +   unsigned int sec, unsigned int usec, void *data)
> > +{
> > +   static drmModeAtomicReqPtr req = NULL;
> > +   unsigned int new_fb_id;
> > +   struct timeval end;
> > +   struct pipe_arg *pipe;
> > +   double t;
> > +   uint32_t flags = 0;
> > +
> > +   pipe = (struct pipe_arg *)(unsigned long)data;
> > +
> > +   if (pipe->current_fb_id == pipe->fb_id[0])
> > +   new_fb_id = pipe->fb_id[1];
> > +   else
> > +   new_fb_id = pipe->fb_id[0];
> > +
> > +   pipe->current_fb_id = new_fb_id;
> > +   pipe->swap_count++;
> > +
> > +   req = drmModeAtomicAlloc();
> > +
> > +   drmModeAtomicAddProperty(req, pipe->plane_id,
> > pipe->fb_obj_id, new_fb_id); +
> We'll crash badly if req is NULL here. I guess we can smoke test the
> API, but that is no excuse for the missing null check.
> 
> > +   flags = DRM_MODE_PAGE_FLIP_EVENT;
> > +   drmModeAtomicCommit(fd, req, flags, pipe);
> > +
> > +   if (pipe->swap_count == 60) {
> > +   gettimeofday(&end, NULL);
> > +   t = end.tv_sec + end.tv_usec * 1e-6 -
> > +   (pipe->start.tv_sec + pipe->start.tv_usec *
> > 1e-6);
> > +   fprintf(stderr, "freq: %.02fHz\n",
> > pipe->swap_count / t);
> > +   pipe->swap_count = 0;
> > +   pipe->start = end;
> > +   }
> > +
> > +   drmModeAtomicFree(req);
> > +}
> > +
> > +static int atomic_test_page_flip(struct device *dev,
> > drmModeAtomicReqPtr req,
> > +   struct resources *res, struct property_arg
> > *prop_args,
> > +   unsigned int prop_count,unsigned int
> > plane_id) +{
> > +   struct bo *other_bo;
> > +   unsigned int other_fb_id;
> > +   struct pipe_arg *pipe = NULL;
> > +   drmEventContext evctx;
> > +   uint32_t flags = 0, fb_obj_id = 0, pixel_format;
> > +   uint64_t width, height;
> > +   int ret;
> > +
> > +   if (!is_obj_id_in_prop_args(prop_args, prop_count,
> > plane_id))
> > +   return -1;
> > +
> > +   fb_obj_id = get_atomic_plane_prop_id(res, plane_id,
> > "FB_ID");
> > +   if (!fb_obj_id)
> > +  

[PATCH v3 1/3] modetest: introduce get_prop_info() for getting property id and type

2015-09-23 Thread Hyungwon Hwang
Modetest gets the property name from user to set it. So the name must be
converted to its id. Until now, this is done in the set_property(). But to
support atomic modeset in modetest, this logic should be separated from the
fuction, because atomic modeset and legacy modeset use different IOCTLs.

Signed-off-by: Hyungwon Hwang 
---
 tests/modetest/modetest.c | 29 -
 1 file changed, 20 insertions(+), 9 deletions(-)

diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
index 3b01918..08ecf58 100644
--- a/tests/modetest/modetest.c
+++ b/tests/modetest/modetest.c
@@ -894,12 +894,11 @@ struct property_arg {
uint64_t value;
 };

-static void set_property(struct device *dev, struct property_arg *p)
+static int get_prop_info(struct resources *resources, struct property_arg *p,
+   const char *obj_type)
 {
drmModeObjectProperties *props = NULL;
drmModePropertyRes **props_info = NULL;
-   const char *obj_type;
-   int ret;
int i;

p->obj_type = 0;
@@ -918,21 +917,21 @@ static void set_property(struct device *dev, struct 
property_arg *p)
}   
\
} while(0)  
\

-   find_object(dev->resources, res, crtc, CRTC);
+   find_object(resources, res, crtc, CRTC);
if (p->obj_type == 0)
-   find_object(dev->resources, res, connector, CONNECTOR);
+   find_object(resources, res, connector, CONNECTOR);
if (p->obj_type == 0)
-   find_object(dev->resources, plane_res, plane, PLANE);
+   find_object(resources, plane_res, plane, PLANE);
if (p->obj_type == 0) {
fprintf(stderr, "Object %i not found, can't set property\n",
p->obj_id);
-   return;
+   return -1;
}

if (!props) {
fprintf(stderr, "%s %i has no properties\n",
obj_type, p->obj_id);
-   return;
+   return -1;
}

for (i = 0; i < (int)props->count_props; ++i) {
@@ -945,11 +944,23 @@ static void set_property(struct device *dev, struct 
property_arg *p)
if (i == (int)props->count_props) {
fprintf(stderr, "%s %i has no %s property\n",
obj_type, p->obj_id, p->name);
-   return;
+   return -1;
}

p->prop_id = props->props[i];

+   return 0;
+}
+
+static void set_property(struct device *dev, struct property_arg *p)
+{
+   int ret;
+   const char *obj_type = NULL;
+
+   ret = get_prop_info(dev->resources, p, obj_type);
+   if (ret < 0)
+   return;
+
ret = drmModeObjectSetProperty(dev->fd, p->obj_id, p->obj_type,
   p->prop_id, p->value);
if (ret < 0)
--
2.4.3



[PATCH v3 2/3] modetest: add atomic modeset support

2015-09-23 Thread Hyungwon Hwang
This patch adds support for atomic modeset. Using -a option, user can
make modeset to use DRM_IOCTL_MODE_ATOMIC instead of legacy IOCTLs.
Also, by using -w option, user can set the property as before.

Signed-off-by: Hyungwon Hwang 
---
 tests/modetest/modetest.c | 273 --
 1 file changed, 265 insertions(+), 8 deletions(-)

diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
index 08ecf58..bc5a227 100644
--- a/tests/modetest/modetest.c
+++ b/tests/modetest/modetest.c
@@ -1477,25 +1477,32 @@ static int parse_property(struct property_arg *p, const 
char *arg)

 static void usage(char *name)
 {
-   fprintf(stderr, "usage: %s [-cDdefMPpsCvw]\n", name);
+   fprintf(stderr, "usage: %s [-acDdefMPpsCvw]\n", name);
+   fprintf(stderr, "\tA: supported in atomic modeset\n");
+   fprintf(stderr, "\tL: supported in legacy modeset\n");

-   fprintf(stderr, "\n Query options:\n\n");
+   fprintf(stderr, "\n Query options: [AL]\n\n");
fprintf(stderr, "\t-c\tlist connectors\n");
fprintf(stderr, "\t-e\tlist encoders\n");
fprintf(stderr, "\t-f\tlist framebuffers\n");
fprintf(stderr, "\t-p\tlist CRTCs and planes (pipes)\n");

-   fprintf(stderr, "\n Test options:\n\n");
+   fprintf(stderr, "\n Common Test options: [AL]\n\n");
+   fprintf(stderr, "\t-w ::\tset property\n");
+
+   fprintf(stderr, "\n Atomic Test options: [A]\n\n");
+   fprintf(stderr, "\t-a\tuse atomic modeset\n");
+
+   fprintf(stderr, "\n Legacy test options: [L]\n\n");
fprintf(stderr, "\t-P 
:x[++][*][@]\tset a plane\n");
fprintf(stderr, "\t-s 
[,][@]:[-][@]\tset 
a mode\n");
fprintf(stderr, "\t-C\ttest hw cursor\n");
fprintf(stderr, "\t-v\ttest vsynced page flipping\n");
-   fprintf(stderr, "\t-w ::\tset property\n");

fprintf(stderr, "\n Generic options:\n\n");
-   fprintf(stderr, "\t-d\tdrop master after mode set\n");
-   fprintf(stderr, "\t-M module\tuse the given driver\n");
-   fprintf(stderr, "\t-D device\tuse the given device\n");
+   fprintf(stderr, "\t-d\tdrop master after mode set [L]\n");
+   fprintf(stderr, "\t-M module\tuse the given driver [AL]\n");
+   fprintf(stderr, "\t-D device\tuse the given device [AL]\n");

fprintf(stderr, "\n\tDefault is to dump all info.\n");
exit(0);
@@ -1554,7 +1561,224 @@ static int pipe_resolve_connectors(struct device *dev, 
struct pipe_arg *pipe)
return 0;
 }

-static char optstr[] = "cdD:efM:P:ps:Cvw:";
+static bool is_obj_id_in_prop_args(struct property_arg *prop_args,
+   unsigned int prop_count, uint32_t obj_id)
+{
+   unsigned int i;
+
+   for (i = 0; i < prop_count; i++)
+   if (obj_id == prop_args[i].obj_id)
+   return true;
+
+   return false;
+}
+
+static int get_value_in_prop_args(struct property_arg *prop_args,
+   unsigned int prop_count, uint32_t obj_id,
+   const char *name, uint64_t *out)
+{
+   unsigned int i;
+
+   for (i = 0; i < prop_count; i++) {
+   if (prop_args[i].obj_id == obj_id &&
+   !strcmp(prop_args[i].name, name)) {
+   *out = prop_args[i].value;
+   return 0;
+   }
+   }
+
+   return -1;
+}
+
+static uint32_t get_plane_prop_id(struct resources *res, uint32_t obj_id,
+   const char *name)
+{
+   drmModePropertyRes *props_info;
+   struct plane *plane;
+   unsigned int i, j;
+
+   for (i = 0; i < res->plane_res->count_planes; i++) {
+   plane = &res->planes[i];
+   if (plane->plane->plane_id != obj_id)
+   continue;
+
+   for (j = 0; j < plane->props->count_props; j++) {
+   props_info = plane->props_info[j];
+   if (!strcmp(props_info->name, name))
+   return props_info->prop_id;
+   }
+   }
+
+   return 0;
+}
+
+static int allocate_fb(int fd, drmModeAtomicReqPtr req, struct resources *res,
+   uint32_t width, uint32_t height, uint32_t pixel_format,
+   int pattern, struct bo **bo, uint32_t *fb_id)
+{
+   uint32_t handles[4] = {0}, pitches[4] = {0}, offsets[4] = {0};
+   int ret;
+
+   *bo = bo_create(fd, pixel_format, width, height,
+   handles, pitches, offsets, pattern);
+   if (*bo == NULL) {
+   fprintf(

[PATCH v3 3/3] modetest: add atomic page flip support

2015-09-23 Thread Hyungwon Hwang
This patch adds support for atomic page flip. User can specify -V option
with the plane id for testing atomic page flipping.

Signed-off-by: Hyungwon Hwang 
---
 tests/modetest/modetest.c | 195 --
 1 file changed, 187 insertions(+), 8 deletions(-)

diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
index bc5a227..418acaa 100644
--- a/tests/modetest/modetest.c
+++ b/tests/modetest/modetest.c
@@ -747,6 +747,10 @@ struct pipe_arg {
struct timeval start;

int swap_count;
+
+   /* for atomic modeset */
+   uint32_t plane_id;
+   uint32_t fb_obj_id;
 };

 struct plane_arg {
@@ -1477,7 +1481,7 @@ static int parse_property(struct property_arg *p, const 
char *arg)

 static void usage(char *name)
 {
-   fprintf(stderr, "usage: %s [-acDdefMPpsCvw]\n", name);
+   fprintf(stderr, "usage: %s [-acDdefMPpsCvVw]\n", name);
fprintf(stderr, "\tA: supported in atomic modeset\n");
fprintf(stderr, "\tL: supported in legacy modeset\n");

@@ -1492,6 +1496,7 @@ static void usage(char *name)

fprintf(stderr, "\n Atomic Test options: [A]\n\n");
fprintf(stderr, "\t-a\tuse atomic modeset\n");
+   fprintf(stderr, "\t-V \ttest vsynced page 
flipping\n");

fprintf(stderr, "\n Legacy test options: [L]\n\n");
fprintf(stderr, "\t-P 
:x[++][*][@]\tset a plane\n");
@@ -1641,7 +1646,8 @@ static int allocate_fb(int fd, drmModeAtomicReqPtr req, 
struct resources *res,

 static int allocate_fbs(struct device *dev, drmModeAtomicReqPtr req,
struct resources *res, struct property_arg *prop_args,
-   unsigned int prop_count, struct bo **bo, uint32_t 
*fb_id)
+   unsigned int prop_count, struct bo **bo, uint32_t 
*fb_id,
+   uint32_t flip_plane_id)
 {
uint32_t plane_id, fb_obj_id, pixel_format;
uint64_t width, height;
@@ -1652,6 +1658,9 @@ static int allocate_fbs(struct device *dev, 
drmModeAtomicReqPtr req,
if (!is_obj_id_in_prop_args(prop_args, prop_count, plane_id))
continue;

+   if (flip_plane_id == plane_id)
+   dev->mode.fb_id = fb_id[i];
+
fb_obj_id = get_plane_prop_id(res, plane_id, "FB_ID");
if (!fb_obj_id) {
fprintf(stderr, "plane(%u) does not exist\n", plane_id);
@@ -1714,8 +1723,162 @@ static void deallocate_fbs(int fd, int num_planes, 
uint32_t *fb_id, struct bo **
}
 }

+static void atomic_page_flip_handler(int fd, unsigned int frame, unsigned int 
sec,
+   unsigned int usec, void *data)
+{
+   static drmModeAtomicReqPtr req = NULL;
+   unsigned int new_fb_id;
+   struct timeval end;
+   struct pipe_arg *pipe;
+   double t;
+   uint32_t flags = 0;
+   int ret;
+
+   pipe = (struct pipe_arg *)(unsigned long)data;
+
+   req = drmModeAtomicAlloc();
+   if (!req) {
+   fprintf(stderr, "failed to allocate drmModeAtomicReqPtr\n");
+   return;
+   }
+
+   if (pipe->current_fb_id == pipe->fb_id[0])
+   new_fb_id = pipe->fb_id[1];
+   else
+   new_fb_id = pipe->fb_id[0];
+
+   pipe->current_fb_id = new_fb_id;
+   pipe->swap_count++;
+
+   ret = drmModeAtomicAddProperty(req, pipe->plane_id, pipe->fb_obj_id, 
new_fb_id);
+   if (ret < 0) {
+   fprintf(stderr, "failed to add atomic property in pageflip 
handler\n");
+   drmModeAtomicFree(req);
+   return;
+   }
+
+   flags = DRM_MODE_PAGE_FLIP_EVENT;
+   ret = drmModeAtomicCommit(fd, req, flags, pipe);
+   if (ret < 0) {
+   fprintf(stderr, "failed to commit in pageflip handler\n");
+   drmModeAtomicFree(req);
+   return;
+   }
+
+   if (pipe->swap_count == 60) {
+   gettimeofday(&end, NULL);
+   t = end.tv_sec + end.tv_usec * 1e-6 -
+   (pipe->start.tv_sec + pipe->start.tv_usec * 1e-6);
+   fprintf(stderr, "freq: %.02fHz\n", pipe->swap_count / t);
+   pipe->swap_count = 0;
+   pipe->start = end;
+   }
+
+   drmModeAtomicFree(req);
+}
+
+static void atomic_test_page_flip(struct device *dev, drmModeAtomicReqPtr req,
+   struct resources *res, struct property_arg *prop_args,
+   unsigned int prop_count, unsigned int flip_plane_id)
+{
+   struct bo *other_bo;
+   unsigned int other_fb_id;
+   struct pipe_arg pipe;
+   drmEventContext evctx;
+   uint32_t flags = 0, fb_obj_id = 0, pixel_format;
+   uint64_t width, height;
+   

radeon_connector->audio is set by RADEON_AUDIO_DISABLE as default.

2016-04-14 Thread Hyungwon Hwang
Dear all,

I switched my desktop environment to GNOME wayland recently, and I found
that no sound in this environment. In X desktop environment, the ioctl
DRM_IOCTL_MODE_SETPROPERTY(I confused it with
DRM_IOCTL_MODE_OBJ_SETPROPERTY - I deleted the log already :( ) is
called by userspace and it makes the sound works. But in Gnome wayland
desktop environment, the ioctl is not called. I tried to fixed it, and
found that it is because radeon_connector->audio is set by
RADEON_AUDIO_DISABLE.

In atombios_encoders.c, atombios_get_encoder_mode()
if (radeon_connector->audio == RADEON_AUDIO_ENABLE)
return ATOM_ENCODER_MODE_HDMI;
else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
 (radeon_connector->audio == RADEON_AUDIO_AUTO))
return ATOM_ENCODER_MODE_HDMI;
else
return ATOM_ENCODER_MODE_DVI;

This code returns ATOM_ENCODER_MODE_DVI.

In atombios_encoders.c, radeon_atom_encoder_mode_set():
encoder_mode = atombios_get_encoder_mode(encoder);

if (connector && (radeon_audio != 0) &&

((encoder_mode == ATOM_ENCODER_MODE_HDMI) ||

 ENCODER_MODE_IS_DP(encoder_mode)))

radeon_audio_mode_set(encoder, adjusted_mode);b

So this code bypasses the calling of radeon_audio_mode_set().

I think that radeon_connector->audio should be set  by
RADEON_AUDIO_AUTO, at least for connectors which can output audio. I
fixed the code like below, and it works for me. But I am not familiar
with radeon DRM driver, and can't see the big picture. Can you review
this code?

Thanks,
Hyungwon Hwang

diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c
b/drivers/gpu/drm/radeon/radeon_connectors.c
index cfcc099..cf52ea5 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -1975,11 +1975,12 @@ radeon_add_atom_connector(struct drm_device *dev,

rdev->mode_info.output_csc_property,

RADEON_OUTPUT_CSC_BYPASS);
break;
-   case DRM_MODE_CONNECTOR_DVII:
-   case DRM_MODE_CONNECTOR_DVID:
case DRM_MODE_CONNECTOR_HDMIA:
case DRM_MODE_CONNECTOR_HDMIB:
case DRM_MODE_CONNECTOR_DisplayPort:
+   radeon_connector->audio = RADEON_AUDIO_AUTO;
+   case DRM_MODE_CONNECTOR_DVII:
+   case DRM_MODE_CONNECTOR_DVID:
drm_connector_init(dev, &radeon_connector->base,
   &radeon_dp_connector_funcs,
connector_type);
drm_connector_helper_add(&radeon_connector->base,
@@ -2024,8 +2025,9 @@ radeon_add_atom_connector(struct drm_device *dev,
  1);
}
break;
-   case DRM_MODE_CONNECTOR_LVDS:
case DRM_MODE_CONNECTOR_eDP:
+   radeon_connector->audio = RADEON_AUDIO_AUTO;
+   case DRM_MODE_CONNECTOR_LVDS:
drm_connector_init(dev, &radeon_connector->base,

&radeon_lvds_bridge_connector_funcs, connector_type);
drm_connector_helper_add(&radeon_connector->base,
@@ -2196,6 +2198,7 @@ radeon_add_atom_connector(struct drm_device *dev,
connector->doublescan_allowed = true;
else
connector->doublescan_allowed = false;
+   radeon_connector->audio = RADEON_AUDIO_AUTO;
break;
case DRM_MODE_CONNECTOR_DisplayPort:
radeon_dig_connector = kzalloc(sizeof(struct
radeon_connector_atom_dig), GFP_KERNEL);
@@ -2245,6 +2248,7 @@ radeon_add_atom_connector(struct drm_device *dev,
connector->interlace_allowed = true;
/* in theory with a DP to VGA converter... */
connector->doublescan_allowed = false;
+   radeon_connector->audio = RADEON_AUDIO_AUTO;
break;
case DRM_MODE_CONNECTOR_eDP:
radeon_dig_connector = kzalloc(sizeof(struct
radeon_connector_atom_dig), GFP_KERNEL);
@@ -2267,6 +2271,7 @@ radeon_add_atom_connector(struct drm_device *dev,
subpixel_order = SubPixelHorizontalRGB;
connector->interlace_allowed = false;
connector->doublescan_allowed = false;
+   radeon_connector->audio = RADEON_AUDIO_AUTO;
break;
case DRM_MODE_CONNECTOR_SVIDEO:
case DRM_MODE_CONNECTOR_Composite:


radeon_connector->audio is set by RADEON_AUDIO_DISABLE as default.

2016-04-14 Thread Hyungwon Hwang
2016. 4. 14. 오전 1:12에 "Deucher, Alexander" 님이 작성:
>
> > -Original Message-
> > From: Hyungwon Hwang [mailto:hyungwon.hwang7 at gmail.com]
> > Sent: Wednesday, April 13, 2016 11:55 AM
> > To: Deucher, Alexander; Koenig, Christian;
dri-devel at lists.freedesktop.org
> > Subject: radeon_connector->audio is set by RADEON_AUDIO_DISABLE as
> > default.
> >
> > Dear all,
> >
> > I switched my desktop environment to GNOME wayland recently, and I
> > found
> > that no sound in this environment. In X desktop environment, the ioctl
> > DRM_IOCTL_MODE_SETPROPERTY(I confused it with
> > DRM_IOCTL_MODE_OBJ_SETPROPERTY - I deleted the log already :( ) is
> > called by userspace and it makes the sound works. But in Gnome wayland
> > desktop environment, the ioctl is not called. I tried to fixed it, and
> > found that it is because radeon_connector->audio is set by
> > RADEON_AUDIO_DISABLE.
>
> Thanks for spotting this.  Does the attached patch fix it?
>
> Alex

Yes. But I could test it only in my environment (radeon hd 5700 + hdmi
monitor).

Thanks,
Hyungwon Hwang

>
> >
> > In atombios_encoders.c, atombios_get_encoder_mode()
> > if (radeon_connector->audio == RADEON_AUDIO_ENABLE)
> > return ATOM_ENCODER_MODE_HDMI;
> > else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
> >  (radeon_connector->audio == RADEON_AUDIO_AUTO))
> > return ATOM_ENCODER_MODE_HDMI;
> > else
> > return ATOM_ENCODER_MODE_DVI;
> >
> > This code returns ATOM_ENCODER_MODE_DVI.
> >
> > In atombios_encoders.c, radeon_atom_encoder_mode_set():
> > encoder_mode = atombios_get_encoder_mode(encoder);
> >
> > if (connector && (radeon_audio != 0) &&
> >
> > ((encoder_mode == ATOM_ENCODER_MODE_HDMI) ||
> >
> >  ENCODER_MODE_IS_DP(encoder_mode)))
> >
> > radeon_audio_mode_set(encoder, adjusted_mode);b
> >
> > So this code bypasses the calling of radeon_audio_mode_set().
> >
> > I think that radeon_connector->audio should be set  by
> > RADEON_AUDIO_AUTO, at least for connectors which can output audio. I
> > fixed the code like below, and it works for me. But I am not familiar
> > with radeon DRM driver, and can't see the big picture. Can you review
> > this code?
> >
> > Thanks,
> > Hyungwon Hwang
> >
> > diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c
> > b/drivers/gpu/drm/radeon/radeon_connectors.c
> > index cfcc099..cf52ea5 100644
> > --- a/drivers/gpu/drm/radeon/radeon_connectors.c
> > +++ b/drivers/gpu/drm/radeon/radeon_connectors.c
> > @@ -1975,11 +1975,12 @@ radeon_add_atom_connector(struct drm_device
> > *dev,
> >
> > rdev->mode_info.output_csc_property,
> >
> > RADEON_OUTPUT_CSC_BYPASS);
> > break;
> > -   case DRM_MODE_CONNECTOR_DVII:
> > -   case DRM_MODE_CONNECTOR_DVID:
> > case DRM_MODE_CONNECTOR_HDMIA:
> > case DRM_MODE_CONNECTOR_HDMIB:
> > case DRM_MODE_CONNECTOR_DisplayPort:
> > +   radeon_connector->audio = RADEON_AUDIO_AUTO;
> > +   case DRM_MODE_CONNECTOR_DVII:
> > +   case DRM_MODE_CONNECTOR_DVID:
> > drm_connector_init(dev, &radeon_connector->base,
> >&radeon_dp_connector_funcs,
> > connector_type);
> >
 drm_connector_helper_add(&radeon_connector->base,
> > @@ -2024,8 +2025,9 @@ radeon_add_atom_connector(struct drm_device
> > *dev,
> >   1);
> > }
> > break;
> > -   case DRM_MODE_CONNECTOR_LVDS:
> > case DRM_MODE_CONNECTOR_eDP:
> > +   radeon_connector->audio = RADEON_AUDIO_AUTO;
> > +   case DRM_MODE_CONNECTOR_LVDS:
> > drm_connector_init(dev, &radeon_connector->base,
> >
> > &radeon_lvds_bridge_connector_funcs, connector_type);
> >
 drm_connector_helper_add(&radeon_connector->base,
> > @@ -2196,6 +2198,7 @@ radeon_add_atom_connector(struct drm_device
> > *dev,
> > connector->doublescan_allowed = true;
> > else
> > connector->doublescan_allowed = false;
> > +   rad

radeon_connector->audio is set by RADEON_AUDIO_DISABLE as default.

2016-04-14 Thread Hyungwon Hwang
2016. 4. 14. 오전 11:59에 "Hyungwon Hwang" 님이 작성:
>
>
> 2016. 4. 14. 오전 1:12에 "Deucher, Alexander"  amd.com>님이
작성:
>
> >
> > > -----Original Message-
> > > From: Hyungwon Hwang [mailto:hyungwon.hwang7 at gmail.com]
> > > Sent: Wednesday, April 13, 2016 11:55 AM
> > > To: Deucher, Alexander; Koenig, Christian;
dri-devel at lists.freedesktop.org
> > > Subject: radeon_connector->audio is set by RADEON_AUDIO_DISABLE as
> > > default.
> > >
> > > Dear all,
> > >
> > > I switched my desktop environment to GNOME wayland recently, and I
> > > found
> > > that no sound in this environment. In X desktop environment, the ioctl
> > > DRM_IOCTL_MODE_SETPROPERTY(I confused it with
> > > DRM_IOCTL_MODE_OBJ_SETPROPERTY - I deleted the log already :( ) is
> > > called by userspace and it makes the sound works. But in Gnome wayland
> > > desktop environment, the ioctl is not called. I tried to fixed it, and
> > > found that it is because radeon_connector->audio is set by
> > > RADEON_AUDIO_DISABLE.
> >
> > Thanks for spotting this.  Does the attached patch fix it?
> >
> > Alex
>
> Yes. But I could test it only in my environment (radeon hd 5700 + hdmi
monitor).
>
> Thanks,
> Hyungwon Hwang

Oh. Sorry. I couldn't see that there was an attached patch, becaue I
checked it in mailing archive. I can test it at night. After that, I will
send the reply again.

Thanks,
Hyungwon Hwang

>
> >
> > >
> > > In atombios_encoders.c, atombios_get_encoder_mode()
> > > if (radeon_connector->audio == RADEON_AUDIO_ENABLE)
> > > return ATOM_ENCODER_MODE_HDMI;
> > > else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
> > >  (radeon_connector->audio == RADEON_AUDIO_AUTO))
> > > return ATOM_ENCODER_MODE_HDMI;
> > > else
> > > return ATOM_ENCODER_MODE_DVI;
> > >
> > > This code returns ATOM_ENCODER_MODE_DVI.
> > >
> > > In atombios_encoders.c, radeon_atom_encoder_mode_set():
> > > encoder_mode = atombios_get_encoder_mode(encoder);
> > >
> > > if (connector && (radeon_audio != 0) &&
> > >
> > > ((encoder_mode == ATOM_ENCODER_MODE_HDMI) ||
> > >
> > >  ENCODER_MODE_IS_DP(encoder_mode)))
> > >
> > > radeon_audio_mode_set(encoder, adjusted_mode);b
> > >
> > > So this code bypasses the calling of radeon_audio_mode_set().
> > >
> > > I think that radeon_connector->audio should be set  by
> > > RADEON_AUDIO_AUTO, at least for connectors which can output audio. I
> > > fixed the code like below, and it works for me. But I am not familiar
> > > with radeon DRM driver, and can't see the big picture. Can you review
> > > this code?
> > >
> > > Thanks,
> > > Hyungwon Hwang
> > >
> > > diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c
> > > b/drivers/gpu/drm/radeon/radeon_connectors.c
> > > index cfcc099..cf52ea5 100644
> > > --- a/drivers/gpu/drm/radeon/radeon_connectors.c
> > > +++ b/drivers/gpu/drm/radeon/radeon_connectors.c
> > > @@ -1975,11 +1975,12 @@ radeon_add_atom_connector(struct drm_device
> > > *dev,
> > >
> > > rdev->mode_info.output_csc_property,
> > >
> > > RADEON_OUTPUT_CSC_BYPASS);
> > > break;
> > > -   case DRM_MODE_CONNECTOR_DVII:
> > > -   case DRM_MODE_CONNECTOR_DVID:
> > > case DRM_MODE_CONNECTOR_HDMIA:
> > > case DRM_MODE_CONNECTOR_HDMIB:
> > > case DRM_MODE_CONNECTOR_DisplayPort:
> > > +   radeon_connector->audio = RADEON_AUDIO_AUTO;
> > > +   case DRM_MODE_CONNECTOR_DVII:
> > > +   case DRM_MODE_CONNECTOR_DVID:
> > > drm_connector_init(dev,
&radeon_connector->base,
> > >&radeon_dp_connector_funcs,
> > > connector_type);
> > >
 drm_connector_helper_add(&radeon_connector->base,
> > > @@ -2024,8 +2025,9 @@ radeon_add_atom_connector(struct drm_device
> > > *dev,
> > >   1);
> > > }
> > > break;
> > > -   case DRM_MODE_CONNECTOR_LVD

radeon_connector->audio is set by RADEON_AUDIO_DISABLE as default.

2016-04-14 Thread Hyungwon Hwang
2016년 04월 14일 01:12에 Deucher, Alexander 이(가) 쓴 글:
>> -Original Message-
>> From: Hyungwon Hwang [mailto:hyungwon.hwang7 at gmail.com]
>> Sent: Wednesday, April 13, 2016 11:55 AM
>> To: Deucher, Alexander; Koenig, Christian; dri-devel at lists.freedesktop.org
>> Subject: radeon_connector->audio is set by RADEON_AUDIO_DISABLE as
>> default.
>>
>> Dear all,
>>
>> I switched my desktop environment to GNOME wayland recently, and I
>> found
>> that no sound in this environment. In X desktop environment, the ioctl
>> DRM_IOCTL_MODE_SETPROPERTY(I confused it with
>> DRM_IOCTL_MODE_OBJ_SETPROPERTY - I deleted the log already :( ) is
>> called by userspace and it makes the sound works. But in Gnome wayland
>> desktop environment, the ioctl is not called. I tried to fixed it, and
>> found that it is because radeon_connector->audio is set by
>> RADEON_AUDIO_DISABLE.
> 
> Thanks for spotting this.  Does the attached patch fix it?
> 
> Alex

Great. Now it works with your patch. Thanks for your work.

Best regards,
Hyungwon Hwang

> 
>>
>> In atombios_encoders.c, atombios_get_encoder_mode()
>> if (radeon_connector->audio == RADEON_AUDIO_ENABLE)
>> return ATOM_ENCODER_MODE_HDMI;
>> else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
>>  (radeon_connector->audio == RADEON_AUDIO_AUTO))
>> return ATOM_ENCODER_MODE_HDMI;
>> else
>> return ATOM_ENCODER_MODE_DVI;
>>
>> This code returns ATOM_ENCODER_MODE_DVI.
>>
>> In atombios_encoders.c, radeon_atom_encoder_mode_set():
>> encoder_mode = atombios_get_encoder_mode(encoder);
>>
>> if (connector && (radeon_audio != 0) &&
>>
>> ((encoder_mode == ATOM_ENCODER_MODE_HDMI) ||
>>
>>  ENCODER_MODE_IS_DP(encoder_mode)))
>>
>> radeon_audio_mode_set(encoder, adjusted_mode);b
>>
>> So this code bypasses the calling of radeon_audio_mode_set().
>>
>> I think that radeon_connector->audio should be set  by
>> RADEON_AUDIO_AUTO, at least for connectors which can output audio. I
>> fixed the code like below, and it works for me. But I am not familiar
>> with radeon DRM driver, and can't see the big picture. Can you review
>> this code?
>>
>> Thanks,
>> Hyungwon Hwang
>>
>> diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c
>> b/drivers/gpu/drm/radeon/radeon_connectors.c
>> index cfcc099..cf52ea5 100644
>> --- a/drivers/gpu/drm/radeon/radeon_connectors.c
>> +++ b/drivers/gpu/drm/radeon/radeon_connectors.c
>> @@ -1975,11 +1975,12 @@ radeon_add_atom_connector(struct drm_device
>> *dev,
>>
>> rdev->mode_info.output_csc_property,
>>
>> RADEON_OUTPUT_CSC_BYPASS);
>> break;
>> -   case DRM_MODE_CONNECTOR_DVII:
>> -   case DRM_MODE_CONNECTOR_DVID:
>> case DRM_MODE_CONNECTOR_HDMIA:
>> case DRM_MODE_CONNECTOR_HDMIB:
>> case DRM_MODE_CONNECTOR_DisplayPort:
>> +   radeon_connector->audio = RADEON_AUDIO_AUTO;
>> +   case DRM_MODE_CONNECTOR_DVII:
>> +   case DRM_MODE_CONNECTOR_DVID:
>> drm_connector_init(dev, &radeon_connector->base,
>>&radeon_dp_connector_funcs,
>> connector_type);
>> drm_connector_helper_add(&radeon_connector->base,
>> @@ -2024,8 +2025,9 @@ radeon_add_atom_connector(struct drm_device
>> *dev,
>>   1);
>> }
>> break;
>> -   case DRM_MODE_CONNECTOR_LVDS:
>> case DRM_MODE_CONNECTOR_eDP:
>> +   radeon_connector->audio = RADEON_AUDIO_AUTO;
>> +   case DRM_MODE_CONNECTOR_LVDS:
>> drm_connector_init(dev, &radeon_connector->base,
>>
>> &radeon_lvds_bridge_connector_funcs, connector_type);
>> drm_connector_helper_add(&radeon_connector->base,
>> @@ -2196,6 +2198,7 @@ radeon_add_atom_connector(struct drm_device
>> *dev,
>> connector->doublescan_allowed = true;
>> else
>> connector->doublescan_allowed = false;
>> +   radeon_connector->audio = RADEON_AUDIO_AUTO;
>> 

[PATCH v2 1/3] ARM: dts: add fimd device support for exynos3250-rinato

2014-12-09 Thread Hyungwon Hwang
From: Inki Dae 

This patch adds fimd device node which is a display controller
for Exynos3250 Rinato board.

Signed-off-by: Inki Dae 
Signed-off-by: Hyungwon Hwang 
Acked-by: Kyungmin Park 
---
Changes for v2:
- None

 arch/arm/boot/dts/exynos3250-rinato.dts | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm/boot/dts/exynos3250-rinato.dts 
b/arch/arm/boot/dts/exynos3250-rinato.dts
index 80aa8b4..79aa916 100644
--- a/arch/arm/boot/dts/exynos3250-rinato.dts
+++ b/arch/arm/boot/dts/exynos3250-rinato.dts
@@ -125,6 +125,17 @@
};
 };

+&fimd {
+   status = "okay";
+
+   i80-if-timings {
+   cs-setup = <0>;
+   wr-setup = <0>;
+   wr-act = <1>;
+   wr-hold = <0>;
+   };
+};
+
 &i2c_0 {
#address-cells = <1>;
#size-cells = <0>;
-- 
1.9.1



[PATCH v2 0/3] add display support for exynos3250 rinato board

2014-12-09 Thread Hyungwon Hwang
This is v2 of the patchset adding support for s6e63j0x03 lcd panel.

Inki Dae sent this patchset before. Because of his busy work at company,
I modifies some point according to the review by Thierry Reding on
behalf of him.

This patch series adds Display support for exynos3250 Rinato board.
For this, it adds fimd, MIPI-DSI and Panel device nodes to
exynos3250-rinato dts file, and adds a s6e63j0x03 Amoled panel device
driver which is based on MIPI-DSI bus.

Changes for v2:
- Change the gamma table to 2-dimensional array
- Change the way to make index for brightness
- Make command functions to an array so that it can be called simply
- Change command id for reading device ID
- Change the way to handle the error condition
- Remove power variable, and use the same name variable in bl_dev
- Add the state FB_BLANK_NORMAL to represent the state which the panel
is working but blanked
- Miscellaneous changes to increase the readability and follow the
  coding-style standard

Inki Dae (3):
  ARM: dts: add fimd device support for exynos3250-rinato
  drm/panel: add s6e63j0x03 LCD panel driver
  ARM: dts: add Panel device support for exynos3250-rinato

 arch/arm/boot/dts/exynos3250-rinato.dts  |  71 
 drivers/gpu/drm/panel/Kconfig|   6 +
 drivers/gpu/drm/panel/Makefile   |   1 +
 drivers/gpu/drm/panel/panel-s6e63j0x03.c | 549 +++
 4 files changed, 627 insertions(+)
 create mode 100644 drivers/gpu/drm/panel/panel-s6e63j0x03.c

-- 
1.9.1



[PATCH v2 3/3] ARM: dts: add Panel device support for exynos3250-rinato

2014-12-09 Thread Hyungwon Hwang
From: Inki Dae 

This patch adds MIPI-DSI and MIPI-DSI based S6E63J0X03 AMOLED panel
device nodes for Exynos3250 Rinato board.

Signed-off-by: Inki Dae 
Signed-off-by: Hyungwon Hwang 
Acked-by: Kyungmin Park 
---
Changes for v2:
- None

 arch/arm/boot/dts/exynos3250-rinato.dts | 60 +
 1 file changed, 60 insertions(+)

diff --git a/arch/arm/boot/dts/exynos3250-rinato.dts 
b/arch/arm/boot/dts/exynos3250-rinato.dts
index 79aa916..a8caee5 100644
--- a/arch/arm/boot/dts/exynos3250-rinato.dts
+++ b/arch/arm/boot/dts/exynos3250-rinato.dts
@@ -125,6 +125,66 @@
};
 };

+&dsi_0 {
+   vddcore-supply = <&ldo6_reg>;
+   vddio-supply = <&ldo6_reg>;
+   samsung,pll-clock-frequency = <2400>;
+   status = "okay";
+
+   ports {
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   port at 1 {
+   reg = <1>;
+
+   dsi_out: endpoint {
+   remote-endpoint = <&dsi_in>;
+   samsung,burst-clock-frequency = <25000>;
+   samsung,esc-clock-frequency = <2000>;
+   };
+   };
+   };
+
+   panel at 0 {
+   compatible = "samsung,s6e63j0x03";
+   reg = <0>;
+   vdd3-supply = <&ldo16_reg>;
+   vci-supply = <&ldo20_reg>;
+   reset-gpios = <&gpe0 1 0>;
+   te-gpios = <&gpx0 6 0>;
+   power-on-delay= <30>;
+   power-off-delay= <120>;
+   reset-delay = <5>;
+   init-delay = <100>;
+   flip-horizontal;
+   flip-vertical;
+   panel-width-mm = <29>;
+   panel-height-mm = <29>;
+
+
+   display-timings {
+   timing-0 {
+   clock-frequency = <0>;
+   hactive = <320>;
+   vactive = <320>;
+   hfront-porch = <1>;
+   hback-porch = <1>;
+   hsync-len = <1>;
+   vfront-porch = <150>;
+   vback-porch = <1>;
+   vsync-len = <2>;
+   };
+   };
+
+   port {
+   dsi_in: endpoint {
+   remote-endpoint = <&dsi_out>;
+   };
+   };
+   };
+};
+
 &fimd {
status = "okay";

-- 
1.9.1



[PATCH v2 2/3] drm/panel: add s6e63j0x03 LCD panel driver

2014-12-09 Thread Hyungwon Hwang
From: Inki Dae 

This patch adds MIPI-DSI based S6E63J0X03 AMOLED LCD panel driver
which uses mipi_dsi bus to communicate with panel. The panel has
320×320 resolution in 1.63-inch physical panel. This panel is used in
Samsung Galaxy Gear 2.

Signed-off-by: Inki Dae 
Signed-off-by: Hyungwon Hwang 
Acked-by: Kyungmin Park 
---
Changes for v2:
- Change the gamma table to 2-dimensional array
- Change the way to make index for brightness
- Make command functions to an array so that it can be called simply
- Change command id for reading device ID
- Change the way to handle the error condition
- Remove power variable, and use the same name variable in bl_dev
- Add the state FB_BLANK_NORMAL to represent the state which the panel
is working but blanked
- Miscellaneous changes to increase the readability and follow the
  coding-style standard

 drivers/gpu/drm/panel/Kconfig|   6 +
 drivers/gpu/drm/panel/Makefile   |   1 +
 drivers/gpu/drm/panel/panel-s6e63j0x03.c | 549 +++
 3 files changed, 556 insertions(+)
 create mode 100644 drivers/gpu/drm/panel/panel-s6e63j0x03.c

diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index bee9f72..bc133e2 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -27,4 +27,10 @@ config DRM_PANEL_S6E8AA0
select DRM_MIPI_DSI
select VIDEOMODE_HELPERS

+config DRM_PANEL_S6E63J0X03
+   tristate "S6E63J0X03 DSI video mode panel"
+   depends on OF
+   select DRM_MIPI_DSI
+   select VIDEOMODE_HELPERS
+
 endmenu
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index 8b92921..7f36dc2 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -1,3 +1,4 @@
 obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o
 obj-$(CONFIG_DRM_PANEL_LD9040) += panel-ld9040.o
 obj-$(CONFIG_DRM_PANEL_S6E8AA0) += panel-s6e8aa0.o
+obj-$(CONFIG_DRM_PANEL_S6E63J0X03) += panel-s6e63j0x03.o
diff --git a/drivers/gpu/drm/panel/panel-s6e63j0x03.c 
b/drivers/gpu/drm/panel/panel-s6e63j0x03.c
new file mode 100644
index 000..28e4a51
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-s6e63j0x03.c
@@ -0,0 +1,549 @@
+/*
+ * MIPI-DSI based S6E63J0X03 AMOLED lcd 1.63 inch panel driver.
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd
+ *
+ * Inki Dae, 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#define READ_ID1   0xDA
+#define READ_ID2   0xDB
+#define READ_ID3   0xDC
+
+#define MCS_LEVEL2_KEY 0xf0
+#define MCS_MTP_KEY0xf1
+#define MCS_MTP_SET3   0xd4
+
+#define MIN_BRIGHTNESS 0
+#define MAX_BRIGHTNESS 100
+#define DEFAULT_BRIGHTNESS 80
+
+#define GAMMA_LEVEL_NUM30
+#define NUM_GAMMA_STEPS9
+#define GAMMA_CMD_CNT  28
+
+struct s6e63j0x03 {
+   struct device *dev;
+   struct drm_panel panel;
+   struct backlight_device *bl_dev;
+
+   struct regulator_bulk_data supplies[2];
+   struct gpio_desc *reset_gpio;
+   u32 power_on_delay;
+   u32 power_off_delay;
+   u32 reset_delay;
+   u32 init_delay;
+   bool flip_horizontal;
+   bool flip_vertical;
+   struct videomode vm;
+   unsigned int width_mm;
+   unsigned int height_mm;
+};
+
+static const unsigned char gamma_tbl[NUM_GAMMA_STEPS][GAMMA_CMD_CNT] = {
+   {   /* Gamma 10 */
+   MCS_MTP_SET3,
+   0x00, 0x00, 0x00, 0x7f, 0x7f, 0x7f, 0x52, 0x6b, 0x6f, 0x26,
+   0x28, 0x2d, 0x28, 0x26, 0x27, 0x33, 0x34, 0x32, 0x36, 0x36,
+   0x35, 0x00, 0xab, 0x00, 0xae, 0x00, 0xbf
+   },
+   {   /* gamma 30 */
+   MCS_MTP_SET3,
+   0x00, 0x00, 0x00, 0x70, 0x7f, 0x7f, 0x4e, 0x64, 0x69, 0x26,
+   0x27, 0x2a, 0x28, 0x29, 0x27, 0x31, 0x32, 0x31, 0x35, 0x34,
+   0x35, 0x00, 0xc4, 0x00, 0xca, 0x00, 0xdc
+   },
+   {   /* gamma 60 */
+   MCS_MTP_SET3,
+   0x00, 0x00, 0x00, 0x65, 0x7b, 0x7d, 0x5f, 0x67, 0x68, 0x2a,
+   0x28, 0x29, 0x28, 0x2a, 0x27, 0x31, 0x2f, 0x30, 0x34, 0x33,
+   0x34, 0x00, 0xd9, 0x00, 0xe4, 0x00, 0xf5
+   },
+   {   /* gamma 90 */
+   MCS_MTP_SET3,
+   0x00, 0x00, 0x00, 0x4d, 0x6f, 0x71, 0x67, 0x6a, 0x6c, 0x29,
+   0x28, 0x28, 0x28, 0x29, 0x27, 0x30, 0x2e, 0x30, 0x32, 0x31,
+   0x31, 0x00, 0xea, 0x00, 0xf6, 0x01, 0x09
+   },
+   {   /* gamma 120 */
+   MCS_MTP_SET3,
+   0x00, 0x00, 0x00, 0x3d, 0x66, 0x68, 0x69, 0x69, 0x69, 0x28,
+   0x28, 0x27, 0x28, 0x28, 0x27, 0x30, 

[PATCH RESEND 1/2] exynos: Don't use DRM_EXYNOS_GEM_{MAP_OFFSET/MMAP} ioctls

2014-12-12 Thread Hyungwon Hwang
The ioctl DRM_EXYNOS_GEM_MAP_OFFSET and DRM_EXYNOS_GEM_MMAP are removed from
the linux kernel. This patch modifies libdrm and libkms to use drm generic
ioctls instead of the removed ioctls.

Signed-off-by: Hyungwon Hwang 
Signed-off-by: Inki Dae 
---
 exynos/exynos_drm.c | 24 +---
 libkms/exynos.c |  7 ---
 2 files changed, 17 insertions(+), 14 deletions(-)

diff --git a/exynos/exynos_drm.c b/exynos/exynos_drm.c
index 4c7dd13..4cb6a6d 100644
--- a/exynos/exynos_drm.c
+++ b/exynos/exynos_drm.c
@@ -283,20 +283,22 @@ drm_public void *exynos_bo_map(struct exynos_bo *bo)
 {
if (!bo->vaddr) {
struct exynos_device *dev = bo->dev;
-   struct drm_exynos_gem_mmap req = {
-   .handle = bo->handle,
-   .size   = bo->size,
-   };
+   struct drm_mode_map_dumb arg;
+   void *map = NULL;
int ret;

-   ret = drmIoctl(dev->fd, DRM_IOCTL_EXYNOS_GEM_MMAP, &req);
-   if (ret) {
-   fprintf(stderr, "failed to mmap[%s].\n",
-   strerror(errno));
-   return NULL;
-   }
+   memset(&arg, 0, sizeof(arg));
+   arg.handle = bo->handle;
+
+   ret = drmIoctl(dev->fd, DRM_IOCTL_MODE_MAP_DUMB, &arg);
+   if (ret)
+   return ret;

-   bo->vaddr = (void *)(uintptr_t)req.mapped;
+   map = drm_mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
+   dev->fd, arg.offset);
+
+   if (map == MAP_FAILED)
+   return NULL;
}

return bo->vaddr;
diff --git a/libkms/exynos.c b/libkms/exynos.c
index 92e329c..1123482 100644
--- a/libkms/exynos.c
+++ b/libkms/exynos.c
@@ -25,6 +25,7 @@
 #include 
 #include "xf86drm.h"

+#include "libdrm.h"
 #include "exynos_drm.h"

 struct exynos_bo
@@ -124,7 +125,7 @@ static int
 exynos_bo_map(struct kms_bo *_bo, void **out)
 {
struct exynos_bo *bo = (struct exynos_bo *)_bo;
-   struct drm_exynos_gem_map_off arg;
+   struct drm_mode_map_dumb arg;
void *map = NULL;
int ret;

@@ -137,11 +138,11 @@ exynos_bo_map(struct kms_bo *_bo, void **out)
memset(&arg, 0, sizeof(arg));
arg.handle = bo->base.handle;

-   ret = drmCommandWriteRead(bo->base.kms->fd, DRM_EXYNOS_GEM_MAP_OFFSET, 
&arg, sizeof(arg));
+   ret = drmIoctl(bo->base.kms->fd, DRM_IOCTL_MODE_MAP_DUMB, &arg);
if (ret)
return ret;

-   map = mmap(0, bo->base.size, PROT_READ | PROT_WRITE, MAP_SHARED, 
bo->base.kms->fd, arg.offset);
+   map = drm_mmap(0, bo->base.size, PROT_READ | PROT_WRITE, MAP_SHARED, 
bo->base.kms->fd, arg.offset);
if (map == MAP_FAILED)
return -errno;

-- 
1.9.1



[PATCH RESEND 2/2] exynos: remove DRM_EXYNOS_GEM_{MAP_OFFSET/MMAP} ioctls

2014-12-12 Thread Hyungwon Hwang
This patch removes the ioctls which are removed from the linux kernel.

Signed-off-by: Hyungwon Hwang 
Signed-off-by: Inki Dae 
---
 exynos/exynos_drm.h | 40 
 1 file changed, 40 deletions(-)

diff --git a/exynos/exynos_drm.h b/exynos/exynos_drm.h
index c3c6579..256c02f 100644
--- a/exynos/exynos_drm.h
+++ b/exynos/exynos_drm.h
@@ -47,38 +47,6 @@ struct drm_exynos_gem_create {
 };

 /**
- * A structure for getting buffer offset.
- *
- * @handle: a pointer to gem object created.
- * @pad: just padding to be 64-bit aligned.
- * @offset: relatived offset value of the memory region allocated.
- * - this value should be set by user.
- */
-struct drm_exynos_gem_map_off {
-   unsigned int handle;
-   unsigned int pad;
-   uint64_t offset;
-};
-
-/**
- * A structure for mapping buffer.
- *
- * @handle: a handle to gem object created.
- * @pad: just padding to be 64-bit aligned.
- * @size: memory size to be mapped.
- * @mapped: having user virtual address mmaped.
- * - this variable would be filled by exynos gem module
- * of kernel side with user virtual address which is allocated
- * by do_mmap().
- */
-struct drm_exynos_gem_mmap {
-   unsigned int handle;
-   unsigned int pad;
-   uint64_t size;
-   uint64_t mapped;
-};
-
-/**
  * A structure to gem information.
  *
  * @handle: a handle to gem object created.
@@ -164,8 +132,6 @@ struct drm_exynos_g2d_exec {
 };

 #define DRM_EXYNOS_GEM_CREATE  0x00
-#define DRM_EXYNOS_GEM_MAP_OFFSET  0x01
-#define DRM_EXYNOS_GEM_MMAP0x02
 /* Reserved 0x04 ~ 0x05 for exynos specific gem ioctl */
 #define DRM_EXYNOS_GEM_GET 0x04
 #define DRM_EXYNOS_VIDI_CONNECTION 0x07
@@ -178,12 +144,6 @@ struct drm_exynos_g2d_exec {
 #define DRM_IOCTL_EXYNOS_GEM_CREATEDRM_IOWR(DRM_COMMAND_BASE + \
DRM_EXYNOS_GEM_CREATE, struct drm_exynos_gem_create)

-#define DRM_IOCTL_EXYNOS_GEM_MAP_OFFSETDRM_IOWR(DRM_COMMAND_BASE + \
-   DRM_EXYNOS_GEM_MAP_OFFSET, struct drm_exynos_gem_map_off)
-
-#define DRM_IOCTL_EXYNOS_GEM_MMAP  DRM_IOWR(DRM_COMMAND_BASE + \
-   DRM_EXYNOS_GEM_MMAP, struct drm_exynos_gem_mmap)
-
 #define DRM_IOCTL_EXYNOS_GEM_GET   DRM_IOWR(DRM_COMMAND_BASE + \
DRM_EXYNOS_GEM_GET, struct drm_exynos_gem_info)

-- 
1.9.1



[patch] tests/kmstest: support exynos

2014-01-07 Thread Hyungwon Hwang
tests/kmstest: support exynos

Add exynos to list of kmstest supported modules.

Signed-off-by: Hyungwon Hwang 
---
 libkms/internal.h|2 ++
 libkms/linux.c   |4 
 tests/kmstest/main.c |1 +
 3 files changed, 7 insertions(+)

diff --git a/libkms/internal.h b/libkms/internal.h
index 5e2501e..f831b57 100644
--- a/libkms/internal.h
+++ b/libkms/internal.h
@@ -74,4 +74,6 @@ int nouveau_create(int fd, struct kms_driver **out);

 int radeon_create(int fd, struct kms_driver **out);

+int exynos_create(int fd, struct kms_driver **out);
+
 #endif
diff --git a/libkms/linux.c b/libkms/linux.c
index fc4f205..2de0145 100644
--- a/libkms/linux.c
+++ b/libkms/linux.c
@@ -115,6 +115,10 @@ linux_from_sysfs(int fd, struct kms_driver **out)
else if (!strcmp(name, "radeon"))
ret = radeon_create(fd, out);
 #endif
+#ifdef HAVE_EXYNOS
+   else if (!strcmp(name, "exynos"))
+   ret = exynos_create(fd, out);
+#endif
else
ret = -ENOSYS;

diff --git a/tests/kmstest/main.c b/tests/kmstest/main.c
index 5df0a38..449d75f 100644
--- a/tests/kmstest/main.c
+++ b/tests/kmstest/main.c
@@ -61,6 +61,7 @@ char *drivers[] = {
"radeon",
"nouveau",
"vmwgfx",
+   "exynos",
NULL
 };

-- 
1.7.9.5

---
Hyungwon Hwang
Samsung SWC S/W Platform Team
Smasung Electronics
human.hwang at samsung.com


[patch] tests/kmstest: support exynos

2014-01-09 Thread Hyungwon Hwang
Hello Rob,

On Wed, 08 Jan 2014 11:28:19 -0500
Rob Clark  wrote:

> On Tue, Jan 7, 2014 at 1:40 AM, Hyungwon Hwang
>  wrote:
> > tests/kmstest: support exynos
> >
> > Add exynos to list of kmstest supported modules.
> >
> > Signed-off-by: Hyungwon Hwang 
> > ---
> >  libkms/internal.h|2 ++
> >  libkms/linux.c   |4 
> >  tests/kmstest/main.c |1 +
> >  3 files changed, 7 insertions(+)
> >
> > diff --git a/libkms/internal.h b/libkms/internal.h
> > index 5e2501e..f831b57 100644
> > --- a/libkms/internal.h
> > +++ b/libkms/internal.h
> > @@ -74,4 +74,6 @@ int nouveau_create(int fd, struct kms_driver
> > **out);
> >
> >  int radeon_create(int fd, struct kms_driver **out);
> >
> > +int exynos_create(int fd, struct kms_driver **out);
> > +
> 
> exynos_create() does not seem to be defined anywhere.. am I missing a
> patch, or perhaps did you forget to 'git add' a file?

Sorry. It was my mistake.
I forgot to include exynos implementation for KMS.
I'll resend again.


> 
> BR,
> -R
> 
> 
> >  #endif
> > diff --git a/libkms/linux.c b/libkms/linux.c
> > index fc4f205..2de0145 100644
> > --- a/libkms/linux.c
> > +++ b/libkms/linux.c
> > @@ -115,6 +115,10 @@ linux_from_sysfs(int fd, struct kms_driver
> > **out) else if (!strcmp(name, "radeon"))
> > ret = radeon_create(fd, out);
> >  #endif
> > +#ifdef HAVE_EXYNOS
> > +   else if (!strcmp(name, "exynos"))
> > +   ret = exynos_create(fd, out);
> > +#endif
> > else
> > ret = -ENOSYS;
> >
> > diff --git a/tests/kmstest/main.c b/tests/kmstest/main.c
> > index 5df0a38..449d75f 100644
> > --- a/tests/kmstest/main.c
> > +++ b/tests/kmstest/main.c
> > @@ -61,6 +61,7 @@ char *drivers[] = {
> > "radeon",
> > "nouveau",
> > "vmwgfx",
> > +       "exynos",
> > NULL
> >  };
> >
> > --
> > 1.7.9.5
> >
> > ---
> > Hyungwon Hwang
> > Samsung SWC S/W Platform Team
> > Smasung Electronics
> > human.hwang at samsung.com
> > ___
> > dri-devel mailing list
> > dri-devel at lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/dri-devel

Thanks,
Hyungwon Hwang

---
Hyungwon Hwang
Samsung SWC S/W Platform Team
Smasung Electronics
human.hwang at samsung.com


[PATCH RESEND] tests/kmstest: support exynos

2014-01-10 Thread Hyungwon Hwang

In this patch, to support exynos for KMS, Exynos KMS driver is newly added.
Also, Exynos is added to the list of kmstest supported modules.

Signed-off-by: Hyungwon Hwang 
---
 libkms/exynos.c  |  207 ++
 libkms/internal.h|2 +
 libkms/linux.c   |4 +
 tests/kmstest/main.c |1 +
 4 files changed, 214 insertions(+)
 create mode 100644 libkms/exynos.c

diff --git a/libkms/exynos.c b/libkms/exynos.c
new file mode 100644
index 000..93e36a1
--- /dev/null
+++ b/libkms/exynos.c
@@ -0,0 +1,207 @@
+/* exynos.c
+ *
+ * Copyright 2009 Samsung Electronics Co., Ltd.
+ * Authors:
+ * SooChan Lim 
+ *  Sangjin LEE 
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#define HAVE_STDINT_H
+#define _FILE_OFFSET_BITS 64
+
+#include 
+#include 
+#include 
+#include 
+#include "internal.h"
+
+#include 
+#include 
+#include "xf86drm.h"
+
+#include "exynos_drm.h"
+
+struct exynos_bo
+{
+   struct kms_bo base;
+   unsigned map_count;
+};
+
+static int
+exynos_get_prop(struct kms_driver *kms, unsigned key, unsigned *out)
+{
+   switch (key) {
+   case KMS_BO_TYPE:
+   *out = KMS_BO_TYPE_SCANOUT_X8R8G8B8 |
KMS_BO_TYPE_CURSOR_64X64_A8R8G8B8;
+   break;
+   default:
+   return -EINVAL;
+   }
+   return 0;
+}
+
+static int
+exynos_destroy(struct kms_driver *kms)
+{
+   free(kms);
+   return 0;
+}
+
+static int
+exynos_bo_create(struct kms_driver *kms,
+const unsigned width, const unsigned height,
+const enum kms_bo_type type, const unsigned *attr,
+struct kms_bo **out)
+{
+   struct drm_exynos_gem_create arg;
+   unsigned size, pitch;
+   struct exynos_bo *bo;
+   int i, ret;
+
+   for (i = 0; attr[i]; i += 2) {
+   switch (attr[i]) {
+   case KMS_WIDTH:
+   case KMS_HEIGHT:
+   case KMS_BO_TYPE:
+   break;
+   default:
+   return -EINVAL;
+   }
+   }
+
+   bo = calloc(1, sizeof(*bo));
+   if (!bo)
+   return -ENOMEM;
+
+   if (type == KMS_BO_TYPE_CURSOR_64X64_A8R8G8B8) {
+   pitch = 64 * 4;
+   size = 64 * 64 * 4;
+   } else if (type == KMS_BO_TYPE_SCANOUT_X8R8G8B8) {
+   pitch = width * 4;
+   pitch = (pitch + 512 - 1) & ~(512 - 1);
+   size = pitch * ((height + 4 - 1) & ~(4 - 1));
+   } else {
+   return -EINVAL;
+   }
+
+   memset(&arg, 0, sizeof(arg));
+   arg.size = size;
+
+   ret = drmCommandWriteRead(kms->fd, DRM_EXYNOS_GEM_CREATE, &arg,
sizeof(arg));
+   if (ret)
+   goto err_free;
+
+   bo->base.kms = kms;
+   bo->base.handle = arg.handle;
+   bo->base.size = size;
+   bo->base.pitch = pitch;
+
+   *out = &bo->base;
+
+   return 0;
+
+err_free:
+   free(bo);
+   return ret;
+}
+
+static int
+exynos_bo_get_prop(struct kms_bo *bo, unsigned key, unsigned *out)
+{
+   switch (key) {
+   default:
+   return -EINVAL;
+   }
+}
+
+static int
+exynos_bo_map(struct kms_bo *_bo, void **out)
+{
+   struct exynos_bo *bo = (struct exynos_bo *)_bo;
+   struct drm_exynos_gem_map_off arg;
+   void *map = NULL;
+   int ret;
+
+   if (bo->base.ptr) {
+   bo->map_count++;
+   *out = bo->base.ptr;
+   return 0;
+   }
+
+   memset(&arg, 0, sizeof(arg));
+   arg.handle = bo->base.handle;
+
+   ret = drmCommandWriteRead(bo->base.kms->fd, DRM_EXYNOS_GEM_MAP_OFFSET,
&arg, sizeof(arg));
+   if (ret)
+   return ret;
+
+   map = mmap(0, bo->base.size, PROT_READ | PROT_WRITE, MAP_SHARED,
bo->base.kms->fd, arg.offset);
+   if (map == MAP_FAILED)
+   return -errno;
+
+   bo->base.ptr = map;
+   bo->map_count++;
+   *out = bo->base.ptr;
+
+   return 0;
+}
+
+static int
+exynos_bo_unmap(struct kms_bo *_bo)
+{
+   struct exynos_bo *bo = (struct exynos_bo *)_bo;
+   bo->map_count--;
+   return 0;
+}
+
+static int
+exynos_bo_destroy(struct kms_bo *_bo)
+{
+   struct exynos_bo *bo = (struct exynos_bo *)_bo;
+   struct drm_gem_close arg;
+   int ret;
+
+   if (bo->base.ptr) {
+   /* XXX Sanity check map_count */
+   munmap(bo->base.ptr, bo->base.size);
+   bo->base.ptr = NULL;
+   }
+
+   memset(&arg, 0, sizeof(arg));
+   arg.handle = bo->base.handle;
+
+   ret = drmIoctl(bo->

[PATCH 1/2] drm/exynos: add more condition to check iommu support

2015-03-12 Thread Hyungwon Hwang
] [] (exynos_drm_platform_probe) from [] 
(platform_drv_probe+0x44/0xa4)
[1.444124] [] (platform_drv_probe) from [] 
(driver_probe_device+0x13c/0x394)
[1.452977] [] (driver_probe_device) from [] 
(__driver_attach+0x8c/0x90)
[1.461395] [] (__driver_attach) from [] 
(bus_for_each_dev+0x68/0x9c)
[1.469555] [] (bus_for_each_dev) from [] 
(bus_add_driver+0x160/0x21c)
[1.477801] [] (bus_add_driver) from [] 
(driver_register+0x78/0xf8)
[1.485786] [] (driver_register) from [] 
(exynos_drm_init+0xc8/0x110)
[1.493946] [] (exynos_drm_init) from [] 
(do_one_initcall+0xb8/0x1f0)
[1.502108] [] (do_one_initcall) from [] 
(kernel_init_freeable+0x1d4/0x278)
[1.510787] [] (kernel_init_freeable) from [] 
(kernel_init+0xc/0xe8)
[1.518859] [] (kernel_init) from [] 
(ret_from_fork+0x14/0x24)
[1.526406] Code: e3130004 1a1e e3a06000 eacf (e7f001f2)
[1.532505] ---[ end trace 03b1b443463b1342 ]---
[1.537077] Kernel panic - not syncing: Fatal exception

Signed-off-by: Hyungwon Hwang 
Cc: Inki Dae 
---
 drivers/gpu/drm/exynos/exynos_drm_iommu.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_iommu.h 
b/drivers/gpu/drm/exynos/exynos_drm_iommu.h
index 35d2588..597bf70 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_iommu.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_iommu.h
@@ -32,7 +32,7 @@ static inline bool is_drm_iommu_supported(struct drm_device 
*drm_dev)
 #ifdef CONFIG_ARM_DMA_USE_IOMMU
struct device *dev = drm_dev->dev;

-   return dev->archdata.mapping ? true : false;
+   return dev->archdata.mapping && dev->archdata.iommu;
 #else
return false;
 #endif
--
1.9.1



[PATCH 2/2] drm/exynos: fix the initialization order in FIMD

2015-03-12 Thread Hyungwon Hwang
able+0x194/0x268)
[1.654626] [] (kernel_init_freeable) from [] 
(kernel_init+0x8/0xe4)
[1.662699] [] (kernel_init) from [] 
(ret_from_fork+0x14/0x34)
[1.670246] Code: ead5 c09df884 e92d40f0 e24dd01c (e5905350)
[1.676408] ---[ end trace 804468492f306a6f ]---
[1.680948] Kernel panic - not syncing: Attempted to kill init! 
exitcode=0x000b
[1.680948]
[1.690035] CPU1: stopping
[1.692727] CPU: 1 PID: 0 Comm: swapper/1 Tainted: G  D 
4.0.0-rc1-00062-g7a7cc79-dirty #123
[1.702097] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
[1.708192] [] (unwind_backtrace) from [] 
(show_stack+0x10/0x14)
[1.715908] [] (show_stack) from [] 
(dump_stack+0x78/0xc8)
[1.723108] [] (dump_stack) from [] 
(handle_IPI+0x16c/0x2b4)
[1.730485] [] (handle_IPI) from [] 
(gic_handle_irq+0x64/0x6c)
[1.738036] [] (gic_handle_irq) from [] 
(__irq_svc+0x40/0x74)
[1.745498] Exception stack(0xee8fdf98 to 0xee8fdfe0)
[1.750533] df80:   
 
[1.758695] dfa0: ee8fdfe8 c0021780 c09df938 0015 10c0387d c0a3d988 
4000406a c09df8d4
[1.766853] dfc0: c0a27a74 c09df940 0100 ee8fdfe0 c00101c0 c00101c4 
6113 
[1.775015] [] (__irq_svc) from [] 
(arch_cpu_idle+0x30/0x3c)
[1.782397] [] (arch_cpu_idle) from [] 
(cpu_startup_entry+0x180/0x324)
[1.790639] [] (cpu_startup_entry) from [<40008764>] (0x40008764)
[1.797579] CPU0: stopping
[1.800272] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G  D 
4.0.0-rc1-00062-g7a7cc79-dirty #123
[1.809642] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
[1.815730] [] (unwind_backtrace) from [] 
(show_stack+0x10/0x14)
[1.823450] [] (show_stack) from [] 
(dump_stack+0x78/0xc8)
[1.830653] [] (dump_stack) from [] 
(handle_IPI+0x16c/0x2b4)
[1.838030] [] (handle_IPI) from [] 
(gic_handle_irq+0x64/0x6c)
[1.845581] [] (gic_handle_irq) from [] 
(__irq_svc+0x40/0x74)
[1.853043] Exception stack(0xc09ddf60 to 0xc09ddfa8)
[1.858081] df60:   c09ddfb0 c0021780 c09df938 0001 
 c0a3d680
[1.866239] df80: c09c0dec c09df8d4 c0a27a74 c09df940 0100 c09ddfa8 
c00101c0 c00101c4
[1.874396] dfa0: 6113 
[1.877872] [] (__irq_svc) from [] 
(arch_cpu_idle+0x30/0x3c)
[1.885251] [] (arch_cpu_idle) from [] 
(cpu_startup_entry+0x180/0x324)
[1.893499] [] (cpu_startup_entry) from [] 
(start_kernel+0x324/0x37c)
[1.901655] [] (start_kernel) from [<40008074>] (0x40008074)
[1.908161] CPU3: stopping
[1.910855] CPU: 3 PID: 0 Comm: swapper/3 Tainted: G  D 
4.0.0-rc1-00062-g7a7cc79-dirty #123
[1.920225] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
[1.926313] [] (unwind_backtrace) from [] 
(show_stack+0x10/0x14)
[1.934034] [] (show_stack) from [] 
(dump_stack+0x78/0xc8)
[1.941237] [] (dump_stack) from [] 
(handle_IPI+0x16c/0x2b4)
[1.948613] [] (handle_IPI) from [] 
(gic_handle_irq+0x64/0x6c)
[1.956165] [] (gic_handle_irq) from [] 
(__irq_svc+0x40/0x74)
[1.963626] Exception stack(0xee901f98 to 0xee901fe0)
[1.968661] 1f80:   
 
[1.976823] 1fa0: ee901fe8 c0021780 c09df938 0015 10c0387d c0a3d988 
4000406a c09df8d4
[1.984982] 1fc0: c0a27a74 c09df940 0100 ee901fe0 c00101c0 c00101c4 
6113 
[1.993143] [] (__irq_svc) from [] 
(arch_cpu_idle+0x30/0x3c)
[2.000522] [] (arch_cpu_idle) from [] 
(cpu_startup_entry+0x180/0x324)
[2.008765] [] (cpu_startup_entry) from [<40008764>] (0x40008764)
[2.015710] ---[ end Kernel panic - not syncing: Attempted to kill init! 
exitcode=0x000b

Signed-off-by: Hyungwon Hwang 
Cc: Inki Dae 
---
 drivers/gpu/drm/exynos/exynos_drm_fimd.c | 31 +--
 1 file changed, 13 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c 
b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 925fc69..31dfa80 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -284,14 +284,9 @@ static void fimd_clear_channel(struct fimd_context *ctx)
}
 }

-static int fimd_ctx_initialize(struct fimd_context *ctx,
+static int fimd_iommu_attach_devices(struct fimd_context *ctx,
struct drm_device *drm_dev)
 {
-   struct exynos_drm_private *priv;
-   priv = drm_dev->dev_private;
-
-   ctx->drm_dev = drm_dev;
-   ctx->pipe = priv->pipe++;

/* attach this sub driver to iommu mapping if supported. */
if (is_drm_iommu_supported(ctx->drm_dev)) {
@@ -313,7 +308,7 @@ static int fimd_ctx_initialize(struct fimd_context *ctx,
return 0;
 }

-static void fimd_ctx_remove(struct fimd_context *ctx)
+static void fimd_iommu_detach_devices(struct fimd_context *ctx)
 {
/* detach this sub driver from iommu mapping if suppo

[PATCH] arm: dts: set panel clock properly for trats2 board

2015-03-12 Thread Hyungwon Hwang
Since commit abc0b1447d4974963548777a5ba4a4457c82c426 ("drm: Perform
basic sanity checks on probed modes"), it became mandatory to set
the pixel clock of the panel. This patch sets the pixel clock properly.

Signed-off-by: Hyungwon Hwang 
---
 arch/arm/boot/dts/exynos4412-trats2.dts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/exynos4412-trats2.dts 
b/arch/arm/boot/dts/exynos4412-trats2.dts
index 29231b4..073ff01 100644
--- a/arch/arm/boot/dts/exynos4412-trats2.dts
+++ b/arch/arm/boot/dts/exynos4412-trats2.dts
@@ -691,7 +691,7 @@

display-timings {
timing-0 {
-   clock-frequency = <0>;
+   clock-frequency = <6000>;
hactive = <720>;
vactive = <1280>;
hfront-porch = <5>;
-- 
1.9.1



[PATCH] drm/exynos: fix the number of overlay planes

2015-03-12 Thread Hyungwon Hwang
The number of overlay planes is one less than the maximum number of
planes, because the one is used for primary plane.

Signed-off-by: Hyungwon Hwang 
---
 drivers/gpu/drm/exynos/exynos_drm_drv.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c 
b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index 90168d7..98a239a 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -81,7 +81,7 @@ static int exynos_drm_load(struct drm_device *dev, unsigned 
long flags)

exynos_drm_mode_config_init(dev);

-   for (nr = 0; nr < MAX_PLANE; nr++) {
+   for (nr = 0; nr < MAX_PLANE - 1; nr++) {
struct drm_plane *plane;
unsigned long possible_crtcs = (1 << MAX_CRTC) - 1;

-- 
1.9.1



[PATCH 0/6] Add drivers for Exynos5433 display

2015-03-12 Thread Hyungwon Hwang
This patchset is based on the git(branch name: exynos-drm-next) which is
maintained by Inki Dae.
https://kernel.googlesource.com/pub/scm/linux/kernel/git/daeinki/drm-exynos.git

This patchset adds 2 new device drivers, decon and mic, and adds support for
Exynos5433 mipi dsi. To enable display in a Exynos5433 board, decon(display
controller), MIC(Mobile image compressor), mipi dsi, and panel have to be turned
on. This patchset contains support for 3 drivers for SoC level devices.

Donghwa Lee (1):
  drm/exynos: dsi: add support for Exynos5433 SoC

Hyungwon Hwang (4):
  of: add helper for getting endpoint node of specific identifiers
  drm/exynos: mic: add MIC driver
  drm/exynos: dsi: add support for MIC driver as a bridge
  drm/exynos: dsi: do not set TE GPIO direction by input

Joonyoung Shim (1):
  drm/exynos: add Exynos5433 decon driver

 .../devicetree/bindings/video/exynos-decon.txt |  65 +++
 .../devicetree/bindings/video/exynos-mic.txt   |  49 ++
 .../devicetree/bindings/video/exynos_dsim.txt  |  24 +-
 drivers/gpu/drm/exynos/Kconfig |  14 +-
 drivers/gpu/drm/exynos/Makefile|   2 +
 drivers/gpu/drm/exynos/exynos_drm_decon.c  | 539 +
 drivers/gpu/drm/exynos/exynos_drm_drv.c|   3 +
 drivers/gpu/drm/exynos/exynos_drm_drv.h|   1 +
 drivers/gpu/drm/exynos/exynos_drm_dsi.c| 459 --
 drivers/gpu/drm/exynos/exynos_drm_mic.c| 483 ++
 drivers/gpu/drm/exynos/regs-decon.h| 163 +++
 drivers/of/base.c  |  33 ++
 include/linux/of_graph.h   |   8 +
 13 files changed, 1697 insertions(+), 146 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/video/exynos-decon.txt
 create mode 100644 Documentation/devicetree/bindings/video/exynos-mic.txt
 create mode 100644 drivers/gpu/drm/exynos/exynos_drm_decon.c
 create mode 100644 drivers/gpu/drm/exynos/exynos_drm_mic.c
 create mode 100644 drivers/gpu/drm/exynos/regs-decon.h

--
1.9.1



[PATCH 1/6] drm/exynos: add Exynos5433 decon driver

2015-03-12 Thread Hyungwon Hwang
From: Joonyoung Shim 

DECON(Display and Enhancement Controller) is new IP replacing FIMD in
Exynos5433. This patch adds Exynos5433 decon driver.

Signed-off-by: Joonyoung Shim 
Signed-off-by: Hyungwon Hwang 
---
 .../devicetree/bindings/video/exynos-decon.txt |  65 +++
 drivers/gpu/drm/exynos/Kconfig |   6 +
 drivers/gpu/drm/exynos/Makefile|   1 +
 drivers/gpu/drm/exynos/exynos_drm_decon.c  | 539 +
 drivers/gpu/drm/exynos/exynos_drm_drv.c|   3 +
 drivers/gpu/drm/exynos/exynos_drm_drv.h|   1 +
 drivers/gpu/drm/exynos/regs-decon.h| 163 +++
 7 files changed, 778 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/video/exynos-decon.txt
 create mode 100644 drivers/gpu/drm/exynos/exynos_drm_decon.c
 create mode 100644 drivers/gpu/drm/exynos/regs-decon.h

diff --git a/Documentation/devicetree/bindings/video/exynos-decon.txt 
b/Documentation/devicetree/bindings/video/exynos-decon.txt
new file mode 100644
index 000..377afbf
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/exynos-decon.txt
@@ -0,0 +1,65 @@
+Device-Tree bindings for Samsung Exynos SoC display controller (DECON)
+
+DECON (Display and Enhancement Controller) is the Display Controller for the
+Exynos series of SoCs which transfers the image data from a video memory
+buffer to an external LCD interface.
+
+Required properties:
+- compatible: value should be "samsung,exynos5433-decon";
+- reg: physical base address and length of the DECON registers set.
+- interrupts: should contain a list of all DECON IP block interrupts in the
+ order: VSYNC, LCD_SYSTEM. The interrupt specifier format
+ depends on the interrupt controller used.
+- interrupt-names: should contain the interrupt names: "vsync", "lcd_sys"
+  in the same order as they were listed in the interrupts
+  property.
+- clocks: must include clock specifiers corresponding to entries in the
+ clock-names property.
+- clock-names: list of clock names sorted in the same order as the clocks
+  property. Must contain "aclk_decon", "aclk_smmu_decon0x",
+  "aclk_xiu_decon0x", "pclk_smmu_decon0x", clk_decon_vclk",
+  "sclk_decon_eclk"
+- ports: contains a port which is connected to mic node. address-cells and
+size-cells must 1 and 0, respectively.
+- port: contains an endpoint node which is connected to the endpoint in the mic
+   node. The reg value muset be 0.
+- i80-if-timings: specify whether the panel which is connected to decon uses
+ i80 lcd interface or mipi video interface. This node contains
+ no timing information as that of fimd does. Because there is
+ no register in decon to specify i80 interface timing value,
+ it is not needed, but make it remain to use same kind of node
+ in fimd and exynos7 decon.
+
+Example:
+SoC specific DT entry:
+decon: decon at 1380 {
+   compatible = "samsung,exynos5433-decon";
+   reg = <0x1380 0x2104>;
+   clocks = <&cmu_disp CLK_ACLK_DECON>, <&cmu_disp CLK_ACLK_SMMU_DECON0X>,
+   <&cmu_disp CLK_ACLK_XIU_DECON0X>,
+   <&cmu_disp CLK_PCLK_SMMU_DECON0X>,
+   <&cmu_disp CLK_SCLK_DECON_VCLK>,
+   <&cmu_disp CLK_SCLK_DECON_ECLK>;
+   clock-names = "aclk_decon", "aclk_smmu_decon0x", "aclk_xiu_decon0x",
+   "pclk_smmu_decon0x", "sclk_decon_vclk", "sclk_decon_eclk";
+   interrupt-names = "vsync", "lcd_sys";
+   interrupts = <0 202 0>, <0 203 0>;
+
+   ports {
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   port at 0 {
+   reg = <0>;
+   decon_to_mic: endpoint {
+   remote-endpoint = <&mic_to_decon>;
+   };
+   };
+   };
+};
+
+Board specific DT entry:
+&decon {
+   i80-if-timings {
+   };
+};
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index a5e7461..11acd6c 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -97,3 +97,9 @@ config DRM_EXYNOS_GSC
depends on DRM_EXYNOS_IPP && ARCH_EXYNOS5 && !ARCH_MULTIPLATFORM
help
  Choose this option if you want to use Exynos GSC for DRM.
+
+config DRM_EXYNOS_DECON
+   bool "Exynos DRM DECON"
+   depends on DRM_EXYNOS
+   help
+ Choose this option if you want to use Exynos DECON for DRM.
diff --git a/drivers/gpu/drm/exynos/Makefile b/dr

[PATCH 6/6] drm/exynos: dsi: do not set TE GPIO direction by input

2015-03-12 Thread Hyungwon Hwang
On some board, TE GPIO should be configured properly thoughout pinctrl driver
as an wakeup interrupt. So this gpio should be configurable in the board's DT,
not being requested as a input pin.

Signed-off-by: Hyungwon Hwang 
---
 drivers/gpu/drm/exynos/exynos_drm_dsi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c 
b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index e385d24..58e0620 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -1324,15 +1324,15 @@ static int exynos_dsi_register_te_irq(struct exynos_dsi 
*dsi)
goto out;
}

-   ret = gpio_request_one(dsi->te_gpio, GPIOF_IN, "te_gpio");
+   ret = gpio_request(dsi->te_gpio, "te_gpio");
if (ret) {
dev_err(dsi->dev, "gpio request failed with %d\n", ret);
goto out;
}

te_gpio_irq = gpio_to_irq(dsi->te_gpio);
-
irq_set_status_flags(te_gpio_irq, IRQ_NOAUTOEN);
+
ret = request_threaded_irq(te_gpio_irq, exynos_dsi_te_irq_handler, NULL,
IRQF_TRIGGER_RISING, "TE", dsi);
if (ret) {
-- 
1.9.1



[PATCH 5/6] drm/exynos: dsi: add support for MIC driver as a bridge

2015-03-12 Thread Hyungwon Hwang
MIC must be initilized by MIPI DSI when it is being bound.

Signed-off-by: Hyungwon Hwang 
---
 drivers/gpu/drm/exynos/exynos_drm_dsi.c | 24 
 1 file changed, 24 insertions(+)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c 
b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 77236ad..e385d24 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -280,6 +281,7 @@ struct exynos_dsi {
struct list_head transfer_list;

struct exynos_dsi_driver_data *driver_data;
+   struct device_node *bridge_node;
 };

 #define host_to_dsi(host) container_of(host, struct exynos_dsi, dsi_host)
@@ -1787,7 +1789,22 @@ static int exynos_dsi_parse_dt(struct exynos_dsi *dsi)

ret = exynos_dsi_of_read_u32(ep, "samsung,esc-clock-frequency",
 &dsi->esc_clk_rate);
+   if (ret < 0)
+   goto end;
+
+   of_node_put(ep);
+
+   ep = of_graph_get_next_endpoint(node, NULL);
+   if (!ep) {
+   ret = -ENXIO;
+   goto end;
+   }

+   dsi->bridge_node = of_graph_get_remote_port_parent(ep);
+   if (!dsi->bridge_node) {
+   ret = -ENXIO;
+   goto end;
+   }
 end:
of_node_put(ep);

@@ -1800,6 +1817,7 @@ static int exynos_dsi_bind(struct device *dev, struct 
device *master,
struct exynos_drm_display *display = dev_get_drvdata(dev);
struct exynos_dsi *dsi = display_to_dsi(display);
struct drm_device *drm_dev = data;
+   struct drm_bridge *bridge;
int ret;

ret = exynos_drm_create_enc_conn(drm_dev, display);
@@ -1809,6 +1827,12 @@ static int exynos_dsi_bind(struct device *dev, struct 
device *master,
return ret;
}

+   bridge = of_drm_find_bridge(dsi->bridge_node);
+   if (bridge) {
+   display->encoder->bridge = bridge;
+   drm_bridge_attach(drm_dev, bridge);
+   }
+
return mipi_dsi_host_register(&dsi->dsi_host);
 }

-- 
1.9.1



[PATCH 2/6] of: add helper for getting endpoint node of specific identifiers

2015-03-12 Thread Hyungwon Hwang
When there are multiple ports or multiple endpoints in a port, they have to be
distinguished by the value of reg property. It is common. The drivers can get
the specific endpoint in the specific port via this function. Now the drivers
have to implement this code in themselves or have to force the order of dt nodes
to get the right node.

Signed-off-by: Hyungwon Hwang 
Acked-by: Rob Herring 
---
 drivers/of/base.c| 33 +
 include/linux/of_graph.h |  8 
 2 files changed, 41 insertions(+)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index 36536b6..d7fa99d 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2155,6 +2155,39 @@ struct device_node *of_graph_get_next_endpoint(const 
struct device_node *parent,
 EXPORT_SYMBOL(of_graph_get_next_endpoint);

 /**
+ * of_graph_get_endpoint_by_regs() - get endpoint node of specific identifiers
+ * @parent: pointer to the parent device node
+ * @port_reg: identifier (value of reg property) of the parent port node
+ * @reg: identifier (value of reg property) of the endpoint node
+ *
+ * Return: An 'endpoint' node pointer which is identified by reg and at the 
same
+ * is the child of a port node identified by port_reg. reg and port_reg are
+ * ignored when they are -1.
+ */
+struct device_node *of_graph_get_endpoint_by_regs(
+   const struct device_node *parent, int port_reg, int reg)
+{
+   struct of_endpoint endpoint;
+   struct device_node *node, *prev_node = NULL;
+
+   while (1) {
+   node = of_graph_get_next_endpoint(parent, prev_node);
+   of_node_put(prev_node);
+   if (!node)
+   break;
+
+   of_graph_parse_endpoint(node, &endpoint);
+   if (((port_reg == -1) || (endpoint.port == port_reg)) &&
+   ((reg == -1) || (endpoint.id == reg)))
+   return node;
+
+   prev_node = node;
+   }
+
+   return NULL;
+}
+
+/**
  * of_graph_get_remote_port_parent() - get remote port's parent node
  * @node: pointer to a local endpoint device_node
  *
diff --git a/include/linux/of_graph.h b/include/linux/of_graph.h
index befef42..e859eb7 100644
--- a/include/linux/of_graph.h
+++ b/include/linux/of_graph.h
@@ -31,6 +31,8 @@ int of_graph_parse_endpoint(const struct device_node *node,
struct of_endpoint *endpoint);
 struct device_node *of_graph_get_next_endpoint(const struct device_node 
*parent,
struct device_node *previous);
+struct device_node *of_graph_get_endpoint_by_regs(
+   const struct device_node *parent, int port_reg, int reg);
 struct device_node *of_graph_get_remote_port_parent(
const struct device_node *node);
 struct device_node *of_graph_get_remote_port(const struct device_node *node);
@@ -49,6 +51,12 @@ static inline struct device_node *of_graph_get_next_endpoint(
return NULL;
 }

+struct device_node *of_graph_get_endpoint_by_regs(
+   const struct device_node *parent, int port_reg, int reg)
+{
+   return NULL;
+}
+
 static inline struct device_node *of_graph_get_remote_port_parent(
const struct device_node *node)
 {
-- 
1.9.1



[PATCH 3/6] drm/exynos: mic: add MIC driver

2015-03-12 Thread Hyungwon Hwang
MIC(Mobile image compressor) is newly added IP in Exynos5433. MIC
resides between decon and mipi dsim, and compresses frame data by 50%.
With dsi, not display port, to send frame data to the panel, the
bandwidth is not enough. That is why this compressor is introduced.

Signed-off-by: Hyungwon Hwang 
---
 .../devicetree/bindings/video/exynos-mic.txt   |  49 +++
 drivers/gpu/drm/exynos/Kconfig |   6 +
 drivers/gpu/drm/exynos/Makefile|   1 +
 drivers/gpu/drm/exynos/exynos_drm_mic.c| 483 +
 4 files changed, 539 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/video/exynos-mic.txt
 create mode 100644 drivers/gpu/drm/exynos/exynos_drm_mic.c

diff --git a/Documentation/devicetree/bindings/video/exynos-mic.txt 
b/Documentation/devicetree/bindings/video/exynos-mic.txt
new file mode 100644
index 000..0804389
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/exynos-mic.txt
@@ -0,0 +1,49 @@
+Device-Tree bindings for Samsung Exynos SoC display controller (DECON)
+
+DECON (Display and Enhancement Controller) is the Display Controller for the
+Exynos series of SoCs which transfers the image data from a video memory
+buffer to an external LCD interface.
+
+Required properties:
+- compatible: value should be "samsung,exynos5433-mic";
+- reg: physical base address and length of the DECON registers set and
+   system register of mic.
+- clocks: must include clock specifiers corresponding to entries in the
+ clock-names property.
+- clock-names: list of clock names sorted in the same order as the clocks
+  property. Must contain "aclk_decon", "aclk_smmu_decon0x",
+  "aclk_xiu_decon0x", "pclk_smmu_decon0x", clk_decon_vclk",
+  "sclk_decon_eclk"
+- ports: contains a port which is connected to decon node and dsi node.
+address-cells and size-cells must 1 and 0, respectively.
+- port: contains an endpoint node which is connected to the endpoint in the
+   decon node or dsi node. The reg value must be 0 and 1 respectively.
+
+Example:
+SoC specific DT entry:
+mic: mic at 1393 {
+   compatible = "samsung,exynos5433-mic";
+   reg = <0x1393 0x48 0x13B8 0x1010>;
+   clocks = <&cmu_disp CLK_PCLK_MIC0>,
+  <&cmu_disp CLK_SCLK_RGB_VCLK_TO_MIC0>;
+   clock-names = "pclk_mic0", "sclk_rgb_vclk_to_mic0";
+
+   ports {
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   port at 0 {
+   reg = <0>;
+   mic_to_decon: endpoint {
+   remote-endpoint = <&decon_to_mic>;
+   };
+   };
+
+   port at 1 {
+   reg = <1>;
+   mic_to_dsi: endpoint {
+   remote-endpoint = <&dsi_to_mic>;
+   };
+   };
+   };
+};
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index 11acd6c..52282ac 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -103,3 +103,9 @@ config DRM_EXYNOS_DECON
depends on DRM_EXYNOS
help
  Choose this option if you want to use Exynos DECON for DRM.
+
+config DRM_EXYNOS_MIC
+   bool "Exynos DRM MIC"
+   depends on DRM_EXYNOS
+   help
+ Choose this option if you want to use Exynos MIC for DRM.
diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile
index 915842d..ad05a88 100644
--- a/drivers/gpu/drm/exynos/Makefile
+++ b/drivers/gpu/drm/exynos/Makefile
@@ -22,5 +22,6 @@ exynosdrm-$(CONFIG_DRM_EXYNOS_FIMC)   += exynos_drm_fimc.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_ROTATOR) += exynos_drm_rotator.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_GSC) += exynos_drm_gsc.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_DECON)   += exynos_drm_decon.o
+exynosdrm-$(CONFIG_DRM_EXYNOS_MIC) += exynos_drm_mic.o

 obj-$(CONFIG_DRM_EXYNOS)   += exynosdrm.o
diff --git a/drivers/gpu/drm/exynos/exynos_drm_mic.c 
b/drivers/gpu/drm/exynos/exynos_drm_mic.c
new file mode 100644
index 000..c6d4fd1
--- /dev/null
+++ b/drivers/gpu/drm/exynos/exynos_drm_mic.c
@@ -0,0 +1,483 @@
+/*
+ * Copyright (C) 2014 Samsung Electronics Co.Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundationr
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* Sysreg registers for MIC */
+#define DSD_CFG_MUX0x1004
+#define MIC0_RGB_MUX   (1 << 0)
+#define MIC0_I80_MUX   (1 << 1)
+#define MIC0_ON_MUX(1 <

[PATCH 4/6] drm/exynos: dsi: add support for Exynos5433 SoC

2015-03-12 Thread Hyungwon Hwang
From: Donghwa Lee 

This patch adds support for Exynos5433. The goal is achieved by
1. Getting the address of registers from driver data
2. Getting the fixed value for registers from driver data
3. Getting different number of clocks using driver data
4. Getting max frequency of pixel clock from driver data

Signed-off-by: Donghwa Lee 
Signed-off-by: Hyungwon Hwang 
---
 .../devicetree/bindings/video/exynos_dsim.txt  |  24 +-
 drivers/gpu/drm/exynos/Kconfig |   2 +-
 drivers/gpu/drm/exynos/exynos_drm_dsi.c| 431 ++---
 3 files changed, 313 insertions(+), 144 deletions(-)

diff --git a/Documentation/devicetree/bindings/video/exynos_dsim.txt 
b/Documentation/devicetree/bindings/video/exynos_dsim.txt
index ca2b4aa..fea7718 100644
--- a/Documentation/devicetree/bindings/video/exynos_dsim.txt
+++ b/Documentation/devicetree/bindings/video/exynos_dsim.txt
@@ -6,6 +6,7 @@ Required properties:
"samsung,exynos4210-mipi-dsi" /* for Exynos4 SoCs */
"samsung,exynos4415-mipi-dsi" /* for Exynos4415 SoC */
"samsung,exynos5410-mipi-dsi" /* for Exynos5410/5420/5440 SoCs 
*/
+   "samsung,exynos5433-mipi-dsi" /* for Exynos5433 SoCs */
   - reg: physical base address and length of the registers set for the device
   - interrupts: should contain DSI interrupt
   - clocks: list of clock specifiers, must contain an entry for each required
@@ -30,10 +31,19 @@ Video interfaces:
   Device node can contain video interface port nodes according to [2].
   The following are properties specific to those nodes:

-  port node:
-- reg: (required) can be 0 for input RGB/I80 port or 1 for DSI port;
+  port node inbound:
+- reg: (required) must be 0.
+  port node outbound:
+- reg: (required) must be 1.

-  endpoint node of DSI port (reg = 1):
+  endpoint node connected from mic node (reg = 0):
+- remote-endpoint: specifies the endpoint in mic node. This node is 
required
+  for Exynos5433 mipi dsi. So mic can access to panel node
+  thoughout this dsi node.
+  endpoint node connected to panel node (reg = 1):
+- remote-endpoint: specifies the endpoint in panel node. This node is
+  required in all kinds of exynos mipi dsi to represent
+  the connection between mipi dsi and panel.
 - samsung,burst-clock-frequency: specifies DSI frequency in high-speed 
burst
   mode
 - samsung,esc-clock-frequency: specifies DSI frequency in escape mode
@@ -72,7 +82,15 @@ Example:
#address-cells = <1>;
#size-cells = <0>;

+   port at 0 {
+   reg = <0>;
+   decon_to_mic: endpoint {
+   remote-endpoint = <&mic_to_decon>;
+   };
+   };
+
port at 1 {
+   reg = <1>;
dsi_ep: endpoint {
reg = <0>;
samsung,burst-clock-frequency = 
<5>;
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index 52282ac..5d297dd 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -41,7 +41,7 @@ config DRM_EXYNOS_DPI

 config DRM_EXYNOS_DSI
bool "EXYNOS DRM MIPI-DSI driver support"
-   depends on (DRM_EXYNOS_FIMD || DRM_EXYNOS7_DECON)
+   depends on (DRM_EXYNOS_FIMD || DRM_EXYNOS_DECON || DRM_EXYNOS7_DECON)
select DRM_MIPI_DSI
select DRM_PANEL
default n
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c 
b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 05fe93d..77236ad 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -33,38 +33,6 @@
 /* returns true iff both arguments logically differs */
 #define NEQV(a, b) (!(a) ^ !(b))

-#define DSIM_STATUS_REG0x0 /* Status register */
-#define DSIM_SWRST_REG 0x4 /* Software reset register */
-#define DSIM_CLKCTRL_REG   0x8 /* Clock control register */
-#define DSIM_TIMEOUT_REG   0xc /* Time out register */
-#define DSIM_CONFIG_REG0x10/* Configuration register */
-#define DSIM_ESCMODE_REG   0x14/* Escape mode register */
-
-/* Main display image resolution register */
-#define DSIM_MDRESOL_REG   0x18
-#define DSIM_MVPORCH_REG   0x1c/* Main display Vporch register */
-#define DSIM_MHPORCH_REG   0x20/* Main display Hporch register */
-#define DSIM_MSYNC_REG 0x24/* Main display sync area register */
-
-/* Sub display image resolution register */
-#define DSIM_SDRESOL_REG   0x28
-#define DSIM_INTSRC_REG

[PATCH v2 2/6] of: add helper for getting endpoint node of specific identifiers

2015-03-18 Thread Hyungwon Hwang
When there are multiple ports or multiple endpoints in a port, they have to be
distinguished by the value of reg property. It is common. The drivers can get
the specific endpoint in the specific port via this function. Now the drivers
have to implement this code in themselves or have to force the order of dt nodes
to get the right node.

Signed-off-by: Hyungwon Hwang 
Acked-by: Rob Herring 
---
 drivers/of/base.c| 33 +
 include/linux/of_graph.h |  8 
 2 files changed, 41 insertions(+)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index 36536b6..d7fa99d 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2155,6 +2155,39 @@ struct device_node *of_graph_get_next_endpoint(const 
struct device_node *parent,
 EXPORT_SYMBOL(of_graph_get_next_endpoint);

 /**
+ * of_graph_get_endpoint_by_regs() - get endpoint node of specific identifiers
+ * @parent: pointer to the parent device node
+ * @port_reg: identifier (value of reg property) of the parent port node
+ * @reg: identifier (value of reg property) of the endpoint node
+ *
+ * Return: An 'endpoint' node pointer which is identified by reg and at the 
same
+ * is the child of a port node identified by port_reg. reg and port_reg are
+ * ignored when they are -1.
+ */
+struct device_node *of_graph_get_endpoint_by_regs(
+   const struct device_node *parent, int port_reg, int reg)
+{
+   struct of_endpoint endpoint;
+   struct device_node *node, *prev_node = NULL;
+
+   while (1) {
+   node = of_graph_get_next_endpoint(parent, prev_node);
+   of_node_put(prev_node);
+   if (!node)
+   break;
+
+   of_graph_parse_endpoint(node, &endpoint);
+   if (((port_reg == -1) || (endpoint.port == port_reg)) &&
+   ((reg == -1) || (endpoint.id == reg)))
+   return node;
+
+   prev_node = node;
+   }
+
+   return NULL;
+}
+
+/**
  * of_graph_get_remote_port_parent() - get remote port's parent node
  * @node: pointer to a local endpoint device_node
  *
diff --git a/include/linux/of_graph.h b/include/linux/of_graph.h
index befef42..e859eb7 100644
--- a/include/linux/of_graph.h
+++ b/include/linux/of_graph.h
@@ -31,6 +31,8 @@ int of_graph_parse_endpoint(const struct device_node *node,
struct of_endpoint *endpoint);
 struct device_node *of_graph_get_next_endpoint(const struct device_node 
*parent,
struct device_node *previous);
+struct device_node *of_graph_get_endpoint_by_regs(
+   const struct device_node *parent, int port_reg, int reg);
 struct device_node *of_graph_get_remote_port_parent(
const struct device_node *node);
 struct device_node *of_graph_get_remote_port(const struct device_node *node);
@@ -49,6 +51,12 @@ static inline struct device_node *of_graph_get_next_endpoint(
return NULL;
 }

+struct device_node *of_graph_get_endpoint_by_regs(
+   const struct device_node *parent, int port_reg, int reg)
+{
+   return NULL;
+}
+
 static inline struct device_node *of_graph_get_remote_port_parent(
const struct device_node *node)
 {
-- 
1.9.1



[PATCH v2 0/6] Add drivers for Exynos5433 display

2015-03-18 Thread Hyungwon Hwang
This patchset is based on the git(branch name: exynos-drm-next) which is
maintained by Inki Dae.
https://kernel.googlesource.com/pub/scm/linux/kernel/git/daeinki/drm-exynos.git

This patchset adds 2 new device drivers, decon and mic, and adds support for
Exynos5433 mipi dsi. To enable display in a Exynos5433 board, decon(display
controller), MIC(Mobile image compressor), mipi dsi, and panel have to be turned
on. This patchset contains support for 3 drivers for SoC level devices.

Changes for v2:
- change config, file, and variable names of decon to represnt exynos5433
instead of exynos to distinguish them from exynos7 decon
- change the initialization order of decon to make it initialized in order like
FIMD or exynos7 decon
- make mic driver to be registered by exynos drm driver instead as a module
driver
- change the description of mic driver in documentation
- add module author at the top of the source file removing MODULE_OWNER,
MODULE_DESCRIPTION, MODULE_LICENSE
- change the author of "drm/exynos: dsi: add support for Exynos5433 SoC" to
Hyungwon Hwang by the previous author's will

Hyungwon Hwang (5):
  of: add helper for getting endpoint node of specific identifiers
  drm/exynos: mic: add MIC driver
  drm/exynos: dsi: add support for Exynos5433 SoC
  drm/exynos: dsi: add support for MIC driver as a bridge
  drm/exynos: dsi: do not set TE GPIO direction by input

Joonyoung Shim (1):
  drm/exynos: add Exynos5433 decon driver

 .../devicetree/bindings/video/exynos-mic.txt   |  49 ++
 .../devicetree/bindings/video/exynos5433-decon.txt |  65 +++
 .../devicetree/bindings/video/exynos_dsim.txt  |  24 +-
 drivers/gpu/drm/exynos/Kconfig |  14 +-
 drivers/gpu/drm/exynos/Makefile|   2 +
 drivers/gpu/drm/exynos/exynos5433_drm_decon.c  | 543 +
 drivers/gpu/drm/exynos/exynos_drm_drv.c|   6 +
 drivers/gpu/drm/exynos/exynos_drm_drv.h|   2 +
 drivers/gpu/drm/exynos/exynos_drm_dsi.c| 459 +++--
 drivers/gpu/drm/exynos/exynos_drm_mic.c| 481 ++
 drivers/gpu/drm/exynos/regs-exynos5433-decon.h | 163 +++
 drivers/of/base.c  |  33 ++
 include/linux/of_graph.h   |   8 +
 13 files changed, 1703 insertions(+), 146 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/video/exynos-mic.txt
 create mode 100644 Documentation/devicetree/bindings/video/exynos5433-decon.txt
 create mode 100644 drivers/gpu/drm/exynos/exynos5433_drm_decon.c
 create mode 100644 drivers/gpu/drm/exynos/exynos_drm_mic.c
 create mode 100644 drivers/gpu/drm/exynos/regs-exynos5433-decon.h

--
1.9.1



[PATCH v2 5/6] drm/exynos: dsi: add support for MIC driver as a bridge

2015-03-18 Thread Hyungwon Hwang
MIC must be initilized by MIPI DSI when it is being bound.

Signed-off-by: Hyungwon Hwang 
---
 drivers/gpu/drm/exynos/exynos_drm_dsi.c | 24 
 1 file changed, 24 insertions(+)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c 
b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 77236ad..e385d24 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -280,6 +281,7 @@ struct exynos_dsi {
struct list_head transfer_list;

struct exynos_dsi_driver_data *driver_data;
+   struct device_node *bridge_node;
 };

 #define host_to_dsi(host) container_of(host, struct exynos_dsi, dsi_host)
@@ -1787,7 +1789,22 @@ static int exynos_dsi_parse_dt(struct exynos_dsi *dsi)

ret = exynos_dsi_of_read_u32(ep, "samsung,esc-clock-frequency",
 &dsi->esc_clk_rate);
+   if (ret < 0)
+   goto end;
+
+   of_node_put(ep);
+
+   ep = of_graph_get_next_endpoint(node, NULL);
+   if (!ep) {
+   ret = -ENXIO;
+   goto end;
+   }

+   dsi->bridge_node = of_graph_get_remote_port_parent(ep);
+   if (!dsi->bridge_node) {
+   ret = -ENXIO;
+   goto end;
+   }
 end:
of_node_put(ep);

@@ -1800,6 +1817,7 @@ static int exynos_dsi_bind(struct device *dev, struct 
device *master,
struct exynos_drm_display *display = dev_get_drvdata(dev);
struct exynos_dsi *dsi = display_to_dsi(display);
struct drm_device *drm_dev = data;
+   struct drm_bridge *bridge;
int ret;

ret = exynos_drm_create_enc_conn(drm_dev, display);
@@ -1809,6 +1827,12 @@ static int exynos_dsi_bind(struct device *dev, struct 
device *master,
return ret;
}

+   bridge = of_drm_find_bridge(dsi->bridge_node);
+   if (bridge) {
+   display->encoder->bridge = bridge;
+   drm_bridge_attach(drm_dev, bridge);
+   }
+
return mipi_dsi_host_register(&dsi->dsi_host);
 }

-- 
1.9.1



[PATCH v2 6/6] drm/exynos: dsi: do not set TE GPIO direction by input

2015-03-18 Thread Hyungwon Hwang
On some board, TE GPIO should be configured properly thoughout pinctrl driver
as an wakeup interrupt. So this gpio should be configurable in the board's DT,
not being requested as a input pin.

Signed-off-by: Hyungwon Hwang 
---
 drivers/gpu/drm/exynos/exynos_drm_dsi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c 
b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index e385d24..58e0620 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -1324,15 +1324,15 @@ static int exynos_dsi_register_te_irq(struct exynos_dsi 
*dsi)
goto out;
}

-   ret = gpio_request_one(dsi->te_gpio, GPIOF_IN, "te_gpio");
+   ret = gpio_request(dsi->te_gpio, "te_gpio");
if (ret) {
dev_err(dsi->dev, "gpio request failed with %d\n", ret);
goto out;
}

te_gpio_irq = gpio_to_irq(dsi->te_gpio);
-
irq_set_status_flags(te_gpio_irq, IRQ_NOAUTOEN);
+
ret = request_threaded_irq(te_gpio_irq, exynos_dsi_te_irq_handler, NULL,
IRQF_TRIGGER_RISING, "TE", dsi);
if (ret) {
-- 
1.9.1



[PATCH v2 1/6] drm/exynos: add Exynos5433 decon driver

2015-03-18 Thread Hyungwon Hwang
From: Joonyoung Shim 

DECON(Display and Enhancement Controller) is new IP replacing FIMD in
Exynos5433. This patch adds Exynos5433 decon driver.

Signed-off-by: Joonyoung Shim 
Signed-off-by: Hyungwon Hwang 
---
Changes for v2:
change file names and variable names of decon to represnt exynos5433 instead of
exynos to distinguish them from exynos7 decon
 .../devicetree/bindings/video/exynos5433-decon.txt |  65 +++
 drivers/gpu/drm/exynos/Kconfig |   6 +
 drivers/gpu/drm/exynos/Makefile|   1 +
 drivers/gpu/drm/exynos/exynos5433_drm_decon.c  | 543 +
 drivers/gpu/drm/exynos/exynos_drm_drv.c|   3 +
 drivers/gpu/drm/exynos/exynos_drm_drv.h|   1 +
 drivers/gpu/drm/exynos/regs-exynos5433-decon.h | 163 +++
 7 files changed, 782 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/video/exynos5433-decon.txt
 create mode 100644 drivers/gpu/drm/exynos/exynos5433_drm_decon.c
 create mode 100644 drivers/gpu/drm/exynos/regs-exynos5433-decon.h

diff --git a/Documentation/devicetree/bindings/video/exynos5433-decon.txt 
b/Documentation/devicetree/bindings/video/exynos5433-decon.txt
new file mode 100644
index 000..377afbf
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/exynos5433-decon.txt
@@ -0,0 +1,65 @@
+Device-Tree bindings for Samsung Exynos SoC display controller (DECON)
+
+DECON (Display and Enhancement Controller) is the Display Controller for the
+Exynos series of SoCs which transfers the image data from a video memory
+buffer to an external LCD interface.
+
+Required properties:
+- compatible: value should be "samsung,exynos5433-decon";
+- reg: physical base address and length of the DECON registers set.
+- interrupts: should contain a list of all DECON IP block interrupts in the
+ order: VSYNC, LCD_SYSTEM. The interrupt specifier format
+ depends on the interrupt controller used.
+- interrupt-names: should contain the interrupt names: "vsync", "lcd_sys"
+  in the same order as they were listed in the interrupts
+  property.
+- clocks: must include clock specifiers corresponding to entries in the
+ clock-names property.
+- clock-names: list of clock names sorted in the same order as the clocks
+  property. Must contain "aclk_decon", "aclk_smmu_decon0x",
+  "aclk_xiu_decon0x", "pclk_smmu_decon0x", clk_decon_vclk",
+  "sclk_decon_eclk"
+- ports: contains a port which is connected to mic node. address-cells and
+size-cells must 1 and 0, respectively.
+- port: contains an endpoint node which is connected to the endpoint in the mic
+   node. The reg value muset be 0.
+- i80-if-timings: specify whether the panel which is connected to decon uses
+ i80 lcd interface or mipi video interface. This node contains
+ no timing information as that of fimd does. Because there is
+ no register in decon to specify i80 interface timing value,
+ it is not needed, but make it remain to use same kind of node
+ in fimd and exynos7 decon.
+
+Example:
+SoC specific DT entry:
+decon: decon at 1380 {
+   compatible = "samsung,exynos5433-decon";
+   reg = <0x1380 0x2104>;
+   clocks = <&cmu_disp CLK_ACLK_DECON>, <&cmu_disp CLK_ACLK_SMMU_DECON0X>,
+   <&cmu_disp CLK_ACLK_XIU_DECON0X>,
+   <&cmu_disp CLK_PCLK_SMMU_DECON0X>,
+   <&cmu_disp CLK_SCLK_DECON_VCLK>,
+   <&cmu_disp CLK_SCLK_DECON_ECLK>;
+   clock-names = "aclk_decon", "aclk_smmu_decon0x", "aclk_xiu_decon0x",
+   "pclk_smmu_decon0x", "sclk_decon_vclk", "sclk_decon_eclk";
+   interrupt-names = "vsync", "lcd_sys";
+   interrupts = <0 202 0>, <0 203 0>;
+
+   ports {
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   port at 0 {
+   reg = <0>;
+   decon_to_mic: endpoint {
+   remote-endpoint = <&mic_to_decon>;
+   };
+   };
+   };
+};
+
+Board specific DT entry:
+&decon {
+   i80-if-timings {
+   };
+};
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index a5e7461..e15cc2e 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -24,6 +24,12 @@ config DRM_EXYNOS_FIMD
help
  Choose this option if you want to use Exynos FIMD for DRM.

+config DRM_EXYNOS5433_DECON
+   bool "Exynos5433 DRM DECON"
+   depends on DRM_EXYNOS
+   help
+ Choose this option if y

[PATCH v2 4/6] drm/exynos: dsi: add support for Exynos5433 SoC

2015-03-18 Thread Hyungwon Hwang
This patch adds support for Exynos5433. The goal is achieved by
1. Getting the address of registers from driver data
2. Getting the fixed value for registers from driver data
3. Getting different number of clocks using driver data
4. Getting max frequency of pixel clock from driver data

Signed-off-by: Donghwa Lee 
Signed-off-by: Hyungwon Hwang 
---
Changes for v2:
- change the author of "drm/exynos: dsi: add support for Exynos5433 SoC" to
Hyungwon Hwang by the previous author's will
 .../devicetree/bindings/video/exynos_dsim.txt  |  24 +-
 drivers/gpu/drm/exynos/Kconfig |   2 +-
 drivers/gpu/drm/exynos/exynos_drm_dsi.c| 431 ++---
 3 files changed, 313 insertions(+), 144 deletions(-)

diff --git a/Documentation/devicetree/bindings/video/exynos_dsim.txt 
b/Documentation/devicetree/bindings/video/exynos_dsim.txt
index ca2b4aa..fea7718 100644
--- a/Documentation/devicetree/bindings/video/exynos_dsim.txt
+++ b/Documentation/devicetree/bindings/video/exynos_dsim.txt
@@ -6,6 +6,7 @@ Required properties:
"samsung,exynos4210-mipi-dsi" /* for Exynos4 SoCs */
"samsung,exynos4415-mipi-dsi" /* for Exynos4415 SoC */
"samsung,exynos5410-mipi-dsi" /* for Exynos5410/5420/5440 SoCs 
*/
+   "samsung,exynos5433-mipi-dsi" /* for Exynos5433 SoCs */
   - reg: physical base address and length of the registers set for the device
   - interrupts: should contain DSI interrupt
   - clocks: list of clock specifiers, must contain an entry for each required
@@ -30,10 +31,19 @@ Video interfaces:
   Device node can contain video interface port nodes according to [2].
   The following are properties specific to those nodes:

-  port node:
-- reg: (required) can be 0 for input RGB/I80 port or 1 for DSI port;
+  port node inbound:
+- reg: (required) must be 0.
+  port node outbound:
+- reg: (required) must be 1.

-  endpoint node of DSI port (reg = 1):
+  endpoint node connected from mic node (reg = 0):
+- remote-endpoint: specifies the endpoint in mic node. This node is 
required
+  for Exynos5433 mipi dsi. So mic can access to panel node
+  thoughout this dsi node.
+  endpoint node connected to panel node (reg = 1):
+- remote-endpoint: specifies the endpoint in panel node. This node is
+  required in all kinds of exynos mipi dsi to represent
+  the connection between mipi dsi and panel.
 - samsung,burst-clock-frequency: specifies DSI frequency in high-speed 
burst
   mode
 - samsung,esc-clock-frequency: specifies DSI frequency in escape mode
@@ -72,7 +82,15 @@ Example:
#address-cells = <1>;
#size-cells = <0>;

+   port at 0 {
+   reg = <0>;
+   decon_to_mic: endpoint {
+   remote-endpoint = <&mic_to_decon>;
+   };
+   };
+
port at 1 {
+   reg = <1>;
dsi_ep: endpoint {
reg = <0>;
samsung,burst-clock-frequency = 
<5>;
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index a796175..eb35a21 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -47,7 +47,7 @@ config DRM_EXYNOS_DPI

 config DRM_EXYNOS_DSI
bool "EXYNOS DRM MIPI-DSI driver support"
-   depends on (DRM_EXYNOS_FIMD || DRM_EXYNOS7_DECON)
+   depends on (DRM_EXYNOS_FIMD || DRM_EXYNOS5433_DECON || 
DRM_EXYNOS7_DECON)
select DRM_MIPI_DSI
select DRM_PANEL
default n
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c 
b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 05fe93d..77236ad 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -33,38 +33,6 @@
 /* returns true iff both arguments logically differs */
 #define NEQV(a, b) (!(a) ^ !(b))

-#define DSIM_STATUS_REG0x0 /* Status register */
-#define DSIM_SWRST_REG 0x4 /* Software reset register */
-#define DSIM_CLKCTRL_REG   0x8 /* Clock control register */
-#define DSIM_TIMEOUT_REG   0xc /* Time out register */
-#define DSIM_CONFIG_REG0x10/* Configuration register */
-#define DSIM_ESCMODE_REG   0x14/* Escape mode register */
-
-/* Main display image resolution register */
-#define DSIM_MDRESOL_REG   0x18
-#define DSIM_MVPORCH_REG   0x1c/* Main display Vporch register */
-#define DSIM_MHPORCH_REG   0x20/* Main display Hporch register */
-#define DSIM_MSYNC_REG 0x24/* Main display syn

[PATCH v2 3/6] drm/exynos: mic: add MIC driver

2015-03-18 Thread Hyungwon Hwang
MIC(Mobile image compressor) is newly added IP in Exynos5433. MIC
resides between decon and mipi dsim, and compresses frame data by 50%.
With dsi, not display port, to send frame data to the panel, the
bandwidth is not enough. That is why this compressor is introduced.

Signed-off-by: Hyungwon Hwang 
---
Changes for v2:
- make mic driver to be registered by exynos drm driver instead as a module 
 |  
-
driver  
 |  
-
- change the description of mic driver in documentation
- add module author at the top of the source file removing MODULE_OWNER,
MODULE_DESCRIPTION, MODULE_LICENSE
 .../devicetree/bindings/video/exynos-mic.txt   |  49 +++
 drivers/gpu/drm/exynos/Kconfig |   6 +
 drivers/gpu/drm/exynos/Makefile|   1 +
 drivers/gpu/drm/exynos/exynos_drm_drv.c|   3 +
 drivers/gpu/drm/exynos/exynos_drm_drv.h|   1 +
 drivers/gpu/drm/exynos/exynos_drm_mic.c| 481 +
 6 files changed, 541 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/video/exynos-mic.txt
 create mode 100644 drivers/gpu/drm/exynos/exynos_drm_mic.c

diff --git a/Documentation/devicetree/bindings/video/exynos-mic.txt 
b/Documentation/devicetree/bindings/video/exynos-mic.txt
new file mode 100644
index 000..006d072
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/exynos-mic.txt
@@ -0,0 +1,49 @@
+Device-Tree bindings for Samsung Exynos SoC mobile image compressor (MIC)
+
+MIC (mobile image compressor) resides between decon and mipi dsi. Mipi dsi is
+not capable to transfer high resoltuion frame data as decon can send. MIC
+solves this problem by compressing the frame data by 1/2 before it is 
transfered
+through mipi dsi. The compressed frame data must be uncompressed in the panel
+PCB.
+
+Required properties:
+- compatible: value should be "samsung,exynos5433-mic".
+- reg: physical base address and length of the MIC registers set and system
+   register of mic.
+- clocks: must include clock specifiers corresponding to entries in the
+ clock-names property.
+- clock-names: list of clock names sorted in the same order as the clocks
+  property. Must contain "pclk_mic0", "sclk_rgb_vclk_to_mic0".
+- ports: contains a port which is connected to decon node and dsi node.
+address-cells and size-cells must 1 and 0, respectively.
+- port: contains an endpoint node which is connected to the endpoint in the
+   decon node or dsi node. The reg value must be 0 and 1 respectively.
+
+Example:
+SoC specific DT entry:
+mic: mic at 1393 {
+   compatible = "samsung,exynos5433-mic";
+   reg = <0x1393 0x48 0x13B8 0x1010>;
+   clocks = <&cmu_disp CLK_PCLK_MIC0>,
+  <&cmu_disp CLK_SCLK_RGB_VCLK_TO_MIC0>;
+   clock-names = "pclk_mic0", "sclk_rgb_vclk_to_mic0";
+
+   ports {
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   port at 0 {
+   reg = <0>;
+   mic_to_decon: endpoint {
+   remote-endpoint = <&decon_to_mic>;
+   };
+   };
+
+   port at 1 {
+   reg = <1>;
+   mic_to_dsi: endpoint {
+   remote-endpoint = <&dsi_to_mic>;
+   };
+   };
+   };
+};
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index e15cc2e..a796175 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -103,3 +103,9 @@ config DRM_EXYNOS_GSC
depends on DRM_EXYNOS_IPP && ARCH_EXYNOS5 && !ARCH_MULTIPLATFORM
help
  Choose this option if you want to use Exynos GSC for DRM.
+
+config DRM_EXYNOS_MIC
+   bool "Exynos DRM MIC"
+   depends on (DRM_EXYNOS && DRM_EXYNOS5433_DECON)
+   help
+ Choose this option if you want to use Exynos MIC for DRM.
diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile
index fbd084d..7de0b10 100644
--- a/drivers/gpu/drm/exynos/Makefile
+++ b/drivers/gpu/drm/exynos/Makefile
@@ -22,5 +22,6 @@ exynosdrm-$(CONFIG_DRM_EXYNOS_IPP)+= exynos_drm_ipp.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_FIMC)+= exynos_drm_fimc.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_ROTATOR) += exynos_drm_rotator.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_GSC) += exynos_drm_gsc.o
+exynosdrm-$(CONFIG_DRM_EXYNOS_MIC) += exyn

[PATCH v2 4/6] drm/exynos: dsi: add support for Exynos5433 SoC

2015-03-19 Thread Hyungwon Hwang
Dear Daniel,

On Wed, 18 Mar 2015 09:52:33 +
Daniel Stone  wrote:

> Hi,
> 
> On 18 March 2015 at 08:16, Hyungwon Hwang 
> wrote:
> > +#define REG(dsi, reg)  ((dsi)->reg_base +
> > dsi->driver_data->regs[(reg)])
> 
> This seems like a good change in general, but please split it up: it
> makes bisection much easier if you have one patch which adds no
> functionality and should have exactly the same behaviour, and then
> another patch which introduces your changes.

Yes. I agree with you.

> 
> > @@ -431,15 +579,11 @@ static unsigned long
> > exynos_dsi_set_pll(struct exynos_dsi *dsi, u16 m;
> > u32 reg;
> >
> > -   clk_set_rate(dsi->pll_clk, dsi->pll_clk_rate);
> > -
> > -   fin = clk_get_rate(dsi->pll_clk);
> > -   if (!fin) {
> > -   dev_err(dsi->dev, "failed to get PLL clock
> > frequency\n");
> > -   return 0;
> > -   }
> > -
> > -   dev_dbg(dsi->dev, "PLL input frequency: %lu\n", fin);
> > +   /*
> > +* The input PLL clock for MIPI DSI in Exynos5433 seems to
> > be fixed
> > +* by OSC CLK.
> > +*/
> > +   fin = 24 * MHZ;
> 
> Er, is this always true on other platforms as well? Shouldn't this be
> a part of the DeviceTree description?

I forgot to change the comment in development. Finally it is found that
all exynos mipi dsi's fin is OSC clk which is 24 MHz. So I will remove
the comment, but remain the code as it is.

> 
> > @@ -509,7 +656,7 @@ static int exynos_dsi_enable_clock(struct
> > exynos_dsi *dsi) dev_dbg(dsi->dev, "hs_clk = %lu, byte_clk = %lu,
> > esc_clk = %lu\n", hs_clk, byte_clk, esc_clk);
> >
> > -   reg = readl(dsi->reg_base + DSIM_CLKCTRL_REG);
> > +   reg = readl(REG(dsi, DSIM_CLKCTRL_REG));
> 
> Instead of this readl(REG()) pattern you have everywhere, maybe it
> would be easier to introduce a dsi_read_reg(dsi, reg_enum_value)
> helper, and the same for write_reg.

I think that it can make the code more readable. I agree.

> 
> > @@ -1720,18 +1873,16 @@ static int exynos_dsi_probe(struct
> > platform_device *pdev) return -EPROBE_DEFER;
> > }
> >
> > -   dsi->pll_clk = devm_clk_get(dev, "pll_clk");
> > -   if (IS_ERR(dsi->pll_clk)) {
> > -   dev_info(dev, "failed to get dsi pll input
> > clock\n");
> > -   ret = PTR_ERR(dsi->pll_clk);
> > -   goto err_del_component;
> > -   }
> > -
> > -   dsi->bus_clk = devm_clk_get(dev, "bus_clk");
> > -   if (IS_ERR(dsi->bus_clk)) {
> > -   dev_info(dev, "failed to get dsi bus clock\n");
> > -   ret = PTR_ERR(dsi->bus_clk);
> > -   goto err_del_component;
> > +   dsi->clks = devm_kzalloc(dev,
> > +   sizeof(*dsi->clks) *
> > dsi->driver_data->num_clks,
> > +   GFP_KERNEL);
> > +   for (i = 0; i < dsi->driver_data->num_clks; i++) {
> > +   dsi->clks[i] = devm_clk_get(dev, clk_names[i]);
> > +   if (IS_ERR(dsi->clks[i])) {
> > +   dev_info(dev, "failed to get dsi pll input
> > clock\n");
> 
> This error message seems wrong; it should contain the name of the
> actual failing clock.

Oh. I forgot. I will change it.

Thanks for your review. I will send it again with the changes you
suggested.

> 
> Cheers,
> Daniel



[PATCH v2 4/6] drm/exynos: dsi: add support for Exynos5433 SoC

2015-03-19 Thread Hyungwon Hwang
Dear Daniel,

On Thu, 19 Mar 2015 01:13:21 +
Daniel Stone  wrote:

> Hi Hyungwon,
> 
> On 19 March 2015 at 01:02, Hyungwon Hwang 
> wrote:
> >> > +   /*
> >> > +* The input PLL clock for MIPI DSI in Exynos5433 seems
> >> > to be fixed
> >> > +* by OSC CLK.
> >> > +*/
> >> > +   fin = 24 * MHZ;
> >>
> >> Er, is this always true on other platforms as well? Shouldn't this
> >> be a part of the DeviceTree description?
> >
> > I forgot to change the comment in development. Finally it is found
> > that all exynos mipi dsi's fin is OSC clk which is 24 MHz. So I
> > will remove the comment, but remain the code as it is.
> 
> Fair enough. Should pll_clk be removed from the DT description then,
> if it's fixed to the oscillator?

Yes. It is redundant to represent pll_clk in DT, and it should be
removed.

> 
> > Thanks for your review. I will send it again with the changes you
> > suggested.
> 
> Thanks very much!
> 
> Cheers,
> Daniel

Best regards,
Hyungwon Hwang


[PATCH v2 4/6] drm/exynos: dsi: add support for Exynos5433 SoC

2015-03-20 Thread Hyungwon Hwang
Dear Andrej,

On Thu, 19 Mar 2015 10:32:10 +0100
Andrzej Hajda  wrote:

> On 03/19/2015 02:18 AM, Hyungwon Hwang wrote:
> > Dear Daniel,
> > 
> > On Thu, 19 Mar 2015 01:13:21 +
> > Daniel Stone  wrote:
> > 
> >> Hi Hyungwon,
> >>
> >> On 19 March 2015 at 01:02, Hyungwon Hwang
> >>  wrote:
> >>>>> +   /*
> >>>>> +* The input PLL clock for MIPI DSI in Exynos5433 seems
> >>>>> to be fixed
> >>>>> +* by OSC CLK.
> >>>>> +*/
> >>>>> +   fin = 24 * MHZ;
> >>>>
> >>>> Er, is this always true on other platforms as well? Shouldn't
> >>>> this be a part of the DeviceTree description?
> >>>
> >>> I forgot to change the comment in development. Finally it is found
> >>> that all exynos mipi dsi's fin is OSC clk which is 24 MHz. So I
> >>> will remove the comment, but remain the code as it is.
> >>
> >> Fair enough. Should pll_clk be removed from the DT description
> >> then, if it's fixed to the oscillator?
> > 
> > Yes. It is redundant to represent pll_clk in DT, and it should be
> > removed.
> 
> Why do you think OSC clk determines value of pll_clk?
> pll_clk is mapped to SCLK_MIPI[01] or SCLK_DSIM0 gate with few
> dividers and muxes above. So at least in theory it can differ from
> osc clk. Additionally this gate should be enabled so you cannot just
> remove it from DT.
> 
> Regards
> Andrzej

As I found, pll clk is not SCLK_MIPI[01] but OSC CLK. SCLK_DSIM0 must
be controlled in this driver as it has been, as a gate clock of MIPI
DSI block, but not as a pll clk. SCLK_DSIM0 is not the input
clock of MIPI DPHY which provides fin in this code. So clock setting
and getting code was wrong, and must be removed.

OSC CLK is not soc-depedendant but board-dependant, even though I have
not seen any board which does not use OSC CLK by 24 MHz. It must be
parsed from board DT file, which in this case, we can use the value in
pll_clk_rate (the variable name must be renamed also).

Because ambiguous description in the technical document, I can be
wrong. Please let me know if I do not understand something. Thanks for
your comment.

Best regards,
Hyungwon Hwang

> 
> > 
> >>
> >>> Thanks for your review. I will send it again with the changes you
> >>> suggested.
> >>
> >> Thanks very much!
> >>
> >> Cheers,
> >> Daniel
> > 
> > Best regards,
> > Hyungwon Hwang
> > --
> > To unsubscribe from this list: send the line "unsubscribe
> > devicetree" in the body of a message to
> > majordomo-u79uwXL29TY76Z2rM5mHXA at public.gmane.org More majordomo
> > info at  http://vger.kernel.org/majordomo-info.html
> > 
> 



[PATCH v2 4/6] drm/exynos: dsi: add support for Exynos5433 SoC

2015-03-23 Thread Hyungwon Hwang
Dear Andrej,

On Mon, 23 Mar 2015 10:31:58 +0100
Andrzej Hajda  wrote:

> On 03/20/2015 06:15 AM, Hyungwon Hwang wrote:
> > Dear Andrej,
> >
> > On Thu, 19 Mar 2015 10:32:10 +0100
> > Andrzej Hajda  wrote:
> >
> >> On 03/19/2015 02:18 AM, Hyungwon Hwang wrote:
> >>> Dear Daniel,
> >>>
> >>> On Thu, 19 Mar 2015 01:13:21 +
> >>> Daniel Stone 
> >>> wrote:
> >>>
> >>>> Hi Hyungwon,
> >>>>
> >>>> On 19 March 2015 at 01:02, Hyungwon Hwang
> >>>>  wrote:
> >>>>>>> +   /*
> >>>>>>> +* The input PLL clock for MIPI DSI in Exynos5433
> >>>>>>> seems to be fixed
> >>>>>>> +* by OSC CLK.
> >>>>>>> +*/
> >>>>>>> +   fin = 24 * MHZ;
> >>>>>> Er, is this always true on other platforms as well? Shouldn't
> >>>>>> this be a part of the DeviceTree description?
> >>>>> I forgot to change the comment in development. Finally it is
> >>>>> found that all exynos mipi dsi's fin is OSC clk which is 24
> >>>>> MHz. So I will remove the comment, but remain the code as it is.
> >>>> Fair enough. Should pll_clk be removed from the DT description
> >>>> then, if it's fixed to the oscillator?
> >>> Yes. It is redundant to represent pll_clk in DT, and it should be
> >>> removed.
> >> Why do you think OSC clk determines value of pll_clk?
> >> pll_clk is mapped to SCLK_MIPI[01] or SCLK_DSIM0 gate with few
> >> dividers and muxes above. So at least in theory it can differ from
> >> osc clk. Additionally this gate should be enabled so you cannot
> >> just remove it from DT.
> >>
> >> Regards
> >> Andrzej
> > As I found, pll clk is not SCLK_MIPI[01] but OSC CLK. SCLK_DSIM0
> > must be controlled in this driver as it has been, as a gate clock
> > of MIPI DSI block, but not as a pll clk. SCLK_DSIM0 is not the input
> > clock of MIPI DPHY which provides fin in this code. So clock setting
> > and getting code was wrong, and must be removed.
> >
> > OSC CLK is not soc-depedendant but board-dependant, even though I
> > have not seen any board which does not use OSC CLK by 24 MHz. It
> > must be parsed from board DT file, which in this case, we can use
> > the value in pll_clk_rate (the variable name must be renamed also).
> >
> > Because ambiguous description in the technical document, I can be
> > wrong. Please let me know if I do not understand something. Thanks
> > for your comment.
> 
> After some digging I agree that documentation is quite confusing and
> current code could be wrong. Anyway I wonder if it wouldn't be better
> to explicitly provide input clock for DSIM, or more precisely for its
> PLL instead of hardcoding 24MHz into the driver.

OK. I agree. It will be more explicit to get the clock rate from DT.

> 
> Another thing that bothers me is relation of DPHY_PLL in clock
> controller to MIPI_DPHY in Exynos7420. There are two clocks used by
> MIPI_DPHY:
> - "Ref Clock" pinned to SCLK_MIPIDPHY_M4 connected to OSCCLK,
> - "PHY Clock" pinned to I_FOUT_DPHY_PLL connected to DPHY_PLL,
> 
> The first clock seems to be your osc clock, but what is the role of
> the 2nd one?

Hmm, I couldn't find similar clock in Exynos5433, also I don't have
the manual for Exynos7420.

Best regards,
Hyungwon Hwang


> 
> Regards
> Andrzej
> 
> > Best regards,
> > Hyungwon Hwang
> >
> >>>>> Thanks for your review. I will send it again with the changes
> >>>>> you suggested.
> >>>> Thanks very much!
> >>>>
> >>>> Cheers,
> >>>> Daniel
> >>> Best regards,
> >>> Hyungwon Hwang
> >>> --
> >>> To unsubscribe from this list: send the line "unsubscribe
> >>> devicetree" in the body of a message to
> >>> majordomo-u79uwXL29TY76Z2rM5mHXA at public.gmane.org More majordomo
> >>> info at  http://vger.kernel.org/majordomo-info.html
> >>>
> 



[PATCH v2 1/6] drm/exynos: add Exynos5433 decon driver

2015-03-26 Thread Hyungwon Hwang
Dear Daniel,

On Wed, 18 Mar 2015 12:24:40 +
Daniel Stone  wrote:

> Hi,
> Some feedback comments - most of these are not unique to your 5433
> DECON driver but endemic throughout Exynos, so I don't blame you for
> them - but they should be fixed anyway.
> 
> On 18 March 2015 at 08:16, Hyungwon Hwang 
> wrote:
> > +static void decon_dpms_on(struct exynos_decon *decon)
> > +{
> > +   int ret;
> > +   int i;
> > +
> > +   for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++) {
> > +   ret = clk_prepare_enable(decon->clks[i]);
> > +   if (ret < 0)
> > +   goto err;
> > +   }
> > +
> > +   set_bit(BIT_CLKS_ENABLED, &decon->enabled);
> 
> Do you really not even need to set a control register?
> 
> > +static void decon_commit(struct exynos_drm_crtc *crtc)
> > +{
> > +   struct exynos_decon *decon = crtc->ctx;
> > +   struct drm_display_mode *mode = &crtc->base.mode;
> > +   u32 val;
> > +
> > +   /* enable clock gate */
> > +   val = CMU_CLKGAGE_MODE_SFR_F | CMU_CLKGAGE_MODE_MEM_F;
> > +   writel(val, decon->addr + DECON_CMU);
> > +
> > +   /* lcd on and use command if */
> > +   val = VIDOUT_LCD_ON;
> > +   if (decon->i80_if)
> > +   val |= VIDOUT_COMMAND_IF;
> > +   else
> > +   val |= VIDOUT_RGB_IF;
> > +   writel(val, decon->addr + DECON_VIDOUTCON0);
> 
> This seems much more likely to be DPMS, no?
> 
> > +   [...]
> > +   /* enable output and display signal */
> > +   val = VIDCON0_ENVID | VIDCON0_ENVID_F;
> > +   writel(val, decon->addr + DECON_VIDCON0);
> 
> As does this.
> 
> Have you tested DPMS on/off, without enabling/disabling the CRTC
> first? Does it work?

Yes. I misunderstanded the behavior of the driver. I will send the
fixed version for working DPMS. Thanks.

> 
> > +static void decon_win_mode_set(struct exynos_drm_crtc *crtc,
> > +  struct exynos_drm_plane *plane)
> > +{
> > +   struct exynos_decon *decon = crtc->ctx;
> > +   struct decon_reg_data *reg_data;
> > +   unsigned int bytes_per_pixel = plane->bpp >> 3;
> > +   unsigned int val_h;
> > +   unsigned int val_l;
> > +   unsigned int win;
> > +   dma_addr_t addr;
> > +   u32 val = 0;
> > +
> > +   if (!plane) {
> > +   DRM_ERROR("plane is NULL\n");
> > +   return;
> > +   }
> > +
> > +   win = plane->zpos;
> > +   if (win == DEFAULT_ZPOS)
> > +   win = 0;
> > +
> > +   if (win < 0 || win >= 5)
> > +   return;
> 
> It would be nice to have a #define for the largest-supported window
> number.

Yes. That would be better.

> 
> > +   reg_data = &decon->reg_data[win];
> > +
> > +   switch (plane->pixel_format) {
> > +   case DRM_FORMAT_XRGB1555:
> > +   val |= WINCONx_BPPMODE_16BPP_I1555;
> > +   val |= WINCONx_HAWSWP_F;
> > +   val |= WINCONx_BURSTLEN_16WORD;
> > +   break;
> > +   case DRM_FORMAT_RGB565:
> > +   val |= WINCONx_BPPMODE_16BPP_565;
> > +   val |= WINCONx_HAWSWP_F;
> > +   val |= WINCONx_BURSTLEN_16WORD;
> > +   break;
> > +   case DRM_FORMAT_XRGB:
> > +   val |= WINCONx_BPPMODE_24BPP_888;
> > +   val |= WINCONx_WSWP_F;
> > +   val |= WINCONx_BURSTLEN_16WORD;
> > +   break;
> > +   case DRM_FORMAT_ARGB:
> > +   val |= WINCONx_BPPMODE_32BPP_A;
> > +   val |= WINCONx_WSWP_F | WINCONx_BLD_PIX_F |
> > WINCONx_ALPHA_SEL_F;
> > +   val |= WINCONx_BURSTLEN_16WORD;
> > +   break;
> > +   default:
> 
> Please remove the 'default' case. If you get here with a format you
> don't know how to configure, then it is a bug and should be fixed: the
> plane should never advertise a format that it cannot support.
> 

Yes. I agree.

> > +   val |= WINCONx_BPPMODE_24BPP_888;
> > +   val |= WINCONx_WSWP_F;
> > +   val |= WINCONx_BURSTLEN_16WORD;
> > +   break;
> > +   }
> > +
> > +   reg_data->wincon = val;
> > +   reg_data->vidosd_a = COORDINATE_X(plane->crtc_x) |
> > 

[PATCH v2 3/6] drm/exynos: mic: add MIC driver

2015-03-26 Thread Hyungwon Hwang
Dear Inki dae,

On Tue, 24 Mar 2015 14:51:31 +0900
Inki Dae  wrote:

> On 2015년 03월 18일 17:16, Hyungwon Hwang wrote:
> > MIC(Mobile image compressor) is newly added IP in Exynos5433. MIC
> > resides between decon and mipi dsim, and compresses frame data by
> > 50%. With dsi, not display port, to send frame data to the panel,
> > the bandwidth is not enough. That is why this compressor is
> > introduced.
> > 
> > Signed-off-by: Hyungwon Hwang 
> > ---
> > Changes for v2:
> > - make mic driver to be registered by exynos drm driver instead as
> > a module  |
> > -
> > driver
> > |
> > -
> > - change the description of mic driver in documentation
> > - add module author at the top of the source file removing
> > MODULE_OWNER, MODULE_DESCRIPTION, MODULE_LICENSE
> >  .../devicetree/bindings/video/exynos-mic.txt   |  49 +++
> >  drivers/gpu/drm/exynos/Kconfig |   6 +
> >  drivers/gpu/drm/exynos/Makefile|   1 +
> >  drivers/gpu/drm/exynos/exynos_drm_drv.c|   3 +
> >  drivers/gpu/drm/exynos/exynos_drm_drv.h|   1 +
> >  drivers/gpu/drm/exynos/exynos_drm_mic.c| 481
> > + 6 files changed, 541 insertions(+)
> >  create mode 100644
> > Documentation/devicetree/bindings/video/exynos-mic.txt create mode
> > 100644 drivers/gpu/drm/exynos/exynos_drm_mic.c
> > 
> > diff --git a/Documentation/devicetree/bindings/video/exynos-mic.txt
> > b/Documentation/devicetree/bindings/video/exynos-mic.txt new file
> > mode 100644 index 000..006d072
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/video/exynos-mic.txt
> > @@ -0,0 +1,49 @@
> > +Device-Tree bindings for Samsung Exynos SoC mobile image
> > compressor (MIC) +
> > +MIC (mobile image compressor) resides between decon and mipi dsi.
> > Mipi dsi is +not capable to transfer high resoltuion frame data as
> > decon can send. MIC +solves this problem by compressing the frame
> > data by 1/2 before it is transfered +through mipi dsi. The
> > compressed frame data must be uncompressed in the panel +PCB.
> > +
> > +Required properties:
> > +- compatible: value should be "samsung,exynos5433-mic".
> > +- reg: physical base address and length of the MIC registers set
> > and system
> > +   register of mic.
> > +- clocks: must include clock specifiers corresponding to entries
> > in the
> > + clock-names property.
> > +- clock-names: list of clock names sorted in the same order as the
> > clocks
> > +  property. Must contain "pclk_mic0",
> > "sclk_rgb_vclk_to_mic0". +- ports: contains a port which is
> > connected to decon node and dsi node.
> > +address-cells and size-cells must 1 and 0, respectively.
> > +- port: contains an endpoint node which is connected to the
> > endpoint in the
> > +   decon node or dsi node. The reg value must be 0 and 1
> > respectively. +
> > +Example:
> > +SoC specific DT entry:
> > +mic: mic at 1393 {
> > +   compatible = "samsung,exynos5433-mic";
> > +   reg = <0x1393 0x48 0x13B8 0x1010>;
> > +   clocks = <&cmu_disp CLK_PCLK_MIC0>,
> > +  <&cmu_disp CLK_SCLK_RGB_VCLK_TO_MIC0>;
> > +   clock-names = "pclk_mic0", "sclk_rgb_vclk_to_mic0";
> > +
> > +   ports {
> > +   #address-cells = <1>;
> > +   #size-cells = <0>;
> > +
> > +   port at 0 {
> > +   reg = <0>;
> > +   mic_to_decon: endpoint {
> > +   remote-endpoint = <&decon_to_mic>;
> > +   };
> > +   };
> > +
> > +   port at 1 {
> > +   reg = <1>;
> > +   mic_to_dsi: endpoint {
> > +   remote-endpoint = <&dsi_to_mic>;
> > +   };
> > +   };
> > +   };
> > +};
> > diff --git a/drivers/gpu/drm/exynos/Kconfig
> > b/drivers/gpu/drm/exynos/Kconfig index e15cc2e..a796175 100644
> > --- a/drivers/gpu/drm/exynos/Kconfig
> > +++ b/drivers/gpu/drm/exynos/Kconfig
> > @@ -103,3 +103,9 @@ config DRM_EXYNOS_GSC
> > depen

[PATCH v2 3/6] drm/exynos: mic: add MIC driver

2015-03-26 Thread Hyungwon Hwang
Dear Inki dae,

Sorry for the previous mail which is not completed. I typed something
and it was the shortcut for maybe.

On Tue, 24 Mar 2015 14:51:31 +0900
Inki Dae  wrote:

> On 2015년 03월 18일 17:16, Hyungwon Hwang wrote:
> > MIC(Mobile image compressor) is newly added IP in Exynos5433. MIC
> > resides between decon and mipi dsim, and compresses frame data by
> > 50%. With dsi, not display port, to send frame data to the panel,
> > the bandwidth is not enough. That is why this compressor is
> > introduced.
> > 
> > Signed-off-by: Hyungwon Hwang 
> > ---
> > Changes for v2:
> > - make mic driver to be registered by exynos drm driver instead as
> > a module  |
> > -
> > driver
> > |
> > -
> > - change the description of mic driver in documentation
> > - add module author at the top of the source file removing
> > MODULE_OWNER, MODULE_DESCRIPTION, MODULE_LICENSE
> >  .../devicetree/bindings/video/exynos-mic.txt   |  49 +++
> >  drivers/gpu/drm/exynos/Kconfig |   6 +
> >  drivers/gpu/drm/exynos/Makefile|   1 +
> >  drivers/gpu/drm/exynos/exynos_drm_drv.c|   3 +
> >  drivers/gpu/drm/exynos/exynos_drm_drv.h|   1 +
> >  drivers/gpu/drm/exynos/exynos_drm_mic.c| 481
> > + 6 files changed, 541 insertions(+)
> >  create mode 100644
> > Documentation/devicetree/bindings/video/exynos-mic.txt create mode
> > 100644 drivers/gpu/drm/exynos/exynos_drm_mic.c
> > 
> > diff --git a/Documentation/devicetree/bindings/video/exynos-mic.txt
> > b/Documentation/devicetree/bindings/video/exynos-mic.txt new file
> > mode 100644 index 000..006d072
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/video/exynos-mic.txt
> > @@ -0,0 +1,49 @@
> > +Device-Tree bindings for Samsung Exynos SoC mobile image
> > compressor (MIC) +
> > +MIC (mobile image compressor) resides between decon and mipi dsi.
> > Mipi dsi is +not capable to transfer high resoltuion frame data as
> > decon can send. MIC +solves this problem by compressing the frame
> > data by 1/2 before it is transfered +through mipi dsi. The
> > compressed frame data must be uncompressed in the panel +PCB.
> > +
> > +Required properties:
> > +- compatible: value should be "samsung,exynos5433-mic".
> > +- reg: physical base address and length of the MIC registers set
> > and system
> > +   register of mic.
> > +- clocks: must include clock specifiers corresponding to entries
> > in the
> > + clock-names property.
> > +- clock-names: list of clock names sorted in the same order as the
> > clocks
> > +  property. Must contain "pclk_mic0",
> > "sclk_rgb_vclk_to_mic0". +- ports: contains a port which is
> > connected to decon node and dsi node.
> > +address-cells and size-cells must 1 and 0, respectively.
> > +- port: contains an endpoint node which is connected to the
> > endpoint in the
> > +   decon node or dsi node. The reg value must be 0 and 1
> > respectively. +
> > +Example:
> > +SoC specific DT entry:
> > +mic: mic at 1393 {
> > +   compatible = "samsung,exynos5433-mic";
> > +   reg = <0x1393 0x48 0x13B8 0x1010>;
> > +   clocks = <&cmu_disp CLK_PCLK_MIC0>,
> > +  <&cmu_disp CLK_SCLK_RGB_VCLK_TO_MIC0>;
> > +   clock-names = "pclk_mic0", "sclk_rgb_vclk_to_mic0";
> > +
> > +   ports {
> > +   #address-cells = <1>;
> > +   #size-cells = <0>;
> > +
> > +   port at 0 {
> > +   reg = <0>;
> > +   mic_to_decon: endpoint {
> > +   remote-endpoint = <&decon_to_mic>;
> > +   };
> > +   };
> > +
> > +   port at 1 {
> > +   reg = <1>;
> > +   mic_to_dsi: endpoint {
> > +   remote-endpoint = <&dsi_to_mic>;
> > +   };
> > +   };
> > +   };
> > +};
> > diff --git a/drivers/gpu/drm/exynos/Kconfig
> > b/drivers/gpu/drm/exynos/Kconfig index e15cc2e..a796175 100644
> > --- a/drivers/gpu/drm/exynos/Kconfig
> >

[PATCH v2 4/6] drm/exynos: dsi: add support for Exynos5433 SoC

2015-03-26 Thread Hyungwon Hwang
Dear Daniel,

On Wed, 18 Mar 2015 09:52:33 +
Daniel Stone  wrote:

> Hi,
> 
> On 18 March 2015 at 08:16, Hyungwon Hwang 
> wrote:
> > +#define REG(dsi, reg)  ((dsi)->reg_base +
> > dsi->driver_data->regs[(reg)])
> 
> This seems like a good change in general, but please split it up: it
> makes bisection much easier if you have one patch which adds no
> functionality and should have exactly the same behaviour, and then
> another patch which introduces your changes.
> 

Yes. That also looks good to me.

> > @@ -431,15 +579,11 @@ static unsigned long
> > exynos_dsi_set_pll(struct exynos_dsi *dsi, u16 m;
> > u32 reg;
> >
> > -   clk_set_rate(dsi->pll_clk, dsi->pll_clk_rate);
> > -
> > -   fin = clk_get_rate(dsi->pll_clk);
> > -   if (!fin) {
> > -   dev_err(dsi->dev, "failed to get PLL clock
> > frequency\n");
> > -   return 0;
> > -   }
> > -
> > -   dev_dbg(dsi->dev, "PLL input frequency: %lu\n", fin);
> > +   /*
> > +* The input PLL clock for MIPI DSI in Exynos5433 seems to
> > be fixed
> > +* by OSC CLK.
> > +*/
> > +   fin = 24 * MHZ;
> 
> Er, is this always true on other platforms as well? Shouldn't this be
> a part of the DeviceTree description?
> 
> > @@ -509,7 +656,7 @@ static int exynos_dsi_enable_clock(struct
> > exynos_dsi *dsi) dev_dbg(dsi->dev, "hs_clk = %lu, byte_clk = %lu,
> > esc_clk = %lu\n", hs_clk, byte_clk, esc_clk);
> >
> > -   reg = readl(dsi->reg_base + DSIM_CLKCTRL_REG);
> > +   reg = readl(REG(dsi, DSIM_CLKCTRL_REG));
> 
> Instead of this readl(REG()) pattern you have everywhere, maybe it
> would be easier to introduce a dsi_read_reg(dsi, reg_enum_value)
> helper, and the same for write_reg.
> 

Yes. That's resonable.

> > @@ -1720,18 +1873,16 @@ static int exynos_dsi_probe(struct
> > platform_device *pdev) return -EPROBE_DEFER;
> > }
> >
> > -   dsi->pll_clk = devm_clk_get(dev, "pll_clk");
> > -   if (IS_ERR(dsi->pll_clk)) {
> > -   dev_info(dev, "failed to get dsi pll input
> > clock\n");
> > -   ret = PTR_ERR(dsi->pll_clk);
> > -   goto err_del_component;
> > -   }
> > -
> > -   dsi->bus_clk = devm_clk_get(dev, "bus_clk");
> > -   if (IS_ERR(dsi->bus_clk)) {
> > -   dev_info(dev, "failed to get dsi bus clock\n");
> > -   ret = PTR_ERR(dsi->bus_clk);
> > -   goto err_del_component;
> > +   dsi->clks = devm_kzalloc(dev,
> > +   sizeof(*dsi->clks) *
> > dsi->driver_data->num_clks,
> > +   GFP_KERNEL);
> > +   for (i = 0; i < dsi->driver_data->num_clks; i++) {
> > +   dsi->clks[i] = devm_clk_get(dev, clk_names[i]);
> > +   if (IS_ERR(dsi->clks[i])) {
> > +   dev_info(dev, "failed to get dsi pll input
> > clock\n");
> 
> This error message seems wrong; it should contain the name of the
> actual failing clock.
> 

OK.

Best regards,
Hyungwon Hwang

> Cheers,
> Daniel



[PATCH v3 0/8] Add drivers for Exynos5433 display

2015-03-26 Thread Hyungwon Hwang
This patchset is based on the git(branch name: exynos-drm-next) which is
maintained by Inki Dae.
https://kernel.googlesource.com/pub/scm/linux/kernel/git/...

This patchset adds 2 new device drivers, decon and mic, and adds support for
Exynos5433 mipi dsi. To enable display in a Exynos5433 board, decon(display
controller), MIC(Mobile image compressor), mipi dsi, and panel have to be turned
on. This patchset contains support for 3 drivers for SoC level devices.

Changes for v2:
- change config, file, and variable names of decon to represnt exynos5433
instead of exynos to distinguish them from exynos7 decon
- change the initialization order of decon to make it initialized in order like
FIMD or exynos7 decon
- make mic driver to be registered by exynos drm driver instead as a module
driver
- change the description of mic driver in documentation
- add module author at the top of the source file removing MODULE_OWNER,
MODULE_DESCRIPTION, MODULE_LICENSE
- change the author of "drm/exynos: dsi: add support for Exynos5433 SoC" to
Hyungwon Hwang by the previous author's will

Changes for v3:
< Decon >
 - fail fast when the proper image format is not set
 - remove unnecessary checking code
 - add and modify the function to make DPMS work well
< MIC >
 - move if statement out of function, so that the function is not called
 unnecessarily
 - Make it use syscon framework for controlling system register
< DSI >
 - separate the previous one patch to three
   - renaming patch: rename pll clock to sclk clock
   - generalizing patch: generalize the way to getting address and values
   - Exynos5433 patch: adds support for Exynos5433 dsi
 - use defines for more readable code
 - fix typos

Hyungwon Hwang (7):
  of: add helper for getting endpoint node of specific identifiers
  drm/exynos: mic: add MIC driver
  drm/exynos: dsi: rename pll_clk to sclk_clk
  drm/exynos: dsi: generalize register setting and clock control
  drm/exynos: dsi: add support for Exynos5433
  drm/exynos: dsi: add support for MIC driver as a bridge
  drm/exynos: dsi: do not set TE GPIO direction by input

Joonyoung Shim (1):
  drm/exynos: add Exynos5433 decon driver

 .../devicetree/bindings/video/exynos-mic.txt   |  51 ++
 .../devicetree/bindings/video/exynos5433-decon.txt |  65 ++
 .../devicetree/bindings/video/exynos_dsim.txt  |  30 +-
 drivers/gpu/drm/exynos/Kconfig |  14 +-
 drivers/gpu/drm/exynos/Makefile|   2 +
 drivers/gpu/drm/exynos/exynos5433_drm_decon.c  | 665 +
 drivers/gpu/drm/exynos/exynos_drm_drv.c|   6 +
 drivers/gpu/drm/exynos/exynos_drm_drv.h|   2 +
 drivers/gpu/drm/exynos/exynos_drm_dsi.c| 453 +-
 drivers/gpu/drm/exynos/exynos_drm_mic.c| 490 +++
 drivers/of/base.c  |  33 +
 include/linux/of_graph.h   |   8 +
 include/video/exynos5433_decon.h   | 163 +
 13 files changed, 1832 insertions(+), 150 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/video/exynos-mic.txt
 create mode 100644 Documentation/devicetree/bindings/video/exynos5433-decon.txt
 create mode 100644 drivers/gpu/drm/exynos/exynos5433_drm_decon.c
 create mode 100644 drivers/gpu/drm/exynos/exynos_drm_mic.c
 create mode 100644 include/video/exynos5433_decon.h

--
1.9.1



[PATCH v3 1/8] drm/exynos: add Exynos5433 decon driver

2015-03-26 Thread Hyungwon Hwang
From: Joonyoung Shim 

DECON(Display and Enhancement Controller) is new IP replacing FIMD in
Exynos5433. This patch adds Exynos5433 decon driver.

Signed-off-by: Joonyoung Shim 
Signed-off-by: Hyungwon Hwang 
---
Changes for v2:
 - change file names and variable names of decon to represnt exynos5433 instead
 of exynos to distinguish them from exynos7 decon

Changes for v3:
 - fail fast when the proper image format is not set
 - remove unnecessary checking code
 - add and modify the function to make DPMS work well
 .../devicetree/bindings/video/exynos5433-decon.txt |  65 ++
 drivers/gpu/drm/exynos/Kconfig |   6 +
 drivers/gpu/drm/exynos/Makefile|   1 +
 drivers/gpu/drm/exynos/exynos5433_drm_decon.c  | 665 +
 drivers/gpu/drm/exynos/exynos_drm_drv.c|   3 +
 drivers/gpu/drm/exynos/exynos_drm_drv.h|   1 +
 include/video/exynos5433_decon.h   | 163 +
 7 files changed, 904 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/video/exynos5433-decon.txt
 create mode 100644 drivers/gpu/drm/exynos/exynos5433_drm_decon.c
 create mode 100644 include/video/exynos5433_decon.h

diff --git a/Documentation/devicetree/bindings/video/exynos5433-decon.txt 
b/Documentation/devicetree/bindings/video/exynos5433-decon.txt
new file mode 100644
index 000..377afbf
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/exynos5433-decon.txt
@@ -0,0 +1,65 @@
+Device-Tree bindings for Samsung Exynos SoC display controller (DECON)
+
+DECON (Display and Enhancement Controller) is the Display Controller for the
+Exynos series of SoCs which transfers the image data from a video memory
+buffer to an external LCD interface.
+
+Required properties:
+- compatible: value should be "samsung,exynos5433-decon";
+- reg: physical base address and length of the DECON registers set.
+- interrupts: should contain a list of all DECON IP block interrupts in the
+ order: VSYNC, LCD_SYSTEM. The interrupt specifier format
+ depends on the interrupt controller used.
+- interrupt-names: should contain the interrupt names: "vsync", "lcd_sys"
+  in the same order as they were listed in the interrupts
+  property.
+- clocks: must include clock specifiers corresponding to entries in the
+ clock-names property.
+- clock-names: list of clock names sorted in the same order as the clocks
+  property. Must contain "aclk_decon", "aclk_smmu_decon0x",
+  "aclk_xiu_decon0x", "pclk_smmu_decon0x", clk_decon_vclk",
+  "sclk_decon_eclk"
+- ports: contains a port which is connected to mic node. address-cells and
+size-cells must 1 and 0, respectively.
+- port: contains an endpoint node which is connected to the endpoint in the mic
+   node. The reg value muset be 0.
+- i80-if-timings: specify whether the panel which is connected to decon uses
+ i80 lcd interface or mipi video interface. This node contains
+ no timing information as that of fimd does. Because there is
+ no register in decon to specify i80 interface timing value,
+ it is not needed, but make it remain to use same kind of node
+ in fimd and exynos7 decon.
+
+Example:
+SoC specific DT entry:
+decon: decon at 1380 {
+   compatible = "samsung,exynos5433-decon";
+   reg = <0x1380 0x2104>;
+   clocks = <&cmu_disp CLK_ACLK_DECON>, <&cmu_disp CLK_ACLK_SMMU_DECON0X>,
+   <&cmu_disp CLK_ACLK_XIU_DECON0X>,
+   <&cmu_disp CLK_PCLK_SMMU_DECON0X>,
+   <&cmu_disp CLK_SCLK_DECON_VCLK>,
+   <&cmu_disp CLK_SCLK_DECON_ECLK>;
+   clock-names = "aclk_decon", "aclk_smmu_decon0x", "aclk_xiu_decon0x",
+   "pclk_smmu_decon0x", "sclk_decon_vclk", "sclk_decon_eclk";
+   interrupt-names = "vsync", "lcd_sys";
+   interrupts = <0 202 0>, <0 203 0>;
+
+   ports {
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   port at 0 {
+   reg = <0>;
+   decon_to_mic: endpoint {
+   remote-endpoint = <&mic_to_decon>;
+   };
+   };
+   };
+};
+
+Board specific DT entry:
+&decon {
+   i80-if-timings {
+   };
+};
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index c8001c2..d9dc408 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -24,6 +24,12 @@ config DRM_EXYNOS_FIMD
help
  Choose this option if you want to use Exynos FIMD for DRM.

[PATCH v3 2/8] of: add helper for getting endpoint node of specific identifiers

2015-03-26 Thread Hyungwon Hwang
When there are multiple ports or multiple endpoints in a port, they have to be
distinguished by the value of reg property. It is common. The drivers can get
the specific endpoint in the specific port via this function. Now the drivers
have to implement this code in themselves or have to force the order of dt nodes
to get the right node.

Signed-off-by: Hyungwon Hwang 
Acked-by: Rob Herring 
---
Changes for v2:
 - None

Changes for v3:
 - None

 drivers/of/base.c| 33 +
 include/linux/of_graph.h |  8 
 2 files changed, 41 insertions(+)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index adb8764..ffc2235 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2165,6 +2165,39 @@ struct device_node *of_graph_get_next_endpoint(const 
struct device_node *parent,
 EXPORT_SYMBOL(of_graph_get_next_endpoint);

 /**
+ * of_graph_get_endpoint_by_regs() - get endpoint node of specific identifiers
+ * @parent: pointer to the parent device node
+ * @port_reg: identifier (value of reg property) of the parent port node
+ * @reg: identifier (value of reg property) of the endpoint node
+ *
+ * Return: An 'endpoint' node pointer which is identified by reg and at the 
same
+ * is the child of a port node identified by port_reg. reg and port_reg are
+ * ignored when they are -1.
+ */
+struct device_node *of_graph_get_endpoint_by_regs(
+   const struct device_node *parent, int port_reg, int reg)
+{
+   struct of_endpoint endpoint;
+   struct device_node *node, *prev_node = NULL;
+
+   while (1) {
+   node = of_graph_get_next_endpoint(parent, prev_node);
+   of_node_put(prev_node);
+   if (!node)
+   break;
+
+   of_graph_parse_endpoint(node, &endpoint);
+   if (((port_reg == -1) || (endpoint.port == port_reg)) &&
+   ((reg == -1) || (endpoint.id == reg)))
+   return node;
+
+   prev_node = node;
+   }
+
+   return NULL;
+}
+
+/**
  * of_graph_get_remote_port_parent() - get remote port's parent node
  * @node: pointer to a local endpoint device_node
  *
diff --git a/include/linux/of_graph.h b/include/linux/of_graph.h
index befef42..e859eb7 100644
--- a/include/linux/of_graph.h
+++ b/include/linux/of_graph.h
@@ -31,6 +31,8 @@ int of_graph_parse_endpoint(const struct device_node *node,
struct of_endpoint *endpoint);
 struct device_node *of_graph_get_next_endpoint(const struct device_node 
*parent,
struct device_node *previous);
+struct device_node *of_graph_get_endpoint_by_regs(
+   const struct device_node *parent, int port_reg, int reg);
 struct device_node *of_graph_get_remote_port_parent(
const struct device_node *node);
 struct device_node *of_graph_get_remote_port(const struct device_node *node);
@@ -49,6 +51,12 @@ static inline struct device_node *of_graph_get_next_endpoint(
return NULL;
 }

+struct device_node *of_graph_get_endpoint_by_regs(
+   const struct device_node *parent, int port_reg, int reg)
+{
+   return NULL;
+}
+
 static inline struct device_node *of_graph_get_remote_port_parent(
const struct device_node *node)
 {
-- 
1.9.1



[PATCH v3 4/8] drm/exynos: dsi: rename pll_clk to sclk_clk

2015-03-26 Thread Hyungwon Hwang
This patch renames pll_clk to sclk_clk. The clock referenced by pll_clk
is actually not the pll input clock for dsi. The pll input clock comes
from the board's oscillator directly.

Signed-off-by: Hyungwon Hwang 
---
Changes for v3:
 - Newly added
 .../devicetree/bindings/video/exynos_dsim.txt  |  6 ++---
 drivers/gpu/drm/exynos/exynos_drm_dsi.c| 31 --
 2 files changed, 14 insertions(+), 23 deletions(-)

diff --git a/Documentation/devicetree/bindings/video/exynos_dsim.txt 
b/Documentation/devicetree/bindings/video/exynos_dsim.txt
index 802aa7e..39940ca 100644
--- a/Documentation/devicetree/bindings/video/exynos_dsim.txt
+++ b/Documentation/devicetree/bindings/video/exynos_dsim.txt
@@ -10,13 +10,13 @@ Required properties:
   - interrupts: should contain DSI interrupt
   - clocks: list of clock specifiers, must contain an entry for each required
 entry in clock-names
-  - clock-names: should include "bus_clk"and "pll_clk" entries
+  - clock-names: should include "bus_clk"and "sclk_mipi" entries
   - phys: list of phy specifiers, must contain an entry for each required
 entry in phy-names
   - phy-names: should include "dsim" entry
   - vddcore-supply: MIPI DSIM Core voltage supply (e.g. 1.1V)
   - vddio-supply: MIPI DSIM I/O and PLL voltage supply (e.g. 1.8V)
-  - samsung,pll-clock-frequency: specifies frequency of the "pll_clk" clock
+  - samsung,pll-clock-frequency: specifies frequency of the oscillator clock
   - #address-cells, #size-cells: should be set respectively to <1> and <0>
 according to DSI host bindings (see MIPI DSI bindings [1])

@@ -48,7 +48,7 @@ Example:
reg = <0x11C8 0x1>;
interrupts = <0 79 0>;
clocks = <&clock 286>, <&clock 143>;
-   clock-names = "bus_clk", "pll_clk";
+   clock-names = "bus_clk", "sclk_mipi";
phys = <&mipi_phy 1>;
phy-names = "dsim";
vddcore-supply = <&vusb_reg>;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c 
b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 05fe93d..4af18b2f 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -277,7 +277,7 @@ struct exynos_dsi {

void __iomem *reg_base;
struct phy *phy;
-   struct clk *pll_clk;
+   struct clk *sclk_clk;
struct clk *bus_clk;
struct regulator_bulk_data supplies[2];
int irq;
@@ -431,16 +431,7 @@ static unsigned long exynos_dsi_set_pll(struct exynos_dsi 
*dsi,
u16 m;
u32 reg;

-   clk_set_rate(dsi->pll_clk, dsi->pll_clk_rate);
-
-   fin = clk_get_rate(dsi->pll_clk);
-   if (!fin) {
-   dev_err(dsi->dev, "failed to get PLL clock frequency\n");
-   return 0;
-   }
-
-   dev_dbg(dsi->dev, "PLL input frequency: %lu\n", fin);
-
+   fin = dsi->pll_clk_rate;
fout = exynos_dsi_pll_find_pms(dsi, fin, freq, &p, &m, &s);
if (!fout) {
dev_err(dsi->dev,
@@ -1308,10 +1299,10 @@ static int exynos_dsi_poweron(struct exynos_dsi *dsi)
goto err_bus_clk;
}

-   ret = clk_prepare_enable(dsi->pll_clk);
+   ret = clk_prepare_enable(dsi->sclk_clk);
if (ret < 0) {
dev_err(dsi->dev, "cannot enable pll clock %d\n", ret);
-   goto err_pll_clk;
+   goto err_sclk_clk;
}

ret = phy_power_on(dsi->phy);
@@ -1323,8 +1314,8 @@ static int exynos_dsi_poweron(struct exynos_dsi *dsi)
return 0;

 err_phy:
-   clk_disable_unprepare(dsi->pll_clk);
-err_pll_clk:
+   clk_disable_unprepare(dsi->sclk_clk);
+err_sclk_clk:
clk_disable_unprepare(dsi->bus_clk);
 err_bus_clk:
regulator_bulk_disable(ARRAY_SIZE(dsi->supplies), dsi->supplies);
@@ -1350,7 +1341,7 @@ static void exynos_dsi_poweroff(struct exynos_dsi *dsi)

phy_power_off(dsi->phy);

-   clk_disable_unprepare(dsi->pll_clk);
+   clk_disable_unprepare(dsi->sclk_clk);
clk_disable_unprepare(dsi->bus_clk);

ret = regulator_bulk_disable(ARRAY_SIZE(dsi->supplies), dsi->supplies);
@@ -1720,10 +1711,10 @@ static int exynos_dsi_probe(struct platform_device 
*pdev)
return -EPROBE_DEFER;
}

-   dsi->pll_clk = devm_clk_get(dev, "pll_clk");
-   if (IS_ERR(dsi->pll_clk)) {
-   dev_info(dev, "failed to get dsi pll input clock\n");
-   ret = PTR_ERR(dsi->pll_clk);
+   dsi->sclk_clk = devm_clk_get(dev, "sclk_mipi");
+   if (IS_ERR(dsi->sclk_clk)) {
+   dev_info(dev, "failed to get dsi sclk clock\n");
+   ret = PTR_ERR(dsi->sclk_clk);
goto err_del_component;
}

-- 
1.9.1



[PATCH v3 8/8] drm/exynos: dsi: do not set TE GPIO direction by input

2015-03-26 Thread Hyungwon Hwang
On some board, TE GPIO should be configured properly thoughout pinctrl driver
as an wakeup interrupt. So this gpio should be configurable in the board's DT,
not being requested as a input pin.

Signed-off-by: Hyungwon Hwang 
---
Changes for v2:
 - None

Changes for v3:
 - None

 drivers/gpu/drm/exynos/exynos_drm_dsi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c 
b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index d382511..230082a 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -1316,15 +1316,15 @@ static int exynos_dsi_register_te_irq(struct exynos_dsi 
*dsi)
goto out;
}

-   ret = gpio_request_one(dsi->te_gpio, GPIOF_IN, "te_gpio");
+   ret = gpio_request(dsi->te_gpio, "te_gpio");
if (ret) {
dev_err(dsi->dev, "gpio request failed with %d\n", ret);
goto out;
}

te_gpio_irq = gpio_to_irq(dsi->te_gpio);
-
irq_set_status_flags(te_gpio_irq, IRQ_NOAUTOEN);
+
ret = request_threaded_irq(te_gpio_irq, exynos_dsi_te_irq_handler, NULL,
IRQF_TRIGGER_RISING, "TE", dsi);
if (ret) {
-- 
1.9.1



[PATCH v3 5/8] drm/exynos: dsi: generalize register setting and clock control

2015-03-26 Thread Hyungwon Hwang
This patch makes the driver use arrays for clocks, register address,
and values. By doing this, it becomes easier to add support for another
SoC.

Signed-off-by: Hyungwon Hwang 
---
Changes for v3:
 - Separated from the patch "drm/exynos: dsi: add support for Exynos5433 SoC"
 in version 2.
 drivers/gpu/drm/exynos/exynos_drm_dsi.c | 347 
 1 file changed, 218 insertions(+), 129 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c 
b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 4af18b2f..2d9a249 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -33,38 +33,6 @@
 /* returns true iff both arguments logically differs */
 #define NEQV(a, b) (!(a) ^ !(b))

-#define DSIM_STATUS_REG0x0 /* Status register */
-#define DSIM_SWRST_REG 0x4 /* Software reset register */
-#define DSIM_CLKCTRL_REG   0x8 /* Clock control register */
-#define DSIM_TIMEOUT_REG   0xc /* Time out register */
-#define DSIM_CONFIG_REG0x10/* Configuration register */
-#define DSIM_ESCMODE_REG   0x14/* Escape mode register */
-
-/* Main display image resolution register */
-#define DSIM_MDRESOL_REG   0x18
-#define DSIM_MVPORCH_REG   0x1c/* Main display Vporch register */
-#define DSIM_MHPORCH_REG   0x20/* Main display Hporch register */
-#define DSIM_MSYNC_REG 0x24/* Main display sync area register */
-
-/* Sub display image resolution register */
-#define DSIM_SDRESOL_REG   0x28
-#define DSIM_INTSRC_REG0x2c/* Interrupt source register */
-#define DSIM_INTMSK_REG0x30/* Interrupt mask register */
-#define DSIM_PKTHDR_REG0x34/* Packet Header FIFO register 
*/
-#define DSIM_PAYLOAD_REG   0x38/* Payload FIFO register */
-#define DSIM_RXFIFO_REG0x3c/* Read FIFO register */
-#define DSIM_FIFOTHLD_REG  0x40/* FIFO threshold level register */
-#define DSIM_FIFOCTRL_REG  0x44/* FIFO status and control register */
-
-/* FIFO memory AC characteristic register */
-#define DSIM_PLLCTRL_REG   0x4c/* PLL control register */
-#define DSIM_PHYACCHR_REG  0x54/* D-PHY AC characteristic register */
-#define DSIM_PHYACCHR1_REG 0x58/* D-PHY AC characteristic register1 */
-#define DSIM_PHYCTRL_REG   0x5c
-#define DSIM_PHYTIMING_REG 0x64
-#define DSIM_PHYTIMING1_REG0x68
-#define DSIM_PHYTIMING2_REG0x6c
-
 /* DSIM_STATUS */
 #define DSIM_STOP_STATE_DAT(x) (((x) & 0xf) << 0)
 #define DSIM_STOP_STATE_CLK(1 << 8)
@@ -128,8 +96,8 @@

 /* DSIM_MDRESOL */
 #define DSIM_MAIN_STAND_BY (1 << 31)
-#define DSIM_MAIN_VRESOL(x)(((x) & 0x7ff) << 16)
-#define DSIM_MAIN_HRESOL(x)(((x) & 0X7ff) << 0)
+#define DSIM_MAIN_VRESOL(x, num_bits)  (((x) & ((1 << (num_bits)) - 1)) << 16)
+#define DSIM_MAIN_HRESOL(x, num_bits)  (((x) & ((1 << (num_bits)) - 1)) << 0)

 /* DSIM_MVPORCH */
 #define DSIM_CMD_ALLOW(x)  ((x) << 28)
@@ -234,6 +202,12 @@
 #define DSI_XFER_TIMEOUT_MS100
 #define DSI_RX_FIFO_EMPTY  0x3082

+#define REG(dsi, reg)  ((dsi)->reg_base + dsi->driver_data->regs[(reg)])
+#define DSI_WRITE(dsi, reg, val)   writel((val), REG((dsi), (reg)))
+#define DSI_READ(dsi, reg) readl(REG((dsi), (reg)))
+
+static char *clk_names[2] = { "bus_clk", "sclk_mipi" };
+
 enum exynos_dsi_transfer_type {
EXYNOS_DSI_TX,
EXYNOS_DSI_RX,
@@ -261,10 +235,15 @@ struct exynos_dsi_transfer {
 #define DSIM_STATE_CMD_LPM BIT(2)

 struct exynos_dsi_driver_data {
+   unsigned int *regs;
unsigned int plltmr_reg;
-
unsigned int has_freqband:1;
unsigned int has_clklane_stop:1;
+   unsigned int num_clks;
+   unsigned int max_freq;
+   unsigned int wait_for_reset;
+   unsigned int num_bits_resol;
+   unsigned int *values;
 };

 struct exynos_dsi {
@@ -277,8 +256,7 @@ struct exynos_dsi {

void __iomem *reg_base;
struct phy *phy;
-   struct clk *sclk_clk;
-   struct clk *bus_clk;
+   struct clk **clks;
struct regulator_bulk_data supplies[2];
int irq;
int te_gpio;
@@ -309,25 +287,133 @@ static inline struct exynos_dsi *display_to_dsi(struct 
exynos_drm_display *d)
return container_of(d, struct exynos_dsi, display);
 }

+enum regs {
+   DSIM_STATUS_REG,/* Status register */
+   DSIM_SWRST_REG, /* Software reset register */
+   DSIM_CLKCTRL_REG,   /* Clock control register */
+   DSIM_TIMEOUT_REG,   /* Time out register */
+   DSIM_CONFIG_REG,/* Configuration register */
+   DSIM_ESCMODE_REG,   /* Escape mode register */
+   DSIM_MDRESOL_REG,
+   DSI

[PATCH v3 6/8] drm/exynos: dsi: add support for Exynos5433

2015-03-26 Thread Hyungwon Hwang
This patch adds support for Exynos5433 mipi dsi.

Signed-off-by: Hyungwon Hwang 
---
Changes for v2:
 - change the author of "drm/exynos: dsi: add support for Exynos5433 SoC" to
 Hyungwon Hwang by the previous author's will
Changes for v3:
 - Separated from the patch "drm/exynos: dsi: add support for Exynos5433 SoC"
 in version 2.
 - use defines for more readable code
 - fix typos
 .../devicetree/bindings/video/exynos_dsim.txt  |  1 +
 drivers/gpu/drm/exynos/Kconfig |  2 +-
 drivers/gpu/drm/exynos/exynos_drm_dsi.c| 69 +-
 3 files changed, 68 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/video/exynos_dsim.txt 
b/Documentation/devicetree/bindings/video/exynos_dsim.txt
index 39940ca..8b12bfe 100644
--- a/Documentation/devicetree/bindings/video/exynos_dsim.txt
+++ b/Documentation/devicetree/bindings/video/exynos_dsim.txt
@@ -6,6 +6,7 @@ Required properties:
"samsung,exynos4210-mipi-dsi" /* for Exynos4 SoCs */
"samsung,exynos4415-mipi-dsi" /* for Exynos4415 SoC */
"samsung,exynos5410-mipi-dsi" /* for Exynos5410/5420/5440 SoCs 
*/
+   "samsung,exynos5433-mipi-dsi" /* for Exynos5433 SoCs */
   - reg: physical base address and length of the registers set for the device
   - interrupts: should contain DSI interrupt
   - clocks: list of clock specifiers, must contain an entry for each required
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index f78f3ef..e873502 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -47,7 +47,7 @@ config DRM_EXYNOS_DPI

 config DRM_EXYNOS_DSI
bool "EXYNOS DRM MIPI-DSI driver support"
-   depends on (DRM_EXYNOS_FIMD || DRM_EXYNOS7_DECON)
+   depends on (DRM_EXYNOS_FIMD || DRM_EXYNOS5433_DECON || 
DRM_EXYNOS7_DECON)
select DRM_MIPI_DSI
select DRM_PANEL
default n
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c 
b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 2d9a249..d1ecd0f 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -131,6 +131,7 @@
 #define DSIM_INT_PLL_STABLE(1 << 31)
 #define DSIM_INT_SW_RST_RELEASE(1 << 30)
 #define DSIM_INT_SFR_FIFO_EMPTY(1 << 29)
+#define DSIM_INT_SFR_HDR_FIFO_EMPTY(1 << 28)
 #define DSIM_INT_BTA   (1 << 25)
 #define DSIM_INT_FRAME_DONE(1 << 24)
 #define DSIM_INT_RX_TIMEOUT(1 << 21)
@@ -179,6 +180,8 @@

 /* DSIM_PHYCTRL */
 #define DSIM_PHYCTRL_ULPS_EXIT(x)  (((x) & 0x1ff) << 0)
+#define DSIM_PHYCTRL_B_DPHYCTL_VREG_LP (1 << 30)
+#define DSIM_PHYCTRL_B_DPHYCTL_SLEW_UP (1 << 14)

 /* DSIM_PHYTIMING */
 #define DSIM_PHYTIMING_LPX(x)  ((x) << 8)
@@ -206,7 +209,9 @@
 #define DSI_WRITE(dsi, reg, val)   writel((val), REG((dsi), (reg)))
 #define DSI_READ(dsi, reg) readl(REG((dsi), (reg)))

-static char *clk_names[2] = { "bus_clk", "sclk_mipi" };
+static char *clk_names[5] = { "bus_clk", "sclk_mipi",
+   "phyclk_mipidphy0_bitclkdiv8", "phyclk_mipidphy0_rxclkesc0",
+   "sclk_rgb_vclk_to_dsim0" };

 enum exynos_dsi_transfer_type {
EXYNOS_DSI_TX,
@@ -335,6 +340,30 @@ static unsigned int regs[] = {
[DSIM_PHYTIMING2_REG] =  0x6c,
 };

+static unsigned int exynos5433_regs[] = {
+   [DSIM_STATUS_REG] = 0x04,
+   [DSIM_SWRST_REG] = 0x0C,
+   [DSIM_CLKCTRL_REG] = 0x10,
+   [DSIM_TIMEOUT_REG] = 0x14,
+   [DSIM_CONFIG_REG] = 0x18,
+   [DSIM_ESCMODE_REG] = 0x1C,
+   [DSIM_MDRESOL_REG] = 0x20,
+   [DSIM_MVPORCH_REG] = 0x24,
+   [DSIM_MHPORCH_REG] = 0x28,
+   [DSIM_MSYNC_REG] = 0x2C,
+   [DSIM_INTSRC_REG] = 0x34,
+   [DSIM_INTMSK_REG] = 0x38,
+   [DSIM_PKTHDR_REG] = 0x3C,
+   [DSIM_PAYLOAD_REG] = 0x40,
+   [DSIM_RXFIFO_REG] = 0x44,
+   [DSIM_FIFOCTRL_REG] = 0x4C,
+   [DSIM_PLLCTRL_REG] = 0x94,
+   [DSIM_PHYCTRL_REG] = 0xA4,
+   [DSIM_PHYTIMING_REG] = 0xB4,
+   [DSIM_PHYTIMING1_REG] = 0xB8,
+   [DSIM_PHYTIMING2_REG] = 0xBC,
+};
+
 enum values {
RESET_TYPE,
PLL_TIMER,
@@ -371,6 +400,24 @@ static unsigned int values[] = {
[PHYTIMING_HS_TRAIL] = DSIM_PHYTIMING2_HS_TRAIL(0x0b),
 };

+static unsigned int exynos5433_values[] = {
+   [RESET_TYPE] = DSIM_FUNCRST,
+   [PLL_TIMER] = 22200,
+   [STOP_STATE_CNT] = 0xa,
+   [PHYCTRL_ULPS_EXIT] = DSIM_PHYCTRL_ULPS_EXIT(0x190),
+   [PHYCTRL_VREG_LP] = DSIM_PHYCTRL_B_DPHYCTL_VREG_LP,
+   [PHYCTRL_SLEW_UP] = DSIM_PHYCTRL_B_DPHYCTL_SLEW_UP,
+   [PHYTIMING_LPX] = DSIM_PHYTIMING_LPX(0x07),
+   [PHYTIMING_HS_EXIT] = DSIM_PHYTIMING_HS_EXIT(0x0c),
+   

[PATCH v3 7/8] drm/exynos: dsi: add support for MIC driver as a bridge

2015-03-26 Thread Hyungwon Hwang
MIC must be initilized by MIPI DSI when it is being bound.

Signed-off-by: Hyungwon Hwang 
---
Changes for v2:
 - None

Changes for v3:
 - None

 .../devicetree/bindings/video/exynos_dsim.txt  | 23 ++---
 drivers/gpu/drm/exynos/exynos_drm_dsi.c| 24 ++
 2 files changed, 44 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/video/exynos_dsim.txt 
b/Documentation/devicetree/bindings/video/exynos_dsim.txt
index 8b12bfe..9112b10 100644
--- a/Documentation/devicetree/bindings/video/exynos_dsim.txt
+++ b/Documentation/devicetree/bindings/video/exynos_dsim.txt
@@ -31,10 +31,19 @@ Video interfaces:
   Device node can contain video interface port nodes according to [2].
   The following are properties specific to those nodes:

-  port node:
-- reg: (required) can be 0 for input RGB/I80 port or 1 for DSI port;
+  port node inbound:
+- reg: (required) must be 0.
+  port node outbound:
+- reg: (required) must be 1.

-  endpoint node of DSI port (reg = 1):
+  endpoint node connected from mic node (reg = 0):
+- remote-endpoint: specifies the endpoint in mic node. This node is 
required
+  for Exynos5433 mipi dsi. So mic can access to panel node
+  thoughout this dsi node.
+  endpoint node connected to panel node (reg = 1):
+- remote-endpoint: specifies the endpoint in panel node. This node is
+  required in all kinds of exynos mipi dsi to represent
+  the connection between mipi dsi and panel.
 - samsung,burst-clock-frequency: specifies DSI frequency in high-speed 
burst
   mode
 - samsung,esc-clock-frequency: specifies DSI frequency in escape mode
@@ -73,7 +82,15 @@ Example:
#address-cells = <1>;
#size-cells = <0>;

+   port at 0 {
+   reg = <0>;
+   decon_to_mic: endpoint {
+   remote-endpoint = <&mic_to_decon>;
+   };
+   };
+
port at 1 {
+   reg = <1>;
dsi_ep: endpoint {
reg = <0>;
samsung,burst-clock-frequency = 
<5>;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c 
b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index d1ecd0f..d382511 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -282,6 +283,7 @@ struct exynos_dsi {
struct list_head transfer_list;

struct exynos_dsi_driver_data *driver_data;
+   struct device_node *bridge_node;
 };

 #define host_to_dsi(host) container_of(host, struct exynos_dsi, dsi_host)
@@ -1778,7 +1780,22 @@ static int exynos_dsi_parse_dt(struct exynos_dsi *dsi)

ret = exynos_dsi_of_read_u32(ep, "samsung,esc-clock-frequency",
 &dsi->esc_clk_rate);
+   if (ret < 0)
+   goto end;
+
+   of_node_put(ep);
+
+   ep = of_graph_get_next_endpoint(node, NULL);
+   if (!ep) {
+   ret = -ENXIO;
+   goto end;
+   }

+   dsi->bridge_node = of_graph_get_remote_port_parent(ep);
+   if (!dsi->bridge_node) {
+   ret = -ENXIO;
+   goto end;
+   }
 end:
of_node_put(ep);

@@ -1791,6 +1808,7 @@ static int exynos_dsi_bind(struct device *dev, struct 
device *master,
struct exynos_drm_display *display = dev_get_drvdata(dev);
struct exynos_dsi *dsi = display_to_dsi(display);
struct drm_device *drm_dev = data;
+   struct drm_bridge *bridge;
int ret;

ret = exynos_drm_create_enc_conn(drm_dev, display);
@@ -1800,6 +1818,12 @@ static int exynos_dsi_bind(struct device *dev, struct 
device *master,
return ret;
}

+   bridge = of_drm_find_bridge(dsi->bridge_node);
+   if (bridge) {
+   display->encoder->bridge = bridge;
+   drm_bridge_attach(drm_dev, bridge);
+   }
+
return mipi_dsi_host_register(&dsi->dsi_host);
 }

-- 
1.9.1



[PATCH v3 3/8] drm/exynos: mic: add MIC driver

2015-03-26 Thread Hyungwon Hwang
MIC(Mobile image compressor) is newly added IP in Exynos5433. MIC
resides between decon and mipi dsim, and compresses frame data by 50%.
With dsi, not display port, to send frame data to the panel, the
bandwidth is not enough. That is why this compressor is introduced.

Signed-off-by: Hyungwon Hwang 
---
Changes for v2:
 - make mic driver to be registered by exynos drm driver instead as a module
 driver
 - change the description of mic driver in documentation
 - add module author at the top of the source file removing MODULE_OWNER,
 MODULE_DESCRIPTION, MODULE_LICENSE

Changes for v3:
 - move if statement out of function, so that the function is not called
 unnecessarily
 - Make it use syscon framework for controlling system register

 .../devicetree/bindings/video/exynos-mic.txt   |  51 +++
 drivers/gpu/drm/exynos/Kconfig |   6 +
 drivers/gpu/drm/exynos/Makefile|   1 +
 drivers/gpu/drm/exynos/exynos_drm_drv.c|   3 +
 drivers/gpu/drm/exynos/exynos_drm_drv.h|   1 +
 drivers/gpu/drm/exynos/exynos_drm_mic.c| 490 +
 6 files changed, 552 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/video/exynos-mic.txt
 create mode 100644 drivers/gpu/drm/exynos/exynos_drm_mic.c

diff --git a/Documentation/devicetree/bindings/video/exynos-mic.txt 
b/Documentation/devicetree/bindings/video/exynos-mic.txt
new file mode 100644
index 000..0fba2ee
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/exynos-mic.txt
@@ -0,0 +1,51 @@
+Device-Tree bindings for Samsung Exynos SoC mobile image compressor (MIC)
+
+MIC (mobile image compressor) resides between decon and mipi dsi. Mipi dsi is
+not capable to transfer high resoltuion frame data as decon can send. MIC
+solves this problem by compressing the frame data by 1/2 before it is
+transferred through mipi dsi. The compressed frame data must be uncompressed in
+the panel PCB.
+
+Required properties:
+- compatible: value should be "samsung,exynos5433-mic".
+- reg: physical base address and length of the MIC registers set and system
+   register of mic.
+- clocks: must include clock specifiers corresponding to entries in the
+ clock-names property.
+- clock-names: list of clock names sorted in the same order as the clocks
+  property. Must contain "pclk_mic0", "sclk_rgb_vclk_to_mic0".
+- samsung,disp-syscon: the reference node for syscon for DISP block.
+- ports: contains a port which is connected to decon node and dsi node.
+address-cells and size-cells must 1 and 0, respectively.
+- port: contains an endpoint node which is connected to the endpoint in the
+   decon node or dsi node. The reg value must be 0 and 1 respectively.
+
+Example:
+SoC specific DT entry:
+mic: mic at 1393 {
+   compatible = "samsung,exynos5433-mic";
+   reg = <0x1393 0x48>;
+   clocks = <&cmu_disp CLK_PCLK_MIC0>,
+  <&cmu_disp CLK_SCLK_RGB_VCLK_TO_MIC0>;
+   clock-names = "pclk_mic0", "sclk_rgb_vclk_to_mic0";
+   samsung,disp-syscon = <&syscon_disp>;
+
+   ports {
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   port at 0 {
+   reg = <0>;
+   mic_to_decon: endpoint {
+   remote-endpoint = <&decon_to_mic>;
+   };
+   };
+
+   port at 1 {
+   reg = <1>;
+   mic_to_dsi: endpoint {
+   remote-endpoint = <&dsi_to_mic>;
+   };
+   };
+   };
+};
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index d9dc408..f78f3ef 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -103,3 +103,9 @@ config DRM_EXYNOS_GSC
depends on DRM_EXYNOS_IPP && ARCH_EXYNOS5 && !ARCH_MULTIPLATFORM
help
  Choose this option if you want to use Exynos GSC for DRM.
+
+config DRM_EXYNOS_MIC
+   bool "Exynos DRM MIC"
+   depends on (DRM_EXYNOS && DRM_EXYNOS5433_DECON)
+   help
+ Choose this option if you want to use Exynos MIC for DRM.
diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile
index fbd084d..7de0b10 100644
--- a/drivers/gpu/drm/exynos/Makefile
+++ b/drivers/gpu/drm/exynos/Makefile
@@ -22,5 +22,6 @@ exynosdrm-$(CONFIG_DRM_EXYNOS_IPP)+= exynos_drm_ipp.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_FIMC)+= exynos_drm_fimc.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_ROTATOR) += exynos_drm_rotator.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_GSC) += exynos_drm_gsc.o
+exynosdrm-$(CONFIG_DRM_EXYNOS_MIC) += exynos_drm_mic.o

 obj-$(CONFIG_DRM_EXYNOS)   += exynosdrm.o
diff --git a/drivers/gpu/d

[PATCH 2/2] drm/exynos: fix the initialization order in FIMD

2015-04-01 Thread Hyungwon Hwang
Dear Joonyoung Shim,

On Tue, 31 Mar 2015 17:05:47 +0900
Joonyoung Shim  wrote:

> Hi,
> 
> Sorry for late comments.
> 
> On 03/13/2015 07:32 PM, Inki Dae wrote:
> > On 2015년 03월 12일 13:36, Hyungwon Hwang wrote:
> >> Since commit 0f04cf8df0b20a97369cb634663fef0578cbf273 ("drm/exynos:
> >> fix wrong pipe calculation for crtc"), fimd_clear_channel() can be
> >> called when is_drm_iommu_supported() returns true. In this case,
> >> the kernel is going to be panicked because crtc is not set yet.
> > 
> > Nice catch!!!
> > 
> >>
> >> [1.211156] [drm] Initialized drm 1.1.0 20060810
> >> [1.216785] Unable to handle kernel NULL pointer dereference at
> >> virtual address 0350 [1.223415] pgd = c0004000
> >> [1.226086] [0350] *pgd=
> >> [1.229649] Internal error: Oops: 5 [#1] PREEMPT SMP ARM
> >> [1.234940] Modules linked in:
> >> [1.237982] CPU: 2 PID: 1 Comm: swapper/0 Not tainted
> >> 4.0.0-rc1-00062-g7a7cc79-dirty #123 [1.246136] Hardware name:
> >> SAMSUNG EXYNOS (Flattened Device Tree) [1.252214] task:
> >> ee8c8000 ti: ee8d task.ti: ee8d [1.257606] PC is at
> >> fimd_wait_for_vblank+0x8/0xc8 [1.262370] LR is at
> >> fimd_bind+0x138/0x1a8 [1.266450] pc : []lr :
> >> []psr: 2113 [1.266450] sp : ee8d1d28  ip :
> >>   fp :  [1.277906] r10: 0001  r9 :
> >> c09d693c  r8 : c0a2d6a8 [1.283114] r7 : 0034  r6 :
> >> 0001  r5 : ee0bb400  r4 : ee244c10 [1.289624] r3 :
> >>   r2 :   r1 : 0001  r0 : 
> >> [1.296135] Flags: nzCv  IRQs on  FIQs on  Mode SVC_32  ISA
> >> ARM  Segment kernel [1.303426] Control: 10c5387d  Table:
> >> 4000404a  DAC: 0015 [1.309154] Process swapper/0 (pid: 1,
> >> stack limit = 0xee8d0210) [1.315143] Stack: (0xee8d1d28 to
> >> 0xee8d2000) [1.319486] 1d20:   
> >> c0113d18 ee0bb400 ee0bb400 ee245c30 eebbe210 [1.327645] 1d40:
> >> ee008a40 ee244c10 ee0bb400 0001 0034 c02fb834 
> >> c030a858 [1.335804] 1d60: ee244a10 eeb60780 ee008a40 eeb60740
> >> ee0bb400 c03030d0   [1.343963] 1d80: ee244a10
> >> ee0bb400  eeb60740 eeb60810   c02f6ba4
> >> [1.352123] 1da0: ee0bb400   c02e0500 ee244a00
> >> c0a04a14 ee0bb400 c02e1de4 [1.360282] 1dc0:  c030a858
> >> 0002 eeb60820 eeb60820 0002 eeb60780 c03033d4
> >> [1.368441] 1de0: c06e9cec  ee244a10 eeb60780 c0a056f8
> >> c03035fc c0a04b24 c0a04b24 [1.376600] 1e00: ee244a10 0001
> >> c0a049d0 c02f6d34 c0ad462c eeba0790  ee244a10
> >> [1.384759] 1e20: ffed c0a049d0  c03090b0 ee244a10
> >> c0ad462c c0a2d840 c03077a0 [1.392919] 1e40: eeb5e880 c024b738
> >> 08db ee244a10 c0a049d0 ee244a44  c09e71d8
> >> [1.401078] 1e60: 00c6 c0307a6c c0a049d0  c03079e0
> >> c0305ea8 ee826e5c ee1dc7b4 [1.409237] 1e80: c0a049d0 eeb5e880
> >> c0a058a8 c0306e2c c0896204 c0a049d0 c06e9d10 c0a049d0
> >> [1.417396] 1ea0: c06e9d10 c0ad4600  c0308360 
> >> 0003 c06e9d10 c02f6e14 [1.42] 1ec0:  c0896204
> >>      
> >> [1.433714] 1ee0:   c02f6d5c c02f6d5c 
> >> eeb5d740 c09e71d8 c0008a30 [1.441874] 1f00: ef7fca5e 
> >>  0066  ee8d1f28 c003ff1c c02514e8
> >> [1.450033] 1f20: 6113  c093906c ef7fca5e 00c6
> >> c004018c  c093906c [1.458192] 1f40: c08a9690 c093840c
> >> 0006 0006 c09eb2ac c09c0d74 0006 c09c0d54
> >> [1.466351] 1f60: c0a3d680 c09745a0 c09d693c 00c6 
> >> c0974db4 0006 0006 [1.474510] 1f80: c09745a0 
> >>  c0692e00    
> >> [1.482669] 1fa0:  c0692e08  c000f040 
> >>    [1.490828] 1fc0:  
> >>      
> >> [1.498988] 1fe0:     0013
> >>    [1.507159] []
> >> (fimd_wait_for_vblank) from [] (fimd_bind+0x138/0x1a8)
> >> [1.515313] [] (fimd_bind) from []
> >> (component_bind_all+0xc4/0x20c) [1.523209] []
> >> (compo

[PATCH] drm/exynos: fimd: check whether exynos_drm_crtc_create succeed or not

2015-04-01 Thread Hyungwon Hwang
>From the commit "drm/exynos: fix the execution order in FIMD
initialization" (598285bfdce46d7c47632a2ba4b980f60be4a677), the error
checking code is removed improperly. This patch fix the regression.

Signed-off-by: Hyungwon Hwang 
---
 drivers/gpu/drm/exynos/exynos_drm_fimd.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c 
b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 31dfa80..15cee94 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -1060,6 +1060,8 @@ static int fimd_bind(struct device *dev, struct device 
*master, void *data)
ctx->crtc = exynos_drm_crtc_create(drm_dev, ctx->pipe,
   EXYNOS_DISPLAY_TYPE_LCD,
   &fimd_crtc_ops, ctx);
+   if (IS_ERR(ctx->crtc))
+   return PTR_ERR(ctx->crtc);

if (ctx->display)
exynos_drm_create_enc_conn(drm_dev, ctx->display);
-- 
1.9.1



[PATCH v2 00/13] drm/exynos: async G2D and g2d_move()

2015-11-23 Thread Hyungwon Hwang
Hello Tobias,

I reviewed this whole patchset, and it looks good to me. Also I tested
it on my odroid u3, and all works fine. Thanks you for your effort.

Tested-by: Hyungwon Hwang 
Reviewed-by: Hyungwon Hwang 

BRs,
Hyungwon Hwang

On Sun, 22 Nov 2015 19:48:30 +0100
Tobias Jakobi  wrote:

> Hello,
> 
> this series mostly touches G2D code. It introduces the following:
> 
> (1) drmHandleEvent2() is added to enable processing of vendor-specific
> events. This will be used to expose asynchronous operation of the
> G2D. The necessary kernel infrastructure is already there since
> a lot of kernel versions. [This touches libdrm core code!]
> 
> (2) The necessary infrastructure to handle G2D events. This includes
> adding g2d_config_event() and g2d_exec2() to the public API.
> A test application is provided to ensure that everything works
> as expected.
> 
> (3) A small performance test application which can be used to measure
> the speed of solid color clear operations. Interesting for
> benchmarking and plotting colorful graphs (e.g. through
> Mathematica).
> 
> (4) g2d_move() which works similar to g2d_copy() but like the C
> memmove() properly handles overlapping buffer copies.
> Again a test application is present to check that this
> indeed does what it should.
> 
> (5) Various small changes. A framebuffer colorformat fix for the
> general G2D test application. Moving the currently unused
> g2d_reset() to the public API. Adding a counterpart to
> exynos_bo_map() to unmap buffers again.
> 
> (6) Last but not least a small bump of the Exynos version number.
> 
> Please review and let me know what I should change/improve.
> 
> 
> With best wishes,
> Tobias
> 
> P.S.: Most patches were submitted already some time ago but never
> made it upstream. So if something looks familiar, don't worry! ;)
> 
> Changes since v1:
> - Added wording changes suggested by Hyungwon Hwang.
> - Added binaries for new test applications to .gitignore.
> - Collected r-b and t-b tags.
> 
> Tobias Jakobi (13):
>   drm: Implement drmHandleEvent2()
>   exynos: Introduce exynos_handle_event()
>   tests/exynos: add fimg2d performance analysis
>   exynos/fimg2d: add g2d_config_event
>   exynos: fimg2d: add g2d_exec2
>   tests/exynos: add fimg2d event test
>   tests/exynos: use XRGB for framebuffer
>   exynos: fimg2d: add g2d_set_direction
>   exynos/fimg2d: add g2d_move
>   tests/exynos: add test for g2d_move
>   exynos/fimg2d: add exynos_bo_unmap()
>   exynos/fimg2d: add g2d_reset() to public API
>   exynos: bump version number
> 
>  .gitignore |   2 +
>  exynos/exynos-symbol-check |   5 +
>  exynos/exynos_drm.c|  48 ++
>  exynos/exynos_drm.h|  12 ++
>  exynos/exynos_drmif.h  |  27 +++
>  exynos/exynos_fimg2d.c | 165 +--
>  exynos/exynos_fimg2d.h |  49 ++
>  exynos/libdrm_exynos.pc.in |   2 +-
>  tests/exynos/Makefile.am   |  26 ++-
>  tests/exynos/exynos_fimg2d_event.c | 326
> 
> tests/exynos/exynos_fimg2d_perf.c  | 327
> +
> tests/exynos/exynos_fimg2d_test.c  | 134 ++-
> xf86drm.h  |  21 +++
> xf86drmMode.c  |  10 +- 14 files changed, 1138
> insertions(+), 16 deletions(-) create mode 100644
> tests/exynos/exynos_fimg2d_event.c create mode 100644
> tests/exynos/exynos_fimg2d_perf.c
> 



[PATCH v2 08/13] exynos: fimg2d: add g2d_set_direction

2015-11-27 Thread Hyungwon Hwang
Dear all,

Yes. I can pick it on behalf of Tobias, if there is no one who can do
that.

BRs,
Hyungwon Hwang

On Thu, 26 Nov 2015 16:48:10 +
Emil Velikov  wrote:

> On 26 November 2015 at 16:41, Tobias Jakobi 
> wrote:
> > Hello Emil,
> >
> > my main system which I also used for development was stolen on
> > Tuesday, so I won't be working on this series anytime soon. If
> > anyone wants to pick it up, please go ahead.
> >
> Sad to hear that x2. You've been doing some good work, despite that we
> weren't always quick to review/pick it. Hope you had some insurance
> and you manage to sort things out, relatively stress free.
> 
> Inki, Hyungwon, other Exynos devs,
> 
> Will you guys be able to pick any of this work ? Most of it can go in
> with the small suggestion in this patch addressed.
> 
> Thanks
> Emil
> 



[PATCH v2 00/13] drm/exynos: async G2D and g2d_move()

2015-11-27 Thread Hyungwon Hwang
Dear All,

On Thu, 26 Nov 2015 16:35:29 +
Emil Velikov  wrote:

> Hi Tobias,
> 
> On 22 November 2015 at 18:48, Tobias Jakobi
>  wrote:
> > Hello,
> >
> > this series mostly touches G2D code. It introduces the following:
> >
> > (1) drmHandleEvent2() is added to enable processing of
> > vendor-specific events. This will be used to expose asynchronous
> > operation of the G2D. The necessary kernel infrastructure is
> > already there since a lot of kernel versions. [This touches libdrm
> > core code!]
> >
> Considering the shortage of input on this can you please respin the
> series without it (and related work mentioned below). This way we can
> pick merge the remaining work now and discuss (ping) about the rest.

I am confused a little here. Did you mean that adding drmHandleEvent2()
is not necessary, and the related code which uses drmHandleEvent2() must
be re-implemented?

> 
> > (2) The necessary infrastructure to handle G2D events. This includes
> > adding g2d_config_event() and g2d_exec2() to the public API.
> > A test application is provided to ensure that everything works
> > as expected.
> >
> With above in mind the g2d event will need to be split out, although
> g2d_exec2() should be ok (although of limited use), imho.
> 
> > (3) A small performance test application which can be used to
> > measure the speed of solid color clear operations. Interesting for
> > benchmarking and plotting colorful graphs (e.g. through
> > Mathematica).
> >
> > (4) g2d_move() which works similar to g2d_copy() but like the C
> > memmove() properly handles overlapping buffer copies.
> > Again a test application is present to check that this
> > indeed does what it should.
> >
> > (5) Various small changes. A framebuffer colorformat fix for the
> > general G2D test application. Moving the currently unused
> > g2d_reset() to the public API.
> I am more of a "add API when it's needed" kind of person, although I
> cannot see anything serious misuse that can arise from g2d_reset().
> 
> > Adding a counterpart to
> > exynos_bo_map() to unmap buffers again.
> >
> The exynos bo map compatibility was broken a few times already so I'm
> wondering if we really want this one. I guess that with the lack of
> any (outside of tizen) user space things cannot go that wrong :-P
> 

Yes. I agree that adding them at this time is not needed and it would
be OK to add them, when the userspace using them comes.

BRs,
Hyungwon Hwang

> Thanks
> Emil
> 



[PATCH v3 1/3] modetest: introduce get_prop_info() for getting property id and type

2015-11-27 Thread Hyungwon Hwang
Hello all,

+To Thierry Reding

On Thu, 26 Nov 2015 16:42:01 +
Emil Velikov  wrote:

> Hi Hyungwon
> 
> I completely missed out that you've sent an updated version of the
> series. I will take a look at them later on tonight. Meanwhile have
> you looked at the atomic tests/helpers work from Thierry [1] ? It
> creates nice simple helpers (as opposed to a single massive C file
> like modetest) and I'm leaning that there is quite a lot of code that
> can be reused from there.
> 
> Speaking of which Thierry,
> What is happening with these patches ? Last time you've respun them
> I've pinged you to send them over for inclusion. There was a trivial
> fix needed here or there but they were in pretty good shape.

Yes. I checked it now. It would be more clear concise, if they comes.
Would it be better to wait Thierry for sending them again? Can you
afford to do that, Thierry?

BRs,
Hyungwon Hwang


> 
> Thanks
> Emil
> 
> [1] http://cgit.freedesktop.org/~tagr/drm/
> 



[PATCH v3 3/9] exynos/fimg2d: add g2d_config_event

2015-11-30 Thread Hyungwon Hwang
From: Tobias Jakobi 

This enables us to pass command buffers to the kernel which
trigger an event on the DRM fd upon completion.
The final goal is to enable asynchronous operation of the
G2D engine, similar to async page flips.

Passing the event userdata pointer through the G2D context
was chosen to not change the current API (e.g. by adding
a userdata argument to each public functions).

Signed-off-by: Tobias Jakobi 
---
Changes for
v2: Add g2d_config_event() to Exynos symbol test.

 exynos/exynos-symbol-check |  1 +
 exynos/exynos_fimg2d.c | 28 ++--
 exynos/exynos_fimg2d.h |  1 +
 3 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/exynos/exynos-symbol-check b/exynos/exynos-symbol-check
index c3ddbe4..bb12315 100755
--- a/exynos/exynos-symbol-check
+++ b/exynos/exynos-symbol-check
@@ -27,6 +27,7 @@ g2d_blend
 g2d_copy
 g2d_copy_with_scale
 g2d_exec
+g2d_config_event
 g2d_fini
 g2d_init
 g2d_scale_and_blend
diff --git a/exynos/exynos_fimg2d.c b/exynos/exynos_fimg2d.c
index e734144..b10620b 100644
--- a/exynos/exynos_fimg2d.c
+++ b/exynos/exynos_fimg2d.c
@@ -57,6 +57,7 @@ struct g2d_context {
unsigned intcmd_nr;
unsigned intcmd_buf_nr;
unsigned intcmdlist_nr;
+   void*event_userdata;
 };

 enum g2d_base_addr_reg {
@@ -280,8 +281,15 @@ static int g2d_flush(struct g2d_context *ctx)
cmdlist.cmd_buf = (uint64_t)(uintptr_t)&ctx->cmd_buf[0];
cmdlist.cmd_nr = ctx->cmd_nr;
cmdlist.cmd_buf_nr = ctx->cmd_buf_nr;
-   cmdlist.event_type = G2D_EVENT_NOT;
-   cmdlist.user_data = 0;
+
+   if (ctx->event_userdata) {
+   cmdlist.event_type = G2D_EVENT_NONSTOP;
+   cmdlist.user_data = (uint64_t)(uintptr_t)(ctx->event_userdata);
+   ctx->event_userdata = NULL;
+   } else {
+   cmdlist.event_type = G2D_EVENT_NOT;
+   cmdlist.user_data = 0;
+   }

ctx->cmd_nr = 0;
ctx->cmd_buf_nr = 0;
@@ -336,6 +344,22 @@ void g2d_fini(struct g2d_context *ctx)
 }

 /**
+ * g2d_config_event - setup userdata configuration for a g2d event.
+ * The next invocation of a g2d call (e.g. g2d_solid_fill) is
+ * then going to flag the command buffer as 'nonstop'.
+ * Completion of the command buffer execution can then be
+ * determined by using drmHandleEvent on the DRM fd.
+ * The userdata is 'consumed' in the process.
+ *
+ * @ctx: a pointer to g2d_context structure.
+ * @userdata: a pointer to the user data
+ */
+void g2d_config_event(struct g2d_context *ctx, void *userdata)
+{
+   ctx->event_userdata = userdata;
+}
+
+/**
  * g2d_exec - start the dma to process all commands summited by g2d_flush().
  *
  * @ctx: a pointer to g2d_context structure.
diff --git a/exynos/exynos_fimg2d.h b/exynos/exynos_fimg2d.h
index 4aa1568..a2c22da 100644
--- a/exynos/exynos_fimg2d.h
+++ b/exynos/exynos_fimg2d.h
@@ -290,6 +290,7 @@ struct g2d_context;

 struct g2d_context *g2d_init(int fd);
 void g2d_fini(struct g2d_context *ctx);
+void g2d_config_event(struct g2d_context *ctx, void *userdata);
 int g2d_exec(struct g2d_context *ctx);
 int g2d_solid_fill(struct g2d_context *ctx, struct g2d_image *img,
unsigned int x, unsigned int y, unsigned int w,
--
1.9.1



[PATCH v3 1/9] exynos: Introduce exynos_handle_event()

2015-11-30 Thread Hyungwon Hwang
From: Tobias Jakobi 

Used to handle kernel events specific to the Exynos platform.
Currently only G2D events are handled.

Signed-off-by: Tobias Jakobi 
Signed-off-by: Hyungwon Hwang 
---
Changes for
v2: Adapt to container approach.
v3: Add exynos_handle_event() to Exynos symbol test.
v4: exynos_handle_event() became not to use drmHandleEvent() for 
Exynos-dependent callback

 exynos/exynos-symbol-check |  1 +
 exynos/exynos_drm.c| 76 ++
 exynos/exynos_drm.h| 12 
 exynos/exynos_drmif.h  | 26 
 4 files changed, 115 insertions(+)

diff --git a/exynos/exynos-symbol-check b/exynos/exynos-symbol-check
index 1a1be89..c3ddbe4 100755
--- a/exynos/exynos-symbol-check
+++ b/exynos/exynos-symbol-check
@@ -22,6 +22,7 @@ exynos_device_destroy
 exynos_prime_fd_to_handle
 exynos_prime_handle_to_fd
 exynos_vidi_connection
+exynos_handle_event
 g2d_blend
 g2d_copy
 g2d_copy_with_scale
diff --git a/exynos/exynos_drm.c b/exynos/exynos_drm.c
index df9b8ed..e689781 100644
--- a/exynos/exynos_drm.c
+++ b/exynos/exynos_drm.c
@@ -32,6 +32,7 @@
 #include 
 #include 
 #include 
+#include 

 #include 
 #include 
@@ -42,6 +43,8 @@
 #include "exynos_drm.h"
 #include "exynos_drmif.h"

+#define U642VOID(x) ((void *)(unsigned long)(x))
+
 /*
  * Create exynos drm device object.
  *
@@ -374,3 +377,76 @@ exynos_vidi_connection(struct exynos_device *dev, uint32_t 
connect,

return 0;
 }
+
+static void
+exynos_handle_vendor(int fd, struct drm_event *e, void *ctx)
+{
+   struct drm_exynos_g2d_event *g2d;
+   struct exynos_event_context *ectx = ctx;
+
+   switch (e->type) {
+   case DRM_EXYNOS_G2D_EVENT:
+   if (ectx->version < 1 || ectx->g2d_event_handler == 
NULL)
+   break;
+   g2d = (struct drm_exynos_g2d_event *)e;
+   ectx->g2d_event_handler(fd, g2d->cmdlist_no, 
g2d->tv_sec,
+   g2d->tv_usec, 
U642VOID(g2d->user_data));
+   break;
+
+   default:
+   break;
+   }
+}
+
+int
+exynos_handle_event(struct exynos_device *dev, struct exynos_event_context 
*ctx)
+{
+   char buffer[1024];
+   int len, i;
+   struct drm_event *e;
+   struct drm_event_vblank *vblank;
+   drmEventContextPtr evctx = &ctx->base;
+
+   /* The DRM read semantics guarantees that we always get only
+* complete events. */
+   len = read(dev->fd, buffer, sizeof buffer);
+   if (len == 0)
+   return 0;
+   if (len < (int)sizeof *e)
+   return -1;
+
+   i = 0;
+   while (i < len) {
+   e = (struct drm_event *) &buffer[i];
+   switch (e->type) {
+   case DRM_EVENT_VBLANK:
+   if (evctx->version < 1 ||
+   evctx->vblank_handler == NULL)
+   break;
+   vblank = (struct drm_event_vblank *) e;
+   evctx->vblank_handler(dev->fd,
+ vblank->sequence,
+ vblank->tv_sec,
+ vblank->tv_usec,
+ U642VOID (vblank->user_data));
+   break;
+   case DRM_EVENT_FLIP_COMPLETE:
+   if (evctx->version < 2 ||
+   evctx->page_flip_handler == NULL)
+   break;
+   vblank = (struct drm_event_vblank *) e;
+   evctx->page_flip_handler(dev->fd,
+vblank->sequence,
+vblank->tv_sec,
+vblank->tv_usec,
+U642VOID (vblank->user_data));
+   break;
+   default:
+   exynos_handle_vendor(dev->fd, e, evctx);
+   break;
+   }
+   i += e->length;
+   }
+
+   return 0;
+}
diff --git a/exynos/exynos_drm.h b/exynos/exynos_drm.h
index 256c02f..c3af0ac 100644
--- a/exynos/exynos_drm.h
+++ b/exynos/exynos_drm.h
@@ -157,4 +157,16 @@ struct drm_exynos_g2d_exec {
 #define DRM_IOCTL_EXYNOS_G2D_EXEC  DRM_IOWR(DRM_COMMAND_BASE + \
DRM_EXYNOS_G2D_EXEC, struct drm_exynos_g2d_exec)

+/* EXYNOS specific events */
+#define DRM_EXYNOS_G2D_EVENT   0x8000
+
+struct drm_exynos_g2d_event {
+   struct drm_eventbase;
+   __u64   user_data;
+   __u32   tv_sec;
+   __u32  

[PATCH v3 4/9] tests/exynos: add fimg2d event test

2015-11-30 Thread Hyungwon Hwang
From: Tobias Jakobi 

This tests async processing of G2D jobs. A separate thread is spawned
to monitor the DRM fd for events and check whether a G2D job was
completed.

Signed-off-by: Tobias Jakobi 
Signed-off-by: Hyungwon Hwang 
---
Changes for
v2: Add GPLv2 header, argument handling and documentation.
Test is only installed when requested.
v3: Allocate G2D jobs with calloc which fixes 'busy' being
potentially uninitialized. Also enable timeout for poll()
in the monitor thread. This fixes pthread_join() not working
because of poll() not returning.
v4: Use explicit/fixed values for the DRM event context versions.
v5: Add binary to .gitignore.
v6: Use g2d_exec() instead of g2d_exec2() until g2d_exec2() being merged

 .gitignore |   1 +
 tests/exynos/Makefile.am   |  11 +-
 tests/exynos/exynos_fimg2d_event.c | 326 +
 3 files changed, 336 insertions(+), 2 deletions(-)
 create mode 100644 tests/exynos/exynos_fimg2d_event.c

diff --git a/.gitignore b/.gitignore
index 204724a..922e339 100644
--- a/.gitignore
+++ b/.gitignore
@@ -94,6 +94,7 @@ tests/proptest/proptest
 tests/kmstest/kmstest
 tests/vbltest/vbltest
 tests/radeon/radeon_ttm
+tests/exynos/exynos_fimg2d_event
 tests/exynos/exynos_fimg2d_perf
 tests/exynos/exynos_fimg2d_test
 man/*.3
diff --git a/tests/exynos/Makefile.am b/tests/exynos/Makefile.am
index e82d199..357d6b8 100644
--- a/tests/exynos/Makefile.am
+++ b/tests/exynos/Makefile.am
@@ -20,16 +20,23 @@ endif

 if HAVE_INSTALL_TESTS
 bin_PROGRAMS += \
-   exynos_fimg2d_perf
+   exynos_fimg2d_perf \
+   exynos_fimg2d_event
 else
 noinst_PROGRAMS += \
-   exynos_fimg2d_perf
+   exynos_fimg2d_perf \
+   exynos_fimg2d_event
 endif

 exynos_fimg2d_perf_LDADD = \
$(top_builddir)/libdrm.la \
$(top_builddir)/exynos/libdrm_exynos.la

+exynos_fimg2d_event_LDADD = \
+   $(top_builddir)/libdrm.la \
+   $(top_builddir)/exynos/libdrm_exynos.la \
+   -lpthread
+
 exynos_fimg2d_test_LDADD = \
$(top_builddir)/libdrm.la \
$(top_builddir)/libkms/libkms.la \
diff --git a/tests/exynos/exynos_fimg2d_event.c 
b/tests/exynos/exynos_fimg2d_event.c
new file mode 100644
index 000..9ed5a30
--- /dev/null
+++ b/tests/exynos/exynos_fimg2d_event.c
@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) 2015 - Tobias Jakobi
+ *
+ * This is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation, either version 2 of the License,
+ * or (at your option) any later version.
+ *
+ * It is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with it. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include 
+
+#include "exynos_drm.h"
+#include "exynos_drmif.h"
+#include "exynos_fimg2d.h"
+
+struct g2d_job {
+   unsigned int id;
+   unsigned int busy;
+};
+
+struct exynos_evhandler {
+   struct pollfd fds;
+   struct exynos_event_context evctx;
+};
+
+struct threaddata {
+   unsigned int stop;
+   struct exynos_device *dev;
+   struct exynos_evhandler evhandler;
+};
+
+static void g2d_event_handler(int fd, unsigned int cmdlist_no, unsigned int 
tv_sec,
+   unsigned int tv_usec, 
void *user_data)
+{
+   struct g2d_job *job = user_data;
+
+   fprintf(stderr, "info: g2d job (id = %u, cmdlist number = %u) 
finished!\n",
+   job->id, cmdlist_no);
+
+   job->busy = 0;
+}
+
+static void setup_g2d_event_handler(struct exynos_evhandler *evhandler, int fd)
+{
+   evhandler->fds.fd = fd;
+   evhandler->fds.events = POLLIN;
+   evhandler->evctx.base.version = 2;
+   evhandler->evctx.version = 1;
+   evhandler->evctx.g2d_event_handler = g2d_event_handler;
+}
+
+static void* threadfunc(void *arg) {
+   const int timeout = 0;
+   struct threaddata *data;
+
+   data = arg;
+
+   while (1) {
+   if (data->stop) break;
+
+   usleep(500);
+
+   data->evhandler.fds.revents = 0;
+
+   if (poll(&data->evhandler.fds, 1, timeout) < 0)
+   continue;
+
+   if (data->evhandler.fds.revents & (POLLHUP | POLLERR))
+   continue;
+
+   if (data->evhandler.fds.revents & POLLIN)
+   exynos_handle_event(data->dev, &data->evhandler.evctx);
+   }
+
+   pthread_exit(0);
+}
+
+/*
+ * We need to wait u

[PATCH v3 7/9] exynos/fimg2d: add g2d_move

2015-11-30 Thread Hyungwon Hwang
From: Tobias Jakobi 

We already have g2d_copy() which implements G2D copy
operations from one buffer to another. However we can't
do a overlapping copy operation in one buffer.

Add g2d_move() which acts like the standard memmove()
and properly handles overlapping copies.

Signed-off-by: Tobias Jakobi 
---
Changes for
v2: Change wording in the description of g2d_move()
as suggested by Hyungwon Hwang.

 exynos/exynos_fimg2d.c | 95 ++
 exynos/exynos_fimg2d.h |  3 ++
 2 files changed, 98 insertions(+)

diff --git a/exynos/exynos_fimg2d.c b/exynos/exynos_fimg2d.c
index 3bef93b..7f1d105 100644
--- a/exynos/exynos_fimg2d.c
+++ b/exynos/exynos_fimg2d.c
@@ -567,6 +567,101 @@ g2d_copy(struct g2d_context *ctx, struct g2d_image *src,
 }

 /**
+ * g2d_move - copy content inside single buffer.
+ * Similar to libc's memmove() this copies a rectangular
+ * region of the provided buffer to another location, while
+ * properly handling the situation where source and
+ * destination rectangle overlap.
+ *
+ * @ctx: a pointer to g2d_context structure.
+ * @img: a pointer to g2d_image structure providing
+ * buffer information.
+ * @src_x: x position of source rectangle.
+ * @src_y: y position of source rectangle.
+ * @dst_x: x position of destination rectangle.
+ * @dst_y: y position of destination rectangle.
+ * @w: width of rectangle to move.
+ * @h: height of rectangle to move.
+ */
+int
+g2d_move(struct g2d_context *ctx, struct g2d_image *img,
+   unsigned int src_x, unsigned int src_y,
+   unsigned int dst_x, unsigned dst_y, unsigned int w,
+   unsigned int h)
+{
+   union g2d_rop4_val rop4;
+   union g2d_point_val pt;
+   union g2d_direction_val dir;
+   unsigned int src_w, src_h, dst_w, dst_h;
+
+   src_w = w;
+   src_h = h;
+   if (src_x + img->width > w)
+   src_w = img->width - src_x;
+   if (src_y + img->height > h)
+   src_h = img->height - src_y;
+
+   dst_w = w;
+   dst_h = w;
+   if (dst_x + img->width > w)
+   dst_w = img->width - dst_x;
+   if (dst_y + img->height > h)
+   dst_h = img->height - dst_y;
+
+   w = MIN(src_w, dst_w);
+   h = MIN(src_h, dst_h);
+
+   if (w == 0 || h == 0) {
+   fprintf(stderr, MSG_PREFIX "invalid width or height.\n");
+   return -EINVAL;
+   }
+
+   if (g2d_check_space(ctx, 13, 2))
+   return -ENOSPC;
+
+   g2d_add_cmd(ctx, DST_SELECT_REG, G2D_SELECT_MODE_BGCOLOR);
+   g2d_add_cmd(ctx, SRC_SELECT_REG, G2D_SELECT_MODE_NORMAL);
+
+   g2d_add_cmd(ctx, DST_COLOR_MODE_REG, img->color_mode);
+   g2d_add_cmd(ctx, SRC_COLOR_MODE_REG, img->color_mode);
+
+   g2d_add_base_addr(ctx, img, g2d_dst);
+   g2d_add_base_addr(ctx, img, g2d_src);
+
+   g2d_add_cmd(ctx, DST_STRIDE_REG, img->stride);
+   g2d_add_cmd(ctx, SRC_STRIDE_REG, img->stride);
+
+   dir.val[0] = dir.val[1] = 0;
+
+   if (dst_x >= src_x)
+   dir.data.src_x_direction = dir.data.dst_x_direction = 1;
+   if (dst_y >= src_y)
+   dir.data.src_y_direction = dir.data.dst_y_direction = 1;
+
+   g2d_set_direction(ctx, &dir);
+
+   pt.data.x = src_x;
+   pt.data.y = src_y;
+   g2d_add_cmd(ctx, SRC_LEFT_TOP_REG, pt.val);
+   pt.data.x = src_x + w;
+   pt.data.y = src_y + h;
+   g2d_add_cmd(ctx, SRC_RIGHT_BOTTOM_REG, pt.val);
+
+   pt.data.x = dst_x;
+   pt.data.y = dst_y;
+   g2d_add_cmd(ctx, DST_LEFT_TOP_REG, pt.val);
+   pt.data.x = dst_x + w;
+   pt.data.y = dst_y + h;
+   g2d_add_cmd(ctx, DST_RIGHT_BOTTOM_REG, pt.val);
+
+   rop4.val = 0;
+   rop4.data.unmasked_rop3 = G2D_ROP3_SRC;
+   g2d_add_cmd(ctx, ROP4_REG, rop4.val);
+
+   return g2d_flush(ctx);
+}
+
+/**
  * g2d_copy_with_scale - copy contents in source buffer to destination buffer
  * scaling up or down properly.
  *
diff --git a/exynos/exynos_fimg2d.h b/exynos/exynos_fimg2d.h
index a2c22da..a825c68 100644
--- a/exynos/exynos_fimg2d.h
+++ b/exynos/exynos_fimg2d.h
@@ -299,6 +299,9 @@ int g2d_copy(struct g2d_context *ctx, struct g2d_image *src,
struct g2d_image *dst, unsigned int src_x,
unsigned int src_y, unsigned int dst_x, unsigned int dst_y,
unsigned int w, unsigned int h);
+int g2d_move(struct g2d_context *ctx, struct g2d_image *img,
+   unsigned int src_x, unsigned int src_y, unsigned int dst_x,
+   unsigned dst_y, unsigned int w, unsigned int h);
 int g2d_copy_with_scale(struct g2d_context *ctx, struct g2d_image *src,
struct g2d_image *dst, unsigned int src_x,
unsigned int src_y, unsigned int src_w,
--
1.9.1



[PATCH v3 5/9] tests/exynos: use XRGB8888 for framebuffer

2015-11-30 Thread Hyungwon Hwang
From: Tobias Jakobi 

This matches the G2D color mode that is used in the entire code.
The previous (incorrect) RGBA would only work since the
Exynos mixer did its configuration based on the bpp, and not
based on the actual pixelformat.

Reviewed-by: Hyungwon Hwang 
Signed-off-by: Tobias Jakobi 
---
 tests/exynos/exynos_fimg2d_test.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/exynos/exynos_fimg2d_test.c 
b/tests/exynos/exynos_fimg2d_test.c
index 8794dac..dfb00a0 100644
--- a/tests/exynos/exynos_fimg2d_test.c
+++ b/tests/exynos/exynos_fimg2d_test.c
@@ -675,7 +675,7 @@ int main(int argc, char **argv)
offsets[0] = 0;

ret = drmModeAddFB2(dev->fd, screen_width, screen_height,
-   DRM_FORMAT_RGBA, handles,
+   DRM_FORMAT_XRGB, handles,
pitches, offsets, &fb_id, 0);
if (ret < 0)
goto err_destroy_buffer;
-- 
1.9.1



[PATCH v3 2/9] tests/exynos: add fimg2d performance analysis

2015-11-30 Thread Hyungwon Hwang
From: Tobias Jakobi 

Currently only fast solid color clear performance is measured.
A large buffer is allocated and solid color clear operations
are executed on it with randomly chosen properties (position
and size of the region, clear color). Execution time is
measured and output together with the amount of pixels
processed.

The 'simple' variant only executes one G2D command buffer at
a time, while the 'multi' variant executes multiple ones. This
can be used to measure setup/exec overhead.

The test also serves a stability check. If clocks/voltages are
too high or low respectively, the test quickly reveals this.

Tested-by: Hyungwon Hwang 
Reviewed-by: Hyungwon Hwang 
Signed-off-by: Tobias Jakobi 
---
Changes for
v2: Add GPLv2 header, argument handling and documentation.
Tool is only installed when requested.
v3: Free images array in fimg2d_perf_multi() as pointed out
    by Hyungwon Hwang.
v4: Include header for error numbers (fixes build).
v5: Add binary to .gitignore.

 .gitignore|   1 +
 tests/exynos/Makefile.am  |  19 ++-
 tests/exynos/exynos_fimg2d_perf.c | 327 ++
 3 files changed, 345 insertions(+), 2 deletions(-)
 create mode 100644 tests/exynos/exynos_fimg2d_perf.c

diff --git a/.gitignore b/.gitignore
index 79b2ac1..204724a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -94,5 +94,6 @@ tests/proptest/proptest
 tests/kmstest/kmstest
 tests/vbltest/vbltest
 tests/radeon/radeon_ttm
+tests/exynos/exynos_fimg2d_perf
 tests/exynos/exynos_fimg2d_test
 man/*.3
diff --git a/tests/exynos/Makefile.am b/tests/exynos/Makefile.am
index b21d016..e82d199 100644
--- a/tests/exynos/Makefile.am
+++ b/tests/exynos/Makefile.am
@@ -5,16 +5,31 @@ AM_CFLAGS = \
-I $(top_srcdir)/exynos \
-I $(top_srcdir)

+bin_PROGRAMS =
+noinst_PROGRAMS =
+
 if HAVE_LIBKMS
 if HAVE_INSTALL_TESTS
-bin_PROGRAMS = \
+bin_PROGRAMS += \
exynos_fimg2d_test
 else
-noinst_PROGRAMS = \
+noinst_PROGRAMS += \
exynos_fimg2d_test
 endif
 endif

+if HAVE_INSTALL_TESTS
+bin_PROGRAMS += \
+   exynos_fimg2d_perf
+else
+noinst_PROGRAMS += \
+   exynos_fimg2d_perf
+endif
+
+exynos_fimg2d_perf_LDADD = \
+   $(top_builddir)/libdrm.la \
+   $(top_builddir)/exynos/libdrm_exynos.la
+
 exynos_fimg2d_test_LDADD = \
$(top_builddir)/libdrm.la \
$(top_builddir)/libkms/libkms.la \
diff --git a/tests/exynos/exynos_fimg2d_perf.c 
b/tests/exynos/exynos_fimg2d_perf.c
new file mode 100644
index 000..1699bba
--- /dev/null
+++ b/tests/exynos/exynos_fimg2d_perf.c
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2015 - Tobias Jakobi
+ *
+ * This is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation, either version 2 of the License,
+ * or (at your option) any later version.
+ *
+ * It is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with it. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include "exynos_drm.h"
+#include "exynos_drmif.h"
+#include "exynos_fimg2d.h"
+
+static int output_mathematica = 0;
+
+static int fimg2d_perf_simple(struct exynos_bo *bo, struct g2d_context *ctx,
+   unsigned buf_width, unsigned buf_height, unsigned 
iterations)
+{
+   struct timespec tspec = { 0 };
+   struct g2d_image img = { 0 };
+
+   unsigned long long g2d_time;
+   unsigned i;
+   int ret = 0;
+
+   img.width = buf_width;
+   img.height = buf_height;
+   img.stride = buf_width * 4;
+   img.color_mode = G2D_COLOR_FMT_ARGB | G2D_ORDER_AXRGB;
+   img.buf_type = G2D_IMGBUF_GEM;
+   img.bo[0] = bo->handle;
+
+   srand(time(NULL));
+
+   printf("starting simple G2D performance test\n");
+   printf("buffer width = %u, buffer height = %u, iterations = %u\n",
+   buf_width, buf_height, iterations);
+
+   if (output_mathematica)
+   putchar('{');
+
+   for (i = 0; i < iterations; ++i) {
+   unsigned x, y, w, h;
+
+   x = rand() % buf_width;
+   y = rand() % buf_height;
+
+   if (x == (buf_width - 1))
+   x -= 1;
+   if (y == (buf_height - 1))
+   y -= 1;
+
+   w = rand() % (buf_width - x);
+   h = rand() % (buf_height - y);
+
+   if (w == 0) w = 1;
+   if (h == 0) h = 1;
+
+   img.color = rand();
+
+   ret = g2d_solid_fill(ctx, &img, x, y,

[PATCH v3 6/9] exynos: fimg2d: add g2d_set_direction

2015-11-30 Thread Hyungwon Hwang
From: Tobias Jakobi 

This allows setting the two direction registers, which specify how
the engine blits pixels. This can be used for overlapping blits,
which happen e.g. when 'moving' a rectangular region inside a
fixed buffer.

Reviewed-by: Hyungwon Hwang 
Signed-off-by: Tobias Jakobi 
Signed-off-by: Hyungwon Hwang 
---
Changes for v3:
- Definitions of e_g2d_dir_mode, g2d_direction_val are moved to source file
from header file

 exynos/exynos_fimg2d.c | 51 ++
 1 file changed, 51 insertions(+)

diff --git a/exynos/exynos_fimg2d.c b/exynos/exynos_fimg2d.c
index b10620b..3bef93b 100644
--- a/exynos/exynos_fimg2d.c
+++ b/exynos/exynos_fimg2d.c
@@ -65,6 +65,44 @@ enum g2d_base_addr_reg {
g2d_src
 };

+enum e_g2d_dir_mode {
+   G2D_DIR_MODE_POSITIVE = 0,
+   G2D_DIR_MODE_NEGATIVE = 1
+};
+
+union g2d_direction_val {
+   unsigned int val[2];
+   struct {
+   /* SRC_MSK_DIRECT_REG [0:1] (source) */
+   enum e_g2d_dir_mode src_x_direction:1;
+   enum e_g2d_dir_mode src_y_direction:1;
+
+   /* SRC_MSK_DIRECT_REG [2:3] */
+   unsigned intreversed1:2;
+
+   /* SRC_MSK_DIRECT_REG [4:5] (mask) */
+   enum e_g2d_dir_mode mask_x_direction:1;
+   enum e_g2d_dir_mode mask_y_direction:1;
+
+   /* SRC_MSK_DIRECT_REG [6:31] */
+   unsigned intpadding1:26;
+
+   /* DST_PAT_DIRECT_REG [0:1] (destination) */
+   enum e_g2d_dir_mode dst_x_direction:1;
+   enum e_g2d_dir_mode dst_y_direction:1;
+
+   /* DST_PAT_DIRECT_REG [2:3] */
+   unsigned intreversed2:2;
+
+   /* DST_PAT_DIRECT_REG [4:5] (pattern) */
+   enum e_g2d_dir_mode pat_x_direction:1;
+   enum e_g2d_dir_mode pat_y_direction:1;
+
+   /* DST_PAT_DIRECT_REG [6:31] */
+   unsigned intpadding2:26;
+   } data;
+};
+
 static unsigned int g2d_get_scaling(unsigned int src, unsigned int dst)
 {
/*
@@ -242,6 +280,19 @@ static void g2d_add_base_addr(struct g2d_context *ctx, 
struct g2d_image *img,
 }

 /*
+ * g2d_set_direction - setup direction register (useful for overlapping blits).
+ *
+ * @ctx: a pointer to g2d_context structure.
+ * @dir: a pointer to the g2d_direction_val structure.
+ */
+static void g2d_set_direction(struct g2d_context *ctx,
+   const union g2d_direction_val *dir)
+{
+   g2d_add_cmd(ctx, SRC_MASK_DIRECT_REG, dir->val[0]);
+   g2d_add_cmd(ctx, DST_PAT_DIRECT_REG, dir->val[1]);
+}
+
+/*
  * g2d_reset - reset fimg2d hardware.
  *
  * @ctx: a pointer to g2d_context structure.
--
1.9.1



[PATCH v3 9/9] exynos: bump version number

2015-11-30 Thread Hyungwon Hwang
From: Tobias Jakobi 

The Exynos API was extended quite a bit, so reflect this in the
version number.

Signed-off-by: Tobias Jakobi 
---
 exynos/libdrm_exynos.pc.in | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/exynos/libdrm_exynos.pc.in b/exynos/libdrm_exynos.pc.in
index 5ce9118..ff1c432 100644
--- a/exynos/libdrm_exynos.pc.in
+++ b/exynos/libdrm_exynos.pc.in
@@ -5,7 +5,7 @@ includedir=@includedir@

 Name: libdrm_exynos
 Description: Userspace interface to exynos kernel DRM services
-Version: 0.6
+Version: 0.7
 Libs: -L${libdir} -ldrm_exynos
 Cflags: -I${includedir} -I${includedir}/libdrm -I${includedir}/exynos
 Requires.private: libdrm
-- 
1.9.1



[PATCH v3 8/9] tests/exynos: add test for g2d_move

2015-11-30 Thread Hyungwon Hwang
From: Tobias Jakobi 

To check if g2d_move() works properly we create a small checkerboard
pattern in the center of the screen and then shift this pattern
around with g2d_move(). The pattern should be properly preserved
by the operation (but not the surrounding area).

Tested-by: Hyungwon Hwang 
Reviewed-by: Hyungwon Hwang 
Signed-off-by: Tobias Jakobi 
---
 tests/exynos/exynos_fimg2d_test.c | 132 ++
 1 file changed, 132 insertions(+)

diff --git a/tests/exynos/exynos_fimg2d_test.c 
b/tests/exynos/exynos_fimg2d_test.c
index dfb00a0..797fb6e 100644
--- a/tests/exynos/exynos_fimg2d_test.c
+++ b/tests/exynos/exynos_fimg2d_test.c
@@ -313,6 +313,130 @@ fail:
return ret;
 }

+static int g2d_move_test(struct exynos_device *dev,
+   struct exynos_bo *tmp,
+   struct exynos_bo *buf,
+   enum e_g2d_buf_type type)
+{
+   struct g2d_context *ctx;
+   struct g2d_image img = {0}, tmp_img = {0};
+   unsigned int img_w, img_h, count;
+   int cur_x, cur_y;
+   void *checkerboard;
+   int ret;
+
+   static const struct g2d_step {
+   int x, y;
+   } steps[] = {
+   { 1,  0}, { 0,  1},
+   {-1,  0}, { 0, -1},
+   { 1,  1}, {-1, -1},
+   { 1, -1}, {-1,  1},
+   { 2,  1}, { 1,  2},
+   {-2, -1}, {-1, -2},
+   { 2, -1}, { 1, -2},
+   {-2,  1}, {-1,  2}
+   };
+   static const unsigned int num_steps =
+   sizeof(steps) / sizeof(struct g2d_step);
+
+   ctx = g2d_init(dev->fd);
+   if (!ctx)
+   return -EFAULT;
+
+   img.bo[0] = buf->handle;
+
+   /* create pattern of half the screen size */
+   checkerboard = create_checkerboard_pattern(screen_width / 64, 
screen_height / 64, 32);
+   if (!checkerboard) {
+   ret = -EFAULT;
+   goto fail;
+   }
+
+   img_w = (screen_width / 64) * 32;
+   img_h = (screen_height / 64) * 32;
+
+   switch (type) {
+   case G2D_IMGBUF_GEM:
+   memcpy(tmp->vaddr, checkerboard, img_w * img_h * 4);
+   tmp_img.bo[0] = tmp->handle;
+   break;
+   case G2D_IMGBUF_USERPTR:
+   tmp_img.user_ptr[0].userptr = (unsigned long)checkerboard;
+   tmp_img.user_ptr[0].size = img_w * img_h * 4;
+   break;
+   case G2D_IMGBUF_COLOR:
+   default:
+   ret = -EFAULT;
+   goto fail;
+   }
+
+   /* solid fill framebuffer with white color */
+   img.width = screen_width;
+   img.height = screen_height;
+   img.stride = screen_width * 4;
+   img.buf_type = G2D_IMGBUF_GEM;
+   img.color_mode = G2D_COLOR_FMT_ARGB | G2D_ORDER_AXRGB;
+   img.color = 0x;
+
+   /* put checkerboard pattern in the center of the framebuffer */
+   cur_x = (screen_width - img_w) / 2;
+   cur_y = (screen_height - img_h) / 2;
+   tmp_img.width = img_w;
+   tmp_img.height = img_h;
+   tmp_img.stride = img_w * 4;
+   tmp_img.buf_type = type;
+   tmp_img.color_mode = G2D_COLOR_FMT_ARGB | G2D_ORDER_AXRGB;
+
+   ret = g2d_solid_fill(ctx, &img, 0, 0, screen_width, screen_height) ||
+   g2d_copy(ctx, &tmp_img, &img, 0, 0, cur_x, cur_y, img_w, img_h);
+
+   if (!ret)
+   ret = g2d_exec(ctx);
+   if (ret < 0)
+   goto fail;
+
+   printf("move test with %s.\n",
+   type == G2D_IMGBUF_GEM ? "gem" : "userptr");
+
+   srand(time(NULL));
+   for (count = 0; count < 256; ++count) {
+   const struct g2d_step *s;
+
+   /* select step and validate it */
+   while (1) {
+   s = &steps[random() % num_steps];
+
+   if (cur_x + s->x < 0 || cur_y + s->y < 0 ||
+   cur_x + img_w + s->x >= screen_width ||
+   cur_y + img_h + s->y >= screen_height)
+   continue;
+   else
+   break;
+   }
+
+   ret = g2d_move(ctx, &img, cur_x, cur_y, cur_x + s->x, cur_y + 
s->y,
+   img_w, img_h);
+   if (!ret)
+   ret = g2d_exec(ctx);
+
+   if (ret < 0)
+   goto fail;
+
+   cur_x += s->x;
+   cur_y += s->y;
+
+   usleep(10);
+   }
+
+fail:
+   g2d_fini(ctx);
+
+   free(checkerboard);
+
+   return ret;
+}
+
 static int g2d_copy_with_scale_test(struct exynos_device *dev,
struct exynos_bo *src,
struct exynos_

[PATCH] drm: Implement drmHandleEvent2()

2015-11-30 Thread Hyungwon Hwang
From: Tobias Jakobi 

Basically this is an extended version of drmHandleEvent().

drmHandleEvent() only handles core events (like e.g. page flips),
but since kernel DRM drivers might use vendor-specific events
to signal userspace the completion of pending jobs, etc., its
desirable to provide a way to handle these without putting
vendor-specific code in the core libdrm.

To use this you provide drmHandleEvent2() with a function that
handles your non-core events.

The signature of that function looks like this:
void vendor(int fd, struct drm_event *e, void *ctx);

'fd' is the DRM file descriptor, 'e' the non-core event
and 'ctx' the event context (casted to void).

This way we don't have to maintain a copy of drmHandleEvent()
in the vendor code.

Signed-off-by: Tobias Jakobi 
---
Changes for v2:
- Remove the opaque pointer, since this can be better handled with
a container approach.

This patch is separated from Tobias's patchset. Please refer to
http://lists.freedesktop.org/archives/dri-devel/2015-November/095456.html

 xf86drm.h | 21 +
 xf86drmMode.c | 10 +-
 2 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/xf86drm.h b/xf86drm.h
index 481d882..1e474a3 100644
--- a/xf86drm.h
+++ b/xf86drm.h
@@ -750,8 +750,29 @@ typedef struct _drmEventContext {

 } drmEventContext, *drmEventContextPtr;

+typedef void (*drmEventVendorHandler)(int fd, struct drm_event *e, void *ctx);
+
 extern int drmHandleEvent(int fd, drmEventContextPtr evctx);

+/*
+ * drmHandleEvent2() is an extended variant of drmHandleEvent() which
+ * allows handling of vendor-specific/non-core events.
+ * The function pointer 'vendorhandler' is used (if non-zero) to
+ * process non-core events. Users of have to prepare a container struct
+ * in the following way:
+ *
+ * struct vendor_event_context {
+ * drmEventContext base;
+ * int vendor_specific_data[num];
+ * };
+ *
+ * And then call:
+ * struct vendor_event_context ctx = {0};
+ * drmHandleEvent2(fd, &ctx.base, handler);
+ */
+extern int drmHandleEvent2(int fd, drmEventContextPtr evctx,
+   drmEventVendorHandler vendorhandler);
+
 extern char *drmGetDeviceNameFromFd(int fd);
 extern int drmGetNodeTypeFromFd(int fd);

diff --git a/xf86drmMode.c b/xf86drmMode.c
index ab6b519..89698da 100644
--- a/xf86drmMode.c
+++ b/xf86drmMode.c
@@ -867,7 +867,8 @@ int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t 
size,
return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETGAMMA, &l);
 }

-int drmHandleEvent(int fd, drmEventContextPtr evctx)
+int drmHandleEvent2(int fd, drmEventContextPtr evctx,
+   drmEventVendorHandler vendorhandler)
 {
char buffer[1024];
int len, i;
@@ -910,6 +911,8 @@ int drmHandleEvent(int fd, drmEventContextPtr evctx)
 U642VOID (vblank->user_data));
break;
default:
+   if (vendorhandler)
+   vendorhandler(fd, e, evctx);
break;
}
i += e->length;
@@ -918,6 +921,11 @@ int drmHandleEvent(int fd, drmEventContextPtr evctx)
return 0;
 }

+int drmHandleEvent(int fd, drmEventContextPtr evctx)
+{
+   return drmHandleEvent2(fd, evctx, NULL);
+}
+
 int drmModePageFlip(int fd, uint32_t crtc_id, uint32_t fb_id,
uint32_t flags, void *user_data)
 {
--
1.9.1



[PATCH v3 0/9] drm/exynos: new G2D test programs and improvement

2015-11-30 Thread Hyungwon Hwang
Hello,

this series mostly touches G2D code. It introduces the following:

(1) A small performance test application which can be used to measure
the speed of solid color clear operations. Interesting for
benchmarking and plotting colorful graphs (e.g. through
Mathematica).

(2) g2d_move() which works similar to g2d_copy() but like the C
memmove() properly handles overlapping buffer copies.
Again a test application is present to check that this
indeed does what it should.

(3) Various small changes. A framebuffer colorformat fix for the
general G2D test application.

(4) Last but not least a small bump of the Exynos version number.

Please review and let me know what I should change/improve.

With best wishes on behalf of Tobias,
Hyungwon Hwang

Changes since v1:
- Added wording changes suggested by Hyungwon Hwang.
- Added binaries for new test applications to .gitignore.
- Collected r-b and t-b tags.

Changes since v2:
- Patches for public API changes (g2d_reset, exynos_bo_unmap, drmHandleEvent)
are excluded.
- Definitions which are used internally are moved from public header to source
file

ps. I've added SOB by me only to the 3 patches I've modified. You can check
easily find the changes by finding SOB by me from the previous series.

ps2. Firewall in the office blocked this email when I sent the patchset today.
So I resend this email again.

Tobias Jakobi (9):
  exynos: Introduce exynos_handle_event()
  tests/exynos: add fimg2d performance analysis
  exynos/fimg2d: add g2d_config_event
  tests/exynos: add fimg2d event test
  tests/exynos: use XRGB for framebuffer
  exynos: fimg2d: add g2d_set_direction
  exynos/fimg2d: add g2d_move
  tests/exynos: add test for g2d_move
  exynos: bump version number

 .gitignore |   2 +
 exynos/exynos-symbol-check |   2 +
 exynos/exynos_drm.c|  76 +
 exynos/exynos_drm.h|  12 ++
 exynos/exynos_drmif.h  |  26 +++
 exynos/exynos_fimg2d.c | 174 +++-
 exynos/exynos_fimg2d.h |   4 +
 exynos/libdrm_exynos.pc.in |   2 +-
 tests/exynos/Makefile.am   |  26 ++-
 tests/exynos/exynos_fimg2d_event.c | 326 
 tests/exynos/exynos_fimg2d_perf.c  | 327 +
 tests/exynos/exynos_fimg2d_test.c  | 134 ++-
 12 files changed, 1105 insertions(+), 6 deletions(-)
 create mode 100644 tests/exynos/exynos_fimg2d_event.c
 create mode 100644 tests/exynos/exynos_fimg2d_perf.c

--
1.9.1



  1   2   >