radeon_connector->audio is set by RADEON_AUDIO_DISABLE as default.

2016-04-15 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, _connector->base,
>>_dp_connector_funcs,
>> connector_type);
>> drm_connector_helper_add(_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, _connector->base,
>>
>> _lvds_bridge_connector_funcs, connector_type);
>> drm_connector_helper_add(_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_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,
_connector->base,
> > >_dp_connector_funcs,
> > > connector_type);
> > >
 drm_connector_helper_add(_connector->base,
> > > @@ -2024,8 +2025,9 @@ radeon_add_atom_connector(struct drm_device
> > > *dev,
> > >   1);
> > > }
> > > break;
> > > -   case DRM_MODE_CONNECTOR_LVDS:
> > > case DRM_MOD

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, _connector->base,
> >_dp_connector_funcs,
> > connector_type);
> >
 drm_connector_helper_add(_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, _connector->base,
> >
> > _lvds_bridge_connector_funcs, connector_type);
> >
 drm_connector_helper_add(_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 = RAD

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, _connector->base,
   _dp_connector_funcs,
connector_type);
drm_connector_helper_add(_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, _connector->base,

_lvds_bridge_connector_funcs, connector_type);
drm_connector_helper_add(_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:


[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



[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, , 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, );
 }

-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 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 <tjak...@math.uni-bielefeld.de>

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, , 0, 0, screen_width, screen_height) ||
+   g2d_copy(ctx, _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 = [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, , 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_bo *dst,
@@ -7

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

2015-11-30 Thread Hyungwon Hwang
From: Tobias Jakobi <tjak...@math.uni-bielefeld.de>

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, );
+
+   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 6/9] exynos: fimg2d: add g2d_set_direction

2015-11-30 Thread Hyungwon Hwang
From: Tobias Jakobi <tjak...@math.uni-bielefeld.de>

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 5/9] tests/exynos: use XRGB8888 for framebuffer

2015-11-30 Thread Hyungwon Hwang
From: Tobias Jakobi <tjak...@math.uni-bielefeld.de>

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, _id, 0);
if (ret < 0)
goto err_destroy_buffer;
-- 
1.9.1



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

2015-11-30 Thread Hyungwon Hwang
From: Tobias Jakobi <tjak...@math.uni-bielefeld.de>

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(>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, >evhandler.evctx);
+   }
+
+   pthread_exit(0);
+}
+
+/*
+ * We need

[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)>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 2/9] tests/exynos: add fimg2d performance analysis

2015-11-30 Thread Hyungwon Hwang
From: Tobias Jakobi <tjak...@math.uni-bielefeld.de>

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, , x, y, w, h);
+
+  

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

2015-11-30 Thread Hyungwon Hwang
From: Tobias Jakobi <tjak...@math.uni-bielefeld.de>

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 = >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 *) [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 

[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 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 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-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 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 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 = 33209
> > num_pi

[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->width > w)
> >> +  dst_w = img->width - ds

[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
hard not by doing that, becau

[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");
> + printf(&quo

[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, , 0, 0, screen_width,
> screen_height) ||
> + g2d_copy(ctx, _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 = [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 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, );
> +
> + 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/e

[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_DIRECT_REG [0:1] (source) */
> >

[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, _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 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 =
> >> %u) finish

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

2015-10-30 Thread 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; +

As I commented in the patch 08/13, I think that direction is related
with flip. If I am right, these two if statements looks awkward.

Best regards,
Hyungwon Hwang

> + g2d_set_direction(ctx, );
> +
> + 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 9eee7c0..2700686 100644
> --- a/exynos/exynos_fimg2d.h
> +++ b/exynos/exynos_fimg2d.h
> @@ -343,6 +343,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,



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

2015-10-30 Thread Hyungwon Hwang
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.

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_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;
> +};
> +
>  struct g2d_image {
>   enum e_g2d_select_mode  select_mode;
>   enum e_g2d_color_mode   color_mode;



[PATCH 03/13] tests/exynos: add fimg2d performance analysis

2015-10-30 Thread Hyungwon Hwang
();
> +
> + ret = g2d_solid_fill(ctx, , x, y, w, h);
> +
> + clock_gettime(CLOCK_MONOTONIC, );
> +
> + if (ret == 0)
> + ret = g2d_exec(ctx);
> +
> + if (ret != 0) {
> + fprintf(stderr, "error: iteration %u failed
> (x = %u, y = %u, w = %u, h = %u)\n",
> + i, x, y, w, h);
> + break;
> + } else {
> + struct timespec end = { 0 };
> + clock_gettime(CLOCK_MONOTONIC, );
> +
> + g2d_time = (end.tv_sec - tspec.tv_sec) *
> 10ULL;
> + g2d_time += (end.tv_nsec - tspec.tv_nsec);
> +
> + if (output_mathematica) {
> + if (i != 0) putchar(',');
> + printf("{%u,%llu}", w * h, g2d_time);
> + } else {
> + printf("num_pixels = %u, usecs =
> %llu\n", w * h, g2d_time);
> + }
> +     }
> + }
> +
> + if (output_mathematica)
> + printf("}\n");
> +
> + return ret;
> +}
> +
> +static int fimg2d_perf_multi(struct exynos_bo *bo, struct
> g2d_context *ctx,
> + unsigned buf_width, unsigned buf_height,
> unsigned iterations, unsigned batch) +{
> + struct timespec tspec = { 0 };
> + struct g2d_image *images;
> +
> + unsigned long long g2d_time;
> + unsigned i, j;
> + int ret = 0;
> +
> + images = calloc(batch, sizeof(struct g2d_image));

I think that this should be freed at the end of this function.

Best regards,
Hyungwon Hwang

> + for (i = 0; i < batch; ++i) {
> + images[i].width = buf_width;
> + images[i].height = buf_height;
> + images[i].stride = buf_width * 4;
> + images[i].color_mode = G2D_COLOR_FMT_ARGB |
> G2D_ORDER_AXRGB;
> + images[i].buf_type = G2D_IMGBUF_GEM;
> + images[i].bo[0] = bo->handle;
> + }
> +
> + srand(time(NULL));
> +
> + printf("starting multi G2D performance test (batch size =
> %u)\n", batch);
> + 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 num_pixels = 0;
> +
> + for (j = 0; j < batch; ++j) {
> + 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;
> +
> + images[j].color = rand();
> +
> + num_pixels += w * h;
> +
> + ret = g2d_solid_fill(ctx, [j], x, y,
> w, h);
> + if (ret != 0)
> + break;
> + }
> +
> + clock_gettime(CLOCK_MONOTONIC, );
> +
> + if (ret == 0)
> + ret = g2d_exec(ctx);
> +
> + if (ret != 0) {
> + fprintf(stderr, "error: iteration %u failed
> (num_pixels = %u)\n", i, num_pixels);
> + break;
> + break;
> + } else {
> + struct timespec end = { 0 };
> + clock_gettime(CLOCK_MONOTONIC, );
> +
> + g2d_time = (end.tv_sec - tspec.tv_sec) *
> 10ULL;
> + g2d_time += (end.tv_nsec - tspec.tv_nsec);
> +
> + if (output_mathematica) {
> + if (i != 0) putchar(',');
> + printf("{%u,%llu}", num_pixels,
> g2d_time);
> + } else {
> + printf("num_pixels = %u, usecs =
> %llu\n", num_pixels, g2d_time);
> + }
> + }
> + }
> +
> + if (output_mathematica)
> + printf("}\n");
> +
> + return ret;
> +}
> +
> +static void usage(const char *name)
> +{
> + f

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

2015-10-30 Thread Hyungwon Hwang
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 =
> %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 = DRM_EVENT_CONTEXT_VERSION;
> + evhandler->evctx.version = EXYNOS_EVENT_CONTEXT_VERSION;

The versions must be set not using XXX_EVENT_CONTEXT_VERSION. After the
versions are bumped, the event will contains wrong version info.

Also, I think the type of event must be set here.

Best regards,
Hyungwon Hwang

> + 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(>evhandler.fds, 1, timeout) < 0)
> +   

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

2015-10-30 Thread Hyungwon Hwang
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, _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.

Best regards,
Hyungwon Hwang


>   if (ret < 0)
>   goto err_destroy_buffer;



[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(, 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;
+   int 

[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 = >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(stde

[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 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(, 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 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(>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(>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] 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(>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(>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 exynos_drm_plan

[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(, 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, _bo, _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(>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(, 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;
+  

[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 = >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 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 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 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
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 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 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(>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(>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(>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/exynos7_drm_decon.c
index 0792654.

[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 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(, 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, _bo, _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(>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(, 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();
+   FD_SET(0, );
+   FD_SET(dev->fd, );
+   ret = select(dev->fd + 1, , NULL, NULL, );
+
+  

[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", _id, _id, ) != 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 = >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 = >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,
+   uint32_t width, uint32_t height, uint32_t pixe

[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(_args[count], optarg) < 0)
usage(argv[0]);

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



[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, );
 }

-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 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(>items[i], >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(>items[i], >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] = req->items[i].property_id;
+  

[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 2/2] drm/exynos: gsc: Handles the combination of rotation and flip

2015-07-01 Thread Hyungwon Hwang
The unique results of all the combination of rotation and flip can
be represented by just 8 states. This patch handles all the combination
correctly.

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

diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c 
b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
index f1c6b76..808a0a0 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
@@ -582,9 +582,17 @@ static int gsc_src_set_transf(struct device *dev,
break;
case EXYNOS_DRM_DEGREE_180:
cfg |= GSC_IN_ROT_180;
+   if (flip & EXYNOS_DRM_FLIP_VERTICAL)
+   cfg &= ~GSC_IN_ROT_XFLIP;
+   if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
+   cfg &= ~GSC_IN_ROT_YFLIP;
break;
case EXYNOS_DRM_DEGREE_270:
cfg |= GSC_IN_ROT_270;
+   if (flip & EXYNOS_DRM_FLIP_VERTICAL)
+   cfg &= ~GSC_IN_ROT_XFLIP;
+   if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
+   cfg &= ~GSC_IN_ROT_YFLIP;
break;
default:
dev_err(ippdrv->dev, "inavlid degree value %d.\n", degree);
@@ -845,9 +853,17 @@ static int gsc_dst_set_transf(struct device *dev,
break;
case EXYNOS_DRM_DEGREE_180:
cfg |= GSC_IN_ROT_180;
+   if (flip & EXYNOS_DRM_FLIP_VERTICAL)
+   cfg &= ~GSC_IN_ROT_XFLIP;
+   if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
+   cfg &= ~GSC_IN_ROT_YFLIP;
break;
case EXYNOS_DRM_DEGREE_270:
cfg |= GSC_IN_ROT_270;
+   if (flip & EXYNOS_DRM_FLIP_VERTICAL)
+   cfg &= ~GSC_IN_ROT_XFLIP;
+   if (flip & EXYNOS_DRM_FLIP_HORIZONTAL)
+   cfg &= ~GSC_IN_ROT_YFLIP;
break;
default:
dev_err(ippdrv->dev, "inavlid degree value %d.\n", degree);
-- 
1.9.1



[PATCH 1/2] drm/exynos: gsc: fix wrong bitwise operation for swap detection

2015-07-01 Thread Hyungwon Hwang
The bits for rotation are not used as exclusively. So GSC_IN_ROT_270 can
not be used for swap detection. The definition of it is same with
GSC_IN_ROT_MASK. It is enough to check GSC_IN_ROT_90 bit is set or not to
check whether width / height size swapping is needed.

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

diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c 
b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
index 8040ed2..f1c6b76 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
@@ -593,8 +593,7 @@ static int gsc_src_set_transf(struct device *dev,

gsc_write(cfg, GSC_IN_CON);

-   ctx->rotation = cfg &
-   (GSC_IN_ROT_90 | GSC_IN_ROT_270) ? 1 : 0;
+   ctx->rotation = (cfg & GSC_IN_ROT_90) ? 1 : 0;
*swap = ctx->rotation;

return 0;
@@ -857,8 +856,7 @@ static int gsc_dst_set_transf(struct device *dev,

gsc_write(cfg, GSC_IN_CON);

-   ctx->rotation = cfg &
-   (GSC_IN_ROT_90 | GSC_IN_ROT_270) ? 1 : 0;
+   ctx->rotation = (cfg & GSC_IN_ROT_90) ? 1 : 0;
*swap = ctx->rotation;

return 0;
-- 
1.9.1



[PATCH] drm/exynos: iommu: fix potential NULL pointer dereference

2015-06-29 Thread Hyungwon Hwang
Dear Marek,

On Thu, 25 Jun 2015 15:10:12 +0200
Marek Szyprowski  wrote:

> Some drivers (like Exynos mixer) calls
> drm_iommu_attach_device_if_possible before registering crtc, so
> additional check for NULL crtc pointer is required.

It seems reasonable.

Reviewed-by: Hyungwon Hwang 

> 
> Signed-off-by: Marek Szyprowski 
> ---
>  drivers/gpu/drm/exynos/exynos_drm_iommu.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_iommu.c
> b/drivers/gpu/drm/exynos/exynos_drm_iommu.c index
> d4ec7465e9cc..d4eb730ba254 100644 ---
> a/drivers/gpu/drm/exynos/exynos_drm_iommu.c +++
> b/drivers/gpu/drm/exynos/exynos_drm_iommu.c @@ -151,7 +151,7 @@ int
> drm_iommu_attach_device_if_possible(struct exynos_drm_crtc
> *exynos_crtc, int ret = 0; 
>   if (is_drm_iommu_supported(drm_dev)) {
> - if (exynos_crtc->ops->clear_channels)
> + if (exynos_crtc && exynos_crtc->ops->clear_channels)
>   exynos_crtc->ops->clear_channels(exynos_crtc);
>   return drm_iommu_attach_device(drm_dev, subdrv_dev);
>   }



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

2015-06-29 Thread Hyungwon Hwang
Dear Theirry,

Gentle ping. I modified as you reviewed before. Also I wrote the
reason for using passing variable by reference for error checking. Can
you share your opinion for that, and review this driver?

Best regards,
Hyungwon Hwang

On Fri, 29 May 2015 18:47:02 +0900
Hyungwon Hwang  wrote:
> 
> 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 = <_reg>;
> +   vci-supply = <_reg>;
> +   reset-gpio = < 0 GPIO_ACTIVE_LOW>;
> +   enable-gpio = < 5 GPIO_ACTIVE_HIGH>;
> +   te-gpio = < 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..

[PATCH v3] ARM: dts: fix the clock-frequency of rinato board's panel

2015-06-15 Thread Hyungwon Hwang
From: Hyungwon Hwang <human.hw...@samsung.com>

After the commit abc0b1447d4974963548777a5ba4a4457c82c426
("drm: Perform basic sanity checks on probed modes"), proper
clock-frequency becomes mandatory for validating the mode of panel.
The display does not work if there is no mode validated. Also, this
clock-frequency must be set appropriately for getting required frame
rate.

Fixes: abc0b1447d49 ("drm: Perform basic sanity checks on probed modes")
Cc: 
Signed-off-by: Hyungwon Hwang 
---
 arch/arm/boot/dts/exynos3250-rinato.dts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/exynos3250-rinato.dts 
b/arch/arm/boot/dts/exynos3250-rinato.dts
index 0b99068..75aba40 100644
--- a/arch/arm/boot/dts/exynos3250-rinato.dts
+++ b/arch/arm/boot/dts/exynos3250-rinato.dts
@@ -181,7 +181,7 @@

display-timings {
timing-0 {
-   clock-frequency = <0>;
+   clock-frequency = <460>;
hactive = <320>;
vactive = <320>;
hfront-porch = <1>;
-- 
1.8.1.2



[v3,2/3] drm/panel: add s6e63j0x03 LCD panel driver

2015-06-12 Thread Hyungwon Hwang
Please ignore this mail. I didn't know that "git send *" includes all
files in the subdirectories. I am very sorry for disturbing you.

Best regards,
Hyungwon Hwang

On Fri, 12 Jun 2015 21:59:17 +0900
Hyungwon Hwang  wrote:

> 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
> Changes for v3:
> - Add DT binding documentation
> - Add the code getting DT properties of 'panel-width-mm' and
> 'panel-height-mm'
> - Remove the code getting unnecessary DT properties flip-*
>  .../bindings/panel/samsung,s6e63j0x03.txt  |  55 +++
>  drivers/gpu/drm/panel/Kconfig  |   6 +
>  drivers/gpu/drm/panel/Makefile |   1 +
>  drivers/gpu/drm/panel/panel-s6e63j0x03.c   | 546
> + 4 files changed, 608 insertions(+)
>  create mode 100644
> Documentation/devicetree/bindings/panel/samsung,s6e63j0x03.txt create
> mode 100644 drivers/gpu/drm/panel/panel-s6e63j0x03.c
> 
> --
> 1.9.1
> 
> diff --git
> a/Documentation/devicetree/bindings/panel/samsung,s6e63j0x03.txt
> b/Documentation/devicetree/bindings/panel/samsung,s6e63j0x03.txt new
> file mode 100644 index 000..f8215e4 --- /dev/null
> +++ b/Documentation/devicetree/bindings/panel/samsung,s6e63j0x03.txt
> @@ -0,0 +1,55 @@
> +Samsung S6E63J0X03 1.63" 320x320 TFT LCD panel
> +
> +Required properties:
> +  - compatible: "samsung,s6e63j0x03"
> +  - reg: the virtual channel number of a DSI peripheral
> +  - vdd3-supply: core voltage supply
> +  - vci-supply: voltage supply for analog circuits
> +  - reset-gpios: a GPIO spec for the reset pin
> +  - te-gpios: a GPIO spec for the tearing effect synchronization
> signal gpio pin +
> +Optional properties:
> +  - display-timings: timings for the connected panel as described by
> [1]
> +  - power-on-delay: delay after turning regulators on [ms]
> +  - power-off-delay: delay after turning regulators off [ms]
> +  - reset-delay: delay after reset sequence [ms]
> +  - panel-width-mm: physical panel width [mm]
> +  - panel-height-mm: physical panel height [mm]
> +
> +The device node can contain one 'port' child node with one child
> +'endpoint' node, according to the bindings defined in [2]. This
> +node should describe panel's video bus.
> +
> +[1]: Documentation/devicetree/bindings/video/display-timing.txt
> +[2]: Documentation/devicetree/bindings/media/video-interfaces.txt
> +
> +Example:
> +
> +panel at 0 {
> + compatible = "samsung,s6e63j0x03";
> + reg = <0>;
> + vdd3-supply = <_reg>;
> + vci-supply = <_reg>;
> + reset-gpios = < 1 0>;
> + te-gpios = < 6 0>;
> + power-on-delay= <30>;
> + power-off-delay= <120>;
> + reset-delay = <5>;
> + init-delay = <100>;
> + 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>;
> + };
> + };
> +};
> diff --git a/drivers/gpu/drm/panel/Kconfig
> b/drivers/gpu/drm/panel/Kconfig index 3df9b9b..8fa7610 100644
> --- a/drivers/gpu/drm/panel/Kconfig
> +++ b/drivers/gpu/drm/panel/Kconfig
> @@ -46,4 +46,10 @@ config DRM_PANEL_S6E3HA2
>   select DRM_MIPI_DSI
>   select VIDEOMODE_HELPERS
> 
> +config DRM_PANEL_S6E63J0X03
> + tristate "S6E63J0X03 DSI video mode panel"
> + depends on OF
> + sele

[PATCH 3/3] ARM: dts: fix the clock-frequency of rinato board's panel

2015-06-12 Thread Hyungwon Hwang
Please ignore this mail. I didn't know that "git send *" includes all
files in the subdirectories. I am very sorry for disturbing you.

Best regards,
Hyungwon Hwang

On Fri, 12 Jun 2015 21:59:16 +0900
Hyungwon Hwang  wrote:

> After the commit abc0b1447d4974963548777a5ba4a4457c82c426
> ("drm: Perform basic sanity checks on probed modes"), proper
> clock-frequency becomes mandatory for validating the mode of panel.
> The display does not work if there is no mode validated. Also, this
> clock-frequency must be set appropriately for getting required frame
> rate.
> 
> Signed-off-by: Hyungwon Hwang 
> ---
>  arch/arm/boot/dts/exynos3250-rinato.dts | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/arm/boot/dts/exynos3250-rinato.dts
> b/arch/arm/boot/dts/exynos3250-rinato.dts index 0b99068..75aba40
> 100644 --- a/arch/arm/boot/dts/exynos3250-rinato.dts
> +++ b/arch/arm/boot/dts/exynos3250-rinato.dts
> @@ -181,7 +181,7 @@
>  
>   display-timings {
>   timing-0 {
> - clock-frequency = <0>;
> + clock-frequency = <460>;
>   hactive = <320>;
>   vactive = <320>;
>   hfront-porch = <1>;



[PATCH 2/3] ARM: dts: Add the reference node for syscon to mipi phy for Exynos3250

2015-06-12 Thread Hyungwon Hwang
Please ignore this mail. I didn't know that "git send *" includes all
files in the subdirectories. I am very sorry for disturbing you.

Best regards,
Hyungwon Hwang

On Fri, 12 Jun 2015 21:59:15 +0900
Hyungwon Hwang  wrote:

> Exynos mipi phy driver needs syscon node to be probed successfully.
> 
> Signed-off-by: Hyungwon Hwang 
> ---
>  arch/arm/boot/dts/exynos3250.dtsi | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/arch/arm/boot/dts/exynos3250.dtsi
> b/arch/arm/boot/dts/exynos3250.dtsi index e3bfb11..f8c02dd 100644
> --- a/arch/arm/boot/dts/exynos3250.dtsi
> +++ b/arch/arm/boot/dts/exynos3250.dtsi
> @@ -140,6 +140,7 @@
>   compatible =
> "samsung,s5pv210-mipi-video-phy"; reg = <0x10020710 8>;
>   #phy-cells = <1>;
> + syscon = <_system_controller>;
>   };
>  
>   pd_cam: cam-power-domain at 10023C00 {



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

2015-06-12 Thread Hyungwon Hwang
Please ignore this mail. I didn't know that "git send *" includes all
files in the subdirectories. I am very sorry for disturbing you.

Best regards,
Hyungwon Hwang

On Fri, 12 Jun 2015 21:59:14 +0900
Hyungwon Hwang  wrote:

> 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 
> ---
>  drivers/gpu/drm/exynos/exynos_drm_dsi.c | 31
> +++
> drivers/gpu/drm/panel/Kconfig   |  6 ++
> drivers/gpu/drm/panel/Makefile  |  1 + 3 files changed, 26
> insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 5576cc3..6cb4887
> 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
> @@ -743,6 +743,14 @@ static void exynos_dsi_disable_clock(struct
> exynos_dsi *dsi) DSI_WRITE(dsi, DSIM_PLLCTRL_REG, reg);
>  }
>  
> +static void exynos_dsi_enable_lane(struct exynos_dsi *dsi, u32 lane)
> +{
> + u32 reg = DSI_READ(dsi, DSIM_CONFIG_REG);
> + reg |= (DSIM_NUM_OF_DATA_LANE(dsi->lanes - 1) |
> DSIM_LANE_EN_CLK |
> + DSIM_LANE_EN(lane));
> + DSI_WRITE(dsi, DSIM_CONFIG_REG, reg);
> +}
> +
>  static int exynos_dsi_init_link(struct exynos_dsi *dsi)
>  {
>   struct exynos_dsi_driver_data *driver_data =
> dsi->driver_data; @@ -815,17 +823,6 @@ static int
> exynos_dsi_init_link(struct exynos_dsi *dsi) return -EINVAL;
>   }
>  
> - reg |= DSIM_NUM_OF_DATA_LANE(dsi->lanes - 1);
> -
> - DSI_WRITE(dsi, DSIM_CONFIG_REG, reg);
> -
> - reg |= DSIM_LANE_EN_CLK;
> - DSI_WRITE(dsi, DSIM_CONFIG_REG, reg);
> -
> - lanes_mask = BIT(dsi->lanes) - 1;
> - reg |= DSIM_LANE_EN(lanes_mask);
> - DSI_WRITE(dsi, DSIM_CONFIG_REG, reg);
> -
>   /*
>* Use non-continuous clock mode if the periparal wants and
>* host controller supports
> @@ -837,8 +834,11 @@ static int exynos_dsi_init_link(struct
> exynos_dsi *dsi) if (driver_data->has_clklane_stop &&
>   dsi->mode_flags &
> MIPI_DSI_CLOCK_NON_CONTINUOUS) { reg |= DSIM_CLKLANE_STOP;
> - DSI_WRITE(dsi, DSIM_CONFIG_REG, reg);
>   }
> + DSI_WRITE(dsi, DSIM_CONFIG_REG, reg);
> +
> + lanes_mask = BIT(dsi->lanes) - 1;
> + exynos_dsi_enable_lane(dsi, lanes_mask);
>  
>   /* Check clock and data lane state are stop state */
>   timeout = 100;
> @@ -1301,6 +1301,10 @@ static int exynos_dsi_init(struct exynos_dsi
> *dsi) 
>   exynos_dsi_reset(dsi);
>   exynos_dsi_enable_irq(dsi);
> +
> + if (driver_data->values[RESET_TYPE] == DSIM_FUNCRST)
> + exynos_dsi_enable_lane(dsi, BIT(dsi->lanes) - 1);
> +
>   exynos_dsi_enable_clock(dsi);
>   if (driver_data->wait_for_reset)
>   exynos_dsi_wait_for_reset(dsi);
> @@ -1893,6 +1897,9 @@ static int exynos_dsi_probe(struct
> platform_device *pdev) dsi->clks = devm_kzalloc(dev,
>   sizeof(*dsi->clks) *
> dsi->driver_data->num_clks, GFP_KERNEL);
> + if (!dsi->clks)
> + goto err_del_component;
> +
>   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])) {
> diff --git a/drivers/gpu/drm/panel/Kconfig
> b/drivers/gpu/drm/panel/Kconfig index 6d64c7b..cb07bc6 100644
> --- a/drivers/gpu/drm/panel/Kconfig
> +++ b/drivers/gpu/drm/panel/Kconfig
> @@ -43,4 +43,10 @@ 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_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 4b2a043..27b0a90 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_S6E63J0X03) +=
> panel-s6e63j0x03.o



[PATCH 2/2] drm/exynos: ipp: validate a GEM handle with multiple planes

2015-06-12 Thread Hyungwon Hwang
Please ignore this mail. I didn't know that "git send *" includes all
files in the subdirectories. I am very sorry for disturbing you.

Best regards,
Hyungwon Hwang

On Fri, 12 Jun 2015 21:59:12 +0900
Hyungwon Hwang  wrote:

> FIMC & GSC driver can calculate the offset of planes. So there are
> use cases which IPP receives just one GEM handle of an image with
> multiple plane. This patch extends ipp_validate_mem_node() to validate
> this case.
> 
> Signed-off-by: Hyungwon Hwang 
> ---
>  drivers/gpu/drm/exynos/exynos_drm_ipp.c | 51
> - 1 file changed, 38 insertions(+),
> 13 deletions(-)
> 
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c
> b/drivers/gpu/drm/exynos/exynos_drm_ipp.c index 54c5cf4..b3dc778
> 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
> @@ -482,8 +482,8 @@ static int ipp_validate_mem_node(struct
> drm_device *drm_dev, {
>   struct drm_exynos_ipp_config *ipp_cfg;
>   unsigned int num_plane;
> - unsigned long min_size, size;
> - unsigned int bpp;
> + unsigned long size, buf_size = 0, plane_size, img_size = 0;
> + unsigned int bpp, width, height;
>   int i;
>  
>   ipp_cfg = _node->property.config[m_node->ops_id];
> @@ -497,20 +497,45 @@ static int ipp_validate_mem_node(struct
> drm_device *drm_dev,
>* but it seems more than enough
>*/
>   for (i = 0; i < num_plane; ++i) {
> - if (!m_node->buf_info.handles[i]) {
> - DRM_ERROR("invalid handle for plane %d\n",
> i);
> - return -EINVAL;
> - }
> + width = ipp_cfg->sz.hsize;
> + height = ipp_cfg->sz.vsize;
>   bpp = drm_format_plane_cpp(ipp_cfg->fmt, i);
> - min_size = (ipp_cfg->sz.hsize * ipp_cfg->sz.vsize *
> bpp) >> 3;
> - size = exynos_drm_gem_get_size(drm_dev,
> -
> m_node->buf_info.handles[i],
> -c_node->filp);
> - if (min_size > size) {
> - DRM_ERROR("invalid size for plane %d\n", i);
> - return -EINVAL;
> +
> + /*
> +  * The result of drm_format_plane_cpp() for chroma
> planes must
> +  * be used with drm_format__chroma_subsampling()
> for
> +  * correct result.
> +  */
> + if (i > 0) {
> + width /= drm_format_horz_chroma_subsampling(
> +
> ipp_cfg->fmt);
> + height /= drm_format_vert_chroma_subsampling(
> +
> ipp_cfg->fmt); }
> + plane_size = width * height * bpp;
> + img_size += plane_size;
> +
> + if (m_node->buf_info.handles[i]) {
> + size = exynos_drm_gem_get_size(drm_dev,
> + m_node->buf_info.handles[i],
> + c_node->filp);
> + if (plane_size > size) {
> + DRM_ERROR(
> + "buffer %d is smaller than
> required\n",
> + i);
> + return -EINVAL;
> + }
> +
> + buf_size += size;
> + }
> + }
> +
> + if (buf_size < img_size) {
> + DRM_ERROR("size of buffers(%lu) is smaller than
> image(%lu)\n",
> + buf_size, img_size);
> + return -EINVAL;
>   }
> +
>   return 0;
>  }
>  



[PATCH 1/2] drm/exynos: ipp: fix wrong index referencing a config element

2015-06-12 Thread Hyungwon Hwang
Please ignore this mail. I didn't know that "git send *" includes all
files in the subdirectories. I am very sorry for disturbing you.

Best regards,
Hyungwon Hwang

On Fri, 12 Jun 2015 21:59:11 +0900
Hyungwon Hwang  wrote:

> Config depends on the opreation. So it must be referenced by an
> operation id, not a property id.
> 
> Signed-off-by: Hyungwon Hwang 
> ---
>  drivers/gpu/drm/exynos/exynos_drm_ipp.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c
> b/drivers/gpu/drm/exynos/exynos_drm_ipp.c index b7f1cbc..54c5cf4
> 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
> @@ -486,8 +486,7 @@ static int ipp_validate_mem_node(struct
> drm_device *drm_dev, unsigned int bpp;
>   int i;
>  
> - /* The property id should already be varified */
> - ipp_cfg = _node->property.config[m_node->prop_id];
> + ipp_cfg = _node->property.config[m_node->ops_id];
>   num_plane = drm_format_num_planes(ipp_cfg->fmt);
>  
>   /**



[PATCH 3/3] ARM: dts: fix the clock-frequency of rinato board's panel

2015-06-12 Thread Hyungwon Hwang
After the commit abc0b1447d4974963548777a5ba4a4457c82c426
("drm: Perform basic sanity checks on probed modes"), proper
clock-frequency becomes mandatory for validating the mode of panel.
The display does not work if there is no mode validated. Also, this
clock-frequency must be set appropriately for getting required frame
rate.

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

diff --git a/arch/arm/boot/dts/exynos3250-rinato.dts 
b/arch/arm/boot/dts/exynos3250-rinato.dts
index 0b99068..75aba40 100644
--- a/arch/arm/boot/dts/exynos3250-rinato.dts
+++ b/arch/arm/boot/dts/exynos3250-rinato.dts
@@ -181,7 +181,7 @@

display-timings {
timing-0 {
-   clock-frequency = <0>;
+   clock-frequency = <460>;
hactive = <320>;
vactive = <320>;
hfront-porch = <1>;
-- 
1.9.1



[PATCH 2/3] ARM: dts: Add the reference node for syscon to mipi phy for Exynos3250

2015-06-12 Thread Hyungwon Hwang
Exynos mipi phy driver needs syscon node to be probed successfully.

Signed-off-by: Hyungwon Hwang 
---
 arch/arm/boot/dts/exynos3250.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/exynos3250.dtsi 
b/arch/arm/boot/dts/exynos3250.dtsi
index e3bfb11..f8c02dd 100644
--- a/arch/arm/boot/dts/exynos3250.dtsi
+++ b/arch/arm/boot/dts/exynos3250.dtsi
@@ -140,6 +140,7 @@
compatible = "samsung,s5pv210-mipi-video-phy";
reg = <0x10020710 8>;
#phy-cells = <1>;
+   syscon = <_system_controller>;
};

pd_cam: cam-power-domain at 10023C00 {
-- 
1.9.1



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

2015-06-12 Thread Hyungwon Hwang
From: Inki Dae <inki@samsung.com>

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 
---
 drivers/gpu/drm/exynos/exynos_drm_dsi.c | 31 +++
 drivers/gpu/drm/panel/Kconfig   |  6 ++
 drivers/gpu/drm/panel/Makefile  |  1 +
 3 files changed, 26 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c 
b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 5576cc3..6cb4887 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -743,6 +743,14 @@ static void exynos_dsi_disable_clock(struct exynos_dsi 
*dsi)
DSI_WRITE(dsi, DSIM_PLLCTRL_REG, reg);
 }

+static void exynos_dsi_enable_lane(struct exynos_dsi *dsi, u32 lane)
+{
+   u32 reg = DSI_READ(dsi, DSIM_CONFIG_REG);
+   reg |= (DSIM_NUM_OF_DATA_LANE(dsi->lanes - 1) | DSIM_LANE_EN_CLK |
+   DSIM_LANE_EN(lane));
+   DSI_WRITE(dsi, DSIM_CONFIG_REG, reg);
+}
+
 static int exynos_dsi_init_link(struct exynos_dsi *dsi)
 {
struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
@@ -815,17 +823,6 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi)
return -EINVAL;
}

-   reg |= DSIM_NUM_OF_DATA_LANE(dsi->lanes - 1);
-
-   DSI_WRITE(dsi, DSIM_CONFIG_REG, reg);
-
-   reg |= DSIM_LANE_EN_CLK;
-   DSI_WRITE(dsi, DSIM_CONFIG_REG, reg);
-
-   lanes_mask = BIT(dsi->lanes) - 1;
-   reg |= DSIM_LANE_EN(lanes_mask);
-   DSI_WRITE(dsi, DSIM_CONFIG_REG, reg);
-
/*
 * Use non-continuous clock mode if the periparal wants and
 * host controller supports
@@ -837,8 +834,11 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi)
if (driver_data->has_clklane_stop &&
dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) {
reg |= DSIM_CLKLANE_STOP;
-   DSI_WRITE(dsi, DSIM_CONFIG_REG, reg);
}
+   DSI_WRITE(dsi, DSIM_CONFIG_REG, reg);
+
+   lanes_mask = BIT(dsi->lanes) - 1;
+   exynos_dsi_enable_lane(dsi, lanes_mask);

/* Check clock and data lane state are stop state */
timeout = 100;
@@ -1301,6 +1301,10 @@ static int exynos_dsi_init(struct exynos_dsi *dsi)

exynos_dsi_reset(dsi);
exynos_dsi_enable_irq(dsi);
+
+   if (driver_data->values[RESET_TYPE] == DSIM_FUNCRST)
+   exynos_dsi_enable_lane(dsi, BIT(dsi->lanes) - 1);
+
exynos_dsi_enable_clock(dsi);
if (driver_data->wait_for_reset)
exynos_dsi_wait_for_reset(dsi);
@@ -1893,6 +1897,9 @@ static int exynos_dsi_probe(struct platform_device *pdev)
dsi->clks = devm_kzalloc(dev,
sizeof(*dsi->clks) * dsi->driver_data->num_clks,
GFP_KERNEL);
+   if (!dsi->clks)
+   goto err_del_component;
+
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])) {
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 6d64c7b..cb07bc6 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -43,4 +43,10 @@ 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_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 4b2a043..27b0a90 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_S6E63J0X03) += panel-s6e63j0x03.o
-- 
1.9.1



[PATCH] ARM: dts: set display clock correctly for exynos4412-trats2

2015-06-12 Thread Hyungwon Hwang
From: Inki Dae 

This patch sets display clock correctly. If Display clock isn't set
correctly then you would find below messages and Display controller
doesn't work correctly.

 exynos-drm: No connectors reported connected with modes
 [drm] Cannot find any crtc or sizes - going 1024x768

Fixes: abc0b1447d49 ("drm: Perform basic sanity checks on probed modes")
Cc: 
Signed-off-by: Inki Dae 
Reviewed-by: Krzysztof Kozlowski 
Tested-by: Krzysztof Kozlowski 
Signed-off-by: Kukjin Kim 
---
 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 173ffa4..792394d 100644
--- a/arch/arm/boot/dts/exynos4412-trats2.dts
+++ b/arch/arm/boot/dts/exynos4412-trats2.dts
@@ -736,7 +736,7 @@

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



[PATCH 2/2] drm/exynos: ipp: validate a GEM handle with multiple planes

2015-06-12 Thread Hyungwon Hwang
FIMC & GSC driver can calculate the offset of planes. So there are
use cases which IPP receives just one GEM handle of an image with
multiple plane. This patch extends ipp_validate_mem_node() to validate
this case.

Signed-off-by: Hyungwon Hwang 
---
 drivers/gpu/drm/exynos/exynos_drm_ipp.c | 51 -
 1 file changed, 38 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c 
b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
index 54c5cf4..b3dc778 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
@@ -482,8 +482,8 @@ static int ipp_validate_mem_node(struct drm_device *drm_dev,
 {
struct drm_exynos_ipp_config *ipp_cfg;
unsigned int num_plane;
-   unsigned long min_size, size;
-   unsigned int bpp;
+   unsigned long size, buf_size = 0, plane_size, img_size = 0;
+   unsigned int bpp, width, height;
int i;

ipp_cfg = _node->property.config[m_node->ops_id];
@@ -497,20 +497,45 @@ static int ipp_validate_mem_node(struct drm_device 
*drm_dev,
 * but it seems more than enough
 */
for (i = 0; i < num_plane; ++i) {
-   if (!m_node->buf_info.handles[i]) {
-   DRM_ERROR("invalid handle for plane %d\n", i);
-   return -EINVAL;
-   }
+   width = ipp_cfg->sz.hsize;
+   height = ipp_cfg->sz.vsize;
bpp = drm_format_plane_cpp(ipp_cfg->fmt, i);
-   min_size = (ipp_cfg->sz.hsize * ipp_cfg->sz.vsize * bpp) >> 3;
-   size = exynos_drm_gem_get_size(drm_dev,
-  m_node->buf_info.handles[i],
-  c_node->filp);
-   if (min_size > size) {
-   DRM_ERROR("invalid size for plane %d\n", i);
-   return -EINVAL;
+
+   /*
+* The result of drm_format_plane_cpp() for chroma planes must
+* be used with drm_format__chroma_subsampling() for
+* correct result.
+*/
+   if (i > 0) {
+   width /= drm_format_horz_chroma_subsampling(
+   ipp_cfg->fmt);
+   height /= drm_format_vert_chroma_subsampling(
+   ipp_cfg->fmt);
}
+   plane_size = width * height * bpp;
+   img_size += plane_size;
+
+   if (m_node->buf_info.handles[i]) {
+   size = exynos_drm_gem_get_size(drm_dev,
+   m_node->buf_info.handles[i],
+   c_node->filp);
+   if (plane_size > size) {
+   DRM_ERROR(
+   "buffer %d is smaller than required\n",
+   i);
+   return -EINVAL;
+   }
+
+   buf_size += size;
+   }
+   }
+
+   if (buf_size < img_size) {
+   DRM_ERROR("size of buffers(%lu) is smaller than image(%lu)\n",
+   buf_size, img_size);
+   return -EINVAL;
}
+
return 0;
 }

-- 
1.9.1



[PATCH 1/2] drm/exynos: ipp: fix wrong index referencing a config element

2015-06-12 Thread Hyungwon Hwang
Config depends on the opreation. So it must be referenced by an
operation id, not a property id.

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

diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c 
b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
index b7f1cbc..54c5cf4 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
@@ -486,8 +486,7 @@ static int ipp_validate_mem_node(struct drm_device *drm_dev,
unsigned int bpp;
int i;

-   /* The property id should already be varified */
-   ipp_cfg = _node->property.config[m_node->prop_id];
+   ipp_cfg = _node->property.config[m_node->ops_id];
num_plane = drm_format_num_planes(ipp_cfg->fmt);

/**
-- 
1.9.1



[PATCH v6 15/15] ARM: dts: rename the clock of MIPI DSI 'pll_clk' to 'sclk_mipi'

2015-06-12 Thread Hyungwon Hwang
The clock which was named as 'pll_clk' is actually not the clock source
of PLL in MIPI DSI. This patch fixes this disagreement.

Signed-off-by: Hyungwon Hwang 
---
Changes before:
- Refer https://patchwork.kernel.org/patch/6191811
Changes for v6:
- None

 arch/arm/boot/dts/exynos4.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi
index e20cdc2..1538d7a 100644
--- a/arch/arm/boot/dts/exynos4.dtsi
+++ b/arch/arm/boot/dts/exynos4.dtsi
@@ -167,7 +167,7 @@
phys = <_phy 1>;
phy-names = "dsim";
clocks = < CLK_DSIM0>, < CLK_SCLK_MIPI0>;
-   clock-names = "bus_clk", "pll_clk";
+   clock-names = "bus_clk", "sclk_mipi";
status = "disabled";
#address-cells = <1>;
#size-cells = <0>;
--
1.9.1



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

2015-06-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 
---
Changes before:
- Refer https://patchwork.kernel.org/patch/6191811
Changes for v6:
- 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 0719114..0e58b36 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -1327,15 +1327,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 v6 13/15] drm/exynos: dsi: add support for MIC driver as a bridge

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

Signed-off-by: Hyungwon Hwang 
---
Changes before:
- Refer https://patchwork.kernel.org/patch/6191811
Changes for v6:
- 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 11ccac9..0be0362 100644
--- a/Documentation/devicetree/bindings/video/exynos_dsim.txt
+++ b/Documentation/devicetree/bindings/video/exynos_dsim.txt
@@ -32,10 +32,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
@@ -74,7 +83,15 @@ Example:
#address-cells = <1>;
#size-cells = <0>;

+   port at 0 {
+   reg = <0>;
+   decon_to_mic: endpoint {
+   remote-endpoint = <_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 d9bcdb9..0719114 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -21,6 +21,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -288,6 +289,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)
@@ -1794,7 +1796,22 @@ static int exynos_dsi_parse_dt(struct exynos_dsi *dsi)

ret = exynos_dsi_of_read_u32(ep, "samsung,esc-clock-frequency",
 >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);

@@ -1807,6 +1824,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);
@@ -1816,6 +1834,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_host);
 }

--
1.9.1



[PATCH v6 12/15] drm/exynos: dsi: add support for Exynos5433

2015-06-12 Thread Hyungwon Hwang
This patch adds support for Exynos5433 mipi dsi.

Signed-off-by: Hyungwon Hwang 
---
Changes before:
- Refer https://patchwork.kernel.org/patch/6191811
Changes for v6:
- Change the order of DSIM_CONFIG_REG register
- Add error checking code in probe function

 .../devicetree/bindings/video/exynos_dsim.txt  |   1 +
 drivers/gpu/drm/exynos/Kconfig |   2 +-
 drivers/gpu/drm/exynos/exynos_drm_dsi.c| 100 +
 3 files changed, 87 insertions(+), 16 deletions(-)

diff --git a/Documentation/devicetree/bindings/video/exynos_dsim.txt 
b/Documentation/devicetree/bindings/video/exynos_dsim.txt
index 44659dd..11ccac9 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 12e4e62..43003c4 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 && (DRM_EXYNOS_FIMD || DRM_EXYNOS7_DECON)
+   depends on DRM_EXYNOS && (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 557b9d2..d9bcdb9 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -132,6 +132,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)
@@ -180,6 +181,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)
@@ -211,7 +214,9 @@
REG_ADDR((dsi), (reg_idx)))
 #define DSI_READ(dsi, reg_idx) readl(REG_ADDR((dsi), (reg_idx)))

-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,
@@ -341,6 +346,30 @@ static unsigned int exynos_reg_ofs[] = {
[DSIM_PHYTIMING2_REG] =  0x6c,
 };

+static unsigned int exynos5433_reg_ofs[] = {
+   [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 reg_value_idx {
RESET_TYPE,
PLL_TIMER,
@@ -377,6 +406,24 @@ static unsigned int reg_values[] = {
[PHYTIMING_HS_TRAIL] = DSIM_PHYTIMING2_HS_TRAIL(0x0b),
 };

+static unsigned int exynos5433_reg_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),
+   [PHYTIMING_CLK_PREPARE] = DSIM_PHYTIMING1_CLK_PREPARE(0x09),
+   [PHYTI

[PATCH v6 11/15] drm/exynos: dsi: make use of array for clock access

2015-06-12 Thread Hyungwon Hwang
This patch make the driver to use an array for clock access. The number
of clocks are different from the existing MIPI DSI driver and Exynos5433
MIPI DSI driver. So this patch is needed before adding support for
Exynos5433 MIPI DSI driver.

Signed-off-by: Hyungwon Hwang 
---
Changes before:
- Refer https://patchwork.kernel.org/patch/6191801
Changes for v6:
- None

 drivers/gpu/drm/exynos/exynos_drm_dsi.c | 68 -
 1 file changed, 33 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c 
b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 0b468d7..557b9d2 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -211,6 +211,8 @@
REG_ADDR((dsi), (reg_idx)))
 #define DSI_READ(dsi, reg_idx) readl(REG_ADDR((dsi), (reg_idx)))

+static char *clk_names[2] = { "bus_clk", "sclk_mipi" };
+
 enum exynos_dsi_transfer_type {
EXYNOS_DSI_TX,
EXYNOS_DSI_RX,
@@ -260,8 +262,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;
@@ -1390,7 +1391,8 @@ static const struct mipi_dsi_host_ops exynos_dsi_ops = {

 static int exynos_dsi_poweron(struct exynos_dsi *dsi)
 {
-   int ret;
+   struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
+   int ret, i;

ret = regulator_bulk_enable(ARRAY_SIZE(dsi->supplies), dsi->supplies);
if (ret < 0) {
@@ -1398,31 +1400,23 @@ static int exynos_dsi_poweron(struct exynos_dsi *dsi)
return ret;
}

-   ret = clk_prepare_enable(dsi->bus_clk);
-   if (ret < 0) {
-   dev_err(dsi->dev, "cannot enable bus clock %d\n", ret);
-   goto err_bus_clk;
-   }
-
-   ret = clk_prepare_enable(dsi->sclk_clk);
-   if (ret < 0) {
-   dev_err(dsi->dev, "cannot enable pll clock %d\n", ret);
-   goto err_sclk_clk;
+   for (i = 0; i < driver_data->num_clks; i++) {
+   ret = clk_prepare_enable(dsi->clks[i]);
+   if (ret < 0)
+   goto err_clk;
}

ret = phy_power_on(dsi->phy);
if (ret < 0) {
dev_err(dsi->dev, "cannot enable phy %d\n", ret);
-   goto err_phy;
+   goto err_clk;
}

return 0;

-err_phy:
-   clk_disable_unprepare(dsi->sclk_clk);
-err_sclk_clk:
-   clk_disable_unprepare(dsi->bus_clk);
-err_bus_clk:
+err_clk:
+   while (--i > -1)
+   clk_disable_unprepare(dsi->clks[i]);
regulator_bulk_disable(ARRAY_SIZE(dsi->supplies), dsi->supplies);

return ret;
@@ -1430,7 +1424,8 @@ err_bus_clk:

 static void exynos_dsi_poweroff(struct exynos_dsi *dsi)
 {
-   int ret;
+   struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
+   int ret, i;

usleep_range(1, 2);

@@ -1446,8 +1441,8 @@ static void exynos_dsi_poweroff(struct exynos_dsi *dsi)

phy_power_off(dsi->phy);

-   clk_disable_unprepare(dsi->sclk_clk);
-   clk_disable_unprepare(dsi->bus_clk);
+   for (i = driver_data->num_clks - 1; i > -1; i--)
+   clk_disable_unprepare(dsi->clks[i]);

ret = regulator_bulk_disable(ARRAY_SIZE(dsi->supplies), dsi->supplies);
if (ret < 0)
@@ -1778,7 +1773,7 @@ static int exynos_dsi_probe(struct platform_device *pdev)
struct device *dev = >dev;
struct resource *res;
struct exynos_dsi *dsi;
-   int ret;
+   int ret, i;

dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);
if (!dsi)
@@ -1813,19 +1808,22 @@ static int exynos_dsi_probe(struct platform_device 
*pdev)
return -EPROBE_DEFER;
}

-   dsi->sclk_clk = devm_clk_get(dev, "sclk_mipi");
-   if (IS_ERR(dsi->sclk_clk)) {
-   dsi->sclk_clk = devm_clk_get(dev, OLD_SCLK_MIPI_CLK_NAME);
-   if (IS_ERR(dsi->sclk_clk)) {
-   dev_info(dev, "failed to get dsi sclk clock\n");
-   eturn PTR_ERR(dsi->sclk_clk);
-   }
-   }
+   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])) {
+   if (strcmp(clk_names[i], "sclk_mipi") == 0) {
+   strcpy(clk_names[i], OLD_SCLK_MIPI_CLK_NAME);
+  

[PATCH v6 10/15] drm/exynos: dsi: make use of driver data for static values

2015-06-12 Thread Hyungwon Hwang
Exynos MIPI DSI driver uses some static values such as address offsets,
register setting values, and etc. This patch makes the driver get those
values from the driver data.

Signed-off-by: Hyungwon Hwang 
---
Changes before:
- Refer https://patchwork.kernel.org/patch/6191731
Changes for v6:
- None

 drivers/gpu/drm/exynos/exynos_drm_dsi.c | 196 +++-
 1 file changed, 145 insertions(+), 51 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c 
b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 70367d0..0b468d7 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -34,38 +34,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)
@@ -129,8 +97,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)
@@ -237,8 +205,11 @@

 #define OLD_SCLK_MIPI_CLK_NAME "pll_clk"

-#define DSI_WRITE(dsi, reg, val)   writel((val), (dsi)->reg_base + (reg))
-#define DSI_READ(dsi, reg) readl((dsi)->reg_base + (reg))
+#define REG_ADDR(dsi, reg_idx) ((dsi)->reg_base + \
+   dsi->driver_data->reg_ofs[(reg_idx)])
+#define DSI_WRITE(dsi, reg_idx, val)   writel((val), \
+   REG_ADDR((dsi), (reg_idx)))
+#define DSI_READ(dsi, reg_idx) readl(REG_ADDR((dsi), (reg_idx)))

 enum exynos_dsi_transfer_type {
EXYNOS_DSI_TX,
@@ -268,10 +239,15 @@ struct exynos_dsi_transfer {
 #define DSIM_STATE_VIDOUT_AVAILABLEBIT(3)

 struct exynos_dsi_driver_data {
+   unsigned int *reg_ofs;
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 *reg_values;
 };

 struct exynos_dsi {
@@ -316,25 +292,133 @@ static inline struct exynos_dsi *display_to_dsi(struct 
exynos_drm_display *d)
return container_of(d, struct exynos_dsi, display);
 }

+enum reg_idx {
+   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,
+   DSIM_MVPORCH_REG,   /* Main display Vporch register */
+   DSIM_MHPORCH_REG,   /* Main display Hporch 

[PATCH v6 09/15] drm/exynos: dsi: add macros for register access

2015-06-12 Thread Hyungwon Hwang
This patch adds macros for register writing/reading. This is needed for
adding support Exynos5433 MIPI DSI driver, not by using if statement, but
by using driver data.

Signed-off-by: Hyungwon Hwang 
---
Changes before:
- Refer https://patchwork.kernel.org/patch/6191761
Changes for v6:
- None

 drivers/gpu/drm/exynos/exynos_drm_dsi.c | 98 +
 1 file changed, 51 insertions(+), 47 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c 
b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index a3bfac2..70367d0 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -237,6 +237,9 @@

 #define OLD_SCLK_MIPI_CLK_NAME "pll_clk"

+#define DSI_WRITE(dsi, reg, val)   writel((val), (dsi)->reg_base + (reg))
+#define DSI_READ(dsi, reg) readl((dsi)->reg_base + (reg))
+
 enum exynos_dsi_transfer_type {
EXYNOS_DSI_TX,
EXYNOS_DSI_RX,
@@ -365,8 +368,10 @@ static void exynos_dsi_wait_for_reset(struct exynos_dsi 
*dsi)

 static void exynos_dsi_reset(struct exynos_dsi *dsi)
 {
+   struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
+
reinit_completion(>completed);
-   writel(DSIM_SWRST, dsi->reg_base + DSIM_SWRST_REG);
+   DSI_WRITE(dsi, DSIM_SWRST_REG, DSIM_SWRST);
 }

 #ifndef MHZ
@@ -376,6 +381,7 @@ static void exynos_dsi_reset(struct exynos_dsi *dsi)
 static unsigned long exynos_dsi_pll_find_pms(struct exynos_dsi *dsi,
unsigned long fin, unsigned long fout, u8 *p, u16 *m, u8 *s)
 {
+   struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
unsigned long best_freq = 0;
u32 min_delta = 0x;
u8 p_min, p_max;
@@ -466,7 +472,7 @@ static unsigned long exynos_dsi_set_pll(struct exynos_dsi 
*dsi,
reg |= DSIM_FREQ_BAND(band);
}

-   writel(reg, dsi->reg_base + DSIM_PLLCTRL_REG);
+   DSI_WRITE(dsi, DSIM_PLLCTRL_REG, reg);

timeout = 1000;
do {
@@ -474,7 +480,7 @@ static unsigned long exynos_dsi_set_pll(struct exynos_dsi 
*dsi,
dev_err(dsi->dev, "PLL failed to stabilize\n");
return 0;
}
-   reg = readl(dsi->reg_base + DSIM_STATUS_REG);
+   reg = DSI_READ(dsi, DSIM_STATUS_REG);
} while ((reg & DSIM_PLL_STABLE) == 0);

return fout;
@@ -504,7 +510,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 = DSI_READ(dsi, DSIM_CLKCTRL_REG);
reg &= ~(DSIM_ESC_PRESCALER_MASK | DSIM_LANE_ESC_CLK_EN_CLK
| DSIM_LANE_ESC_CLK_EN_DATA_MASK | DSIM_PLL_BYPASS
| DSIM_BYTE_CLK_SRC_MASK);
@@ -514,7 +520,7 @@ static int exynos_dsi_enable_clock(struct exynos_dsi *dsi)
| DSIM_LANE_ESC_CLK_EN_DATA(BIT(dsi->lanes) - 1)
| DSIM_BYTE_CLK_SRC(0)
| DSIM_TX_REQUEST_HSCLK;
-   writel(reg, dsi->reg_base + DSIM_CLKCTRL_REG);
+   DSI_WRITE(dsi, DSIM_CLKCTRL_REG, reg);

return 0;
 }
@@ -529,7 +535,7 @@ static void exynos_dsi_set_phy_ctrl(struct exynos_dsi *dsi)

/* B D-PHY: D-PHY Master & Slave Analog Block control */
reg = DSIM_PHYCTRL_ULPS_EXIT(0x0af);
-   writel(reg, dsi->reg_base + DSIM_PHYCTRL_REG);
+   DSI_WRITE(dsi, DSIM_PHYCTRL_REG, reg);

/*
 * T LPX: Transmitted length of any Low-Power state period
@@ -537,7 +543,7 @@ static void exynos_dsi_set_phy_ctrl(struct exynos_dsi *dsi)
 *  burst
 */
reg = DSIM_PHYTIMING_LPX(0x06) | DSIM_PHYTIMING_HS_EXIT(0x0b);
-   writel(reg, dsi->reg_base + DSIM_PHYTIMING_REG);
+   DSI_WRITE(dsi, DSIM_PHYTIMING_REG, reg);

/*
 * T CLK-PREPARE: Time that the transmitter drives the Clock Lane LP-00
@@ -556,7 +562,7 @@ static void exynos_dsi_set_phy_ctrl(struct exynos_dsi *dsi)
DSIM_PHYTIMING1_CLK_ZERO(0x27) |
DSIM_PHYTIMING1_CLK_POST(0x0d) |
DSIM_PHYTIMING1_CLK_TRAIL(0x08);
-   writel(reg, dsi->reg_base + DSIM_PHYTIMING1_REG);
+   DSI_WRITE(dsi, DSIM_PHYTIMING1_REG, reg);

/*
 * T HS-PREPARE: Time that the transmitter drives the Data Lane LP-00
@@ -569,21 +575,21 @@ static void exynos_dsi_set_phy_ctrl(struct exynos_dsi 
*dsi)
 */
reg = DSIM_PHYTIMING2_HS_PREPARE(0x09) | DSIM_PHYTIMING2_HS_ZERO(0x0d) |
DSIM_PHYTIMING2_HS_TRAIL(0x0b);
-   writel(reg, dsi->reg_base + DSIM_PHYTIMING2_REG);
+   DSI_WRITE(dsi, DSIM_PHYTIMING2_REG, reg);
 }

 static void exynos_dsi_disable_clock(struct exynos_dsi *dsi)
 {
u32 reg;

- 

[PATCH v6 08/15] drm/exynos: dsi: rename pll_clk to sclk_clk

2015-06-12 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. But for the backward
compatibility, the old clock name "pll_clk" is also OK.

Signed-off-by: Hyungwon Hwang 
---
Changes before:
- Refer https://patchwork.kernel.org/patch/6191721
Changes for v6:
- Merged 2 patches
   drm/exynos: dsi: add the backward compatibility for the renamed clock
   drm/exynos: dsi: rename pll_clk to sclk_clk

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

diff --git a/Documentation/devicetree/bindings/video/exynos_dsim.txt 
b/Documentation/devicetree/bindings/video/exynos_dsim.txt
index 802aa7e..44659dd 100644
--- a/Documentation/devicetree/bindings/video/exynos_dsim.txt
+++ b/Documentation/devicetree/bindings/video/exynos_dsim.txt
@@ -10,13 +10,14 @@ 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
+the use of "pll_clk" is deprecated
   - 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 +49,7 @@ Example:
reg = <0x11C8 0x1>;
interrupts = <0 79 0>;
clocks = < 286>, < 143>;
-   clock-names = "bus_clk", "pll_clk";
+   clock-names = "bus_clk", "sclk_mipi";
phys = <_phy 1>;
phy-names = "dsim";
vddcore-supply = <_reg>;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c 
b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index c1999ad..a3bfac2 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -235,6 +235,8 @@
 #define DSI_XFER_TIMEOUT_MS100
 #define DSI_RX_FIFO_EMPTY  0x3082

+#define OLD_SCLK_MIPI_CLK_NAME "pll_clk"
+
 enum exynos_dsi_transfer_type {
EXYNOS_DSI_TX,
EXYNOS_DSI_RX,
@@ -279,7 +281,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;
@@ -433,16 +435,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, , , );
if (!fout) {
dev_err(dsi->dev,
@@ -1313,10 +1306,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);
@@ -1328,8 +1321,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);
@@ -1355,7 +1348,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);

[PATCH v6 07/15] drm/exynos: mic: add MIC driver

2015-06-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 
---
Changes before:
- Refer https://patchwork.kernel.org/patch/6191711/
Changes for v6:
- None
 .../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 = <_disp CLK_PCLK_MIC0>,
+  <_disp CLK_SCLK_RGB_VCLK_TO_MIC0>;
+   clock-names = "pclk_mic0", "sclk_rgb_vclk_to_mic0";
+   samsung,disp-syscon = <_disp>;
+
+   ports {
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   port at 0 {
+   reg = <0>;
+   mic_to_decon: endpoint {
+   remote-endpoint = <_to_mic>;
+   };
+   };
+
+   port at 1 {
+   reg = <1>;
+   mic_to_dsi: endpoint {
+   remote-endpoint = <_to_mic>;
+   };
+   };
+   };
+};
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index 51a4eb5..12e4e62 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/drm/exynos/exynos_drm_drv.c 
b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index 591bdec..c14b44a 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -357,6 +357,9 @@ static struct platform_driver *const 
exynos_drm_kms_drivers[] = {
 #ifdef CONFIG_DRM_EXYNOS7_DECON
_driver,
 #endif
+#ifdef CONFIG_DRM_EXYNOS_MIC
+   _driver,
+#endif
 

[PATCH v6 06/15] of: add helper for getting endpoint node of specific identifiers

2015-06-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 <robh+dt at kernel.org>
---
Changes before:
- Refer https://patchwork.kernel.org/patch/6191751/
Changes for v6:
- 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 99764db..f3b583b 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2233,6 +2233,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, );
+   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 7bc92e0..1c1d5b9 100644
--- a/include/linux/of_graph.h
+++ b/include/linux/of_graph.h
@@ -45,6 +45,8 @@ int of_graph_parse_endpoint(const struct device_node *node,
 struct device_node *of_graph_get_port_by_id(struct device_node *node, u32 id);
 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);
@@ -69,6 +71,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 v6 05/15] drm/exynos: add Exynos5433 decon driver

2015-06-12 Thread Hyungwon Hwang
From: Joonyoung Shim <jy0922.s...@samsung.com>

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 before:
- Refer https://patchwork.kernel.org/patch/6192071/
Changes for v6:
- Add support for atomic modeset
 .../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  | 694 +
 drivers/gpu/drm/exynos/exynos_drm_drv.h|   1 +
 include/video/exynos5433_decon.h   | 165 +
 6 files changed, 932 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 = <_disp CLK_ACLK_DECON>, <_disp CLK_ACLK_SMMU_DECON0X>,
+   <_disp CLK_ACLK_XIU_DECON0X>,
+   <_disp CLK_PCLK_SMMU_DECON0X>,
+   <_disp CLK_SCLK_DECON_VCLK>,
+   <_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 = <_to_decon>;
+   };
+   };
+   };
+};
+
+Board specific DT entry:
+ {
+   i80-if-timings {
+   };
+};
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index ddb7c8a..51a4eb5 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 you want to use Exynos5433 DECON for DRM.
+
 config DRM_EXYNOS7_DECON
bool "Exynos7 DRM DECON"
depends o

[PATCH v6 04/15] drm/exynos: fix the input prompt of Exynos7 DECON

2015-06-12 Thread Hyungwon Hwang
This patch is a preparation patch for adding support for Exynos5433
DECON. Exynos7 DECON have to be distinguished from Exynos5433 DECON.

Signed-off-by: Hyungwon Hwang 
---
Changes for v6:
- New
 drivers/gpu/drm/exynos/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index f1b1239..ddb7c8a 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -25,7 +25,7 @@ config DRM_EXYNOS_FIMD
  Choose this option if you want to use Exynos FIMD for DRM.

 config DRM_EXYNOS7_DECON
-   bool "Exynos DRM DECON"
+   bool "Exynos7 DRM DECON"
depends on DRM_EXYNOS && !FB_S3C
select FB_MODE_HELPERS
help
--
1.9.1



[PATCH v6 03/15] drm/exynos: add drm_iommu_attach_device_if_possible()

2015-06-12 Thread Hyungwon Hwang
Every CRTC drivers in Exynos DRM implements the code which checks
whether IOMMU is supported or not, and if supported enable it.
Making new helper for it generalize each CRTC drivers.

Signed-off-by: Hyungwon Hwang 
---
Changes for v6:
- New
 drivers/gpu/drm/exynos/exynos7_drm_decon.c | 25 +++---
 drivers/gpu/drm/exynos/exynos_drm_drv.h|  1 +
 drivers/gpu/drm/exynos/exynos_drm_fimd.c   | 34 +++---
 drivers/gpu/drm/exynos/exynos_drm_iommu.c  | 14 
 drivers/gpu/drm/exynos/exynos_drm_iommu.h  | 11 ++
 drivers/gpu/drm/exynos/exynos_mixer.c  |  8 ---
 6 files changed, 47 insertions(+), 46 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c 
b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
index 7d0955d..b0261dd 100644
--- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
@@ -89,8 +89,9 @@ static void decon_wait_for_vblank(struct exynos_drm_crtc 
*crtc)
DRM_DEBUG_KMS("vblank wait timed out.\n");
 }

-static void decon_clear_channel(struct decon_context *ctx)
+static void decon_clear_channels(struct exynos_drm_crtc *crtc)
 {
+   struct decon_context *ctx = crtc->ctx;
unsigned int win, ch_enabled = 0;

DRM_DEBUG_KMS("%s\n", __FILE__);
@@ -120,27 +121,16 @@ static int decon_ctx_initialize(struct decon_context *ctx,
struct drm_device *drm_dev)
 {
struct exynos_drm_private *priv = drm_dev->dev_private;
+   int ret;

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)) {
-   int ret;
-
-   /*
-* If any channel is already active, iommu will throw
-* a PAGE FAULT when enabled. So clear any channel if enabled.
-*/
-   decon_clear_channel(ctx);
-   ret = drm_iommu_attach_device(ctx->drm_dev, ctx->dev);
-   if (ret) {
-   DRM_ERROR("drm_iommu_attach failed.\n");
-   return ret;
-   }
-   }
+   ret = drm_iommu_attach_device_if_possible(ctx->crtc, drm_dev, ctx->dev);
+   if (ret)
+   priv->pipe--;

-   return 0;
+   return ret;
 }

 static void decon_ctx_remove(struct decon_context *ctx)
@@ -684,6 +674,7 @@ static const struct exynos_drm_crtc_ops decon_crtc_ops = {
.wait_for_vblank = decon_wait_for_vblank,
.win_commit = decon_win_commit,
.win_disable = decon_win_disable,
+   .clear_channels = decon_clear_channels,
 };


diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h 
b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index 6b4958b..1ba34f1 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -182,6 +182,7 @@ struct exynos_drm_crtc_ops {
void (*win_disable)(struct exynos_drm_crtc *crtc, unsigned int zpos);
void (*te_handler)(struct exynos_drm_crtc *crtc);
void (*clock_enable)(struct exynos_drm_crtc *crtc, bool enable);
+   void (*clear_channels)(struct exynos_drm_crtc *crtc);
 };

 /*
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c 
b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 9cce2bc..ddf4c84 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -242,8 +242,9 @@ static void fimd_enable_shadow_channel_path(struct 
fimd_context *ctx,
writel(val, ctx->regs + SHADOWCON);
 }

-static void fimd_clear_channel(struct fimd_context *ctx)
+static void fimd_clear_channels(struct exynos_drm_crtc *crtc)
 {
+   struct fimd_context *ctx = crtc->ctx;
unsigned int win, ch_enabled = 0;

DRM_DEBUG_KMS("%s\n", __FILE__);
@@ -273,30 +274,6 @@ static void fimd_clear_channel(struct fimd_context *ctx)
}
 }

-static int fimd_iommu_attach_devices(struct fimd_context *ctx,
-   struct drm_device *drm_dev)
-{
-
-   /* attach this sub driver to iommu mapping if supported. */
-   if (is_drm_iommu_supported(ctx->drm_dev)) {
-   int ret;
-
-   /*
-* If any channel is already active, iommu will throw
-* a PAGE FAULT when enabled. So clear any channel if enabled.
-*/
-   fimd_clear_channel(ctx);
-   ret = drm_iommu_attach_device(ctx->drm_dev, ctx->dev);
-   if (ret) {
-   DRM_ERROR("drm_iommu_attach failed.\n");
-   return ret;
-   }
-
-   }
-
-   return 0;
-}
-
 static void fimd_iommu_detach_devices(struct fimd_context *ctx)
 {
/* detach this sub driver from iommu mapping if supported. */
@@ -943,6 +920,7 @@ static const struct exynos_drm_crtc_op

[PATCH v6 02/15] drm/exynos: Add the dependency for DRM_EXYNOS to DPI/DSI/DP

2015-06-12 Thread Hyungwon Hwang
Without this dependency, Kbuild is confused and the configs below
them are not placed under Exynos DRM. This patch fixes it, so the
configs below them become to be placed under Exynos DRM.

Signed-off-by: Hyungwon Hwang 
---
Changes for v6:
- New
 drivers/gpu/drm/exynos/Kconfig | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index 926ed36..f1b1239 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -33,7 +33,7 @@ config DRM_EXYNOS7_DECON

 config DRM_EXYNOS_DPI
bool "EXYNOS DRM parallel output support"
-   depends on (DRM_EXYNOS_FIMD || DRM_EXYNOS7_DECON)
+   depends on DRM_EXYNOS && (DRM_EXYNOS_FIMD || DRM_EXYNOS7_DECON)
select DRM_PANEL
default n
help
@@ -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 && (DRM_EXYNOS_FIMD || DRM_EXYNOS7_DECON)
select DRM_MIPI_DSI
select DRM_PANEL
default n
@@ -50,7 +50,7 @@ config DRM_EXYNOS_DSI

 config DRM_EXYNOS_DP
bool "EXYNOS DRM DP driver support"
-   depends on (DRM_EXYNOS_FIMD || DRM_EXYNOS7_DECON) && (DRM_PTN3460=n || 
DRM_PTN3460=y || DRM_PTN3460=DRM_EXYNOS)
+   depends on DRM_EXYNOS && (DRM_EXYNOS_FIMD || DRM_EXYNOS7_DECON) && 
(DRM_PTN3460=n || DRM_PTN3460=y || DRM_PTN3460=DRM_EXYNOS)
default DRM_EXYNOS
select DRM_PANEL
help
--
1.9.1



[PATCH v6 01/15] drm/exynos: remove the dependency of DP driver for ARCH_EXYNOS

2015-06-12 Thread Hyungwon Hwang
This dependency is a historical thing. It is added when this DP driver is
under media subsystem. Now because it is under Exynos DRM, this dependency
is not needed anymore.

Signed-off-by: Hyungwon Hwang 
---
Changes for v6:
- New
 drivers/gpu/drm/exynos/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index 8203283..926ed36 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -50,7 +50,7 @@ config DRM_EXYNOS_DSI

 config DRM_EXYNOS_DP
bool "EXYNOS DRM DP driver support"
-   depends on (DRM_EXYNOS_FIMD || DRM_EXYNOS7_DECON) && ARCH_EXYNOS && 
(DRM_PTN3460=n || DRM_PTN3460=y || DRM_PTN3460=DRM_EXYNOS)
+   depends on (DRM_EXYNOS_FIMD || DRM_EXYNOS7_DECON) && (DRM_PTN3460=n || 
DRM_PTN3460=y || DRM_PTN3460=DRM_EXYNOS)
default DRM_EXYNOS
select DRM_PANEL
help
--
1.9.1



[PATCH v6 00/15] Add drivers for Exynos5433 display

2015-06-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/...

This patchset adds 2 new device drivers, Exynos54333 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

Changes for v4:
- rebased to exynos-drm-next with the clean-up patchset by Gustavo Padovan.

Changes for v5:
- separated the refactoring patch of MIPI DSI driver into 3 patches
- added the patch to make DSI driver compatiable with the old clock name
- added the patch to rename the DSI driver's clock
- rename the newly added dsi variables for clarity

Changes for v6:
- Clean up the build dependencies of Exynos DRM devices as preparation
- Introduce new common function drm_iommu_attach_device_if_possible()
- Add support for atomic modeset in Exynos5433 decon driver

Hyungwon Hwang (14):
  drm/exynos: remove the dependency of DP driver for ARCH_EXYNOS
  drm/exynos: Add the dependency for DRM_EXYNOS to DPI/DSI/DP
  drm/exynos: add drm_iommu_attach_device_if_possible()
  drm/exynos: fix the input prompt of Exynos7 DECON
  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: add macros for register access
  drm/exynos: dsi: make use of driver data for static values
  drm/exynos: dsi: make use of array for clock access
  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
  ARM: dts: rename the clock of MIPI DSI 'pll_clk' to 'sclk_mipi'

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  |  31 +-
 arch/arm/boot/dts/exynos4.dtsi |   2 +-
 drivers/gpu/drm/exynos/Kconfig |  20 +-
 drivers/gpu/drm/exynos/Makefile|   2 +
 drivers/gpu/drm/exynos/exynos5433_drm_decon.c  | 694 +
 drivers/gpu/drm/exynos/exynos7_drm_decon.c |  25 +-
 drivers/gpu/drm/exynos/exynos_drm_drv.c|   3 +
 drivers/gpu/drm/exynos/exynos_drm_drv.h|   3 +
 drivers/gpu/drm/exynos/exynos_drm_dsi.c| 484 +-
 drivers/gpu/drm/exynos/exynos_drm_fimd.c   |  34 +-
 drivers/gpu/drm/exynos/exynos_drm_iommu.c  |  14 +
 drivers/gpu/drm/exynos/exynos_drm_iommu.h  |  11 +
 drivers/gpu/drm/exynos/exynos_drm_mic.c| 490 +++
 drivers/gpu/drm/exynos/exynos_mixer.c  |   8 +-
 drivers/of/base.c  |  33 +
 include/linux/of_graph.h   |   8 +
 include/video/exynos5433_decon.h   | 165 +
 19 files changed, 1937 insertions(+), 206 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 v2] ARM: dts: fix the clock-frequency of rinato board's panel

2015-06-12 Thread Hyungwon Hwang
After the commit abc0b1447d4974963548777a5ba4a4457c82c426
("drm: Perform basic sanity checks on probed modes"), proper
clock-frequency becomes mandatory for validating the mode of panel.
The display does not work if there is no mode validated. Also, this
clock-frequency must be set appropriately for getting required frame
rate.

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

diff --git a/arch/arm/boot/dts/exynos3250-rinato.dts 
b/arch/arm/boot/dts/exynos3250-rinato.dts
index 0b99068..75aba40 100644
--- a/arch/arm/boot/dts/exynos3250-rinato.dts
+++ b/arch/arm/boot/dts/exynos3250-rinato.dts
@@ -181,7 +181,7 @@

display-timings {
timing-0 {
-   clock-frequency = <0>;
+   clock-frequency = <460>;
hactive = <320>;
vactive = <320>;
hfront-porch = <1>;
--
1.9.1



[PATCH 2/3] ARM: dts: fix the clock-frequency of rinato board's panel

2015-06-12 Thread Hyungwon Hwang
On Fri, 12 Jun 2015 18:23:18 +0900
Krzysztof Kozlowski  wrote:

> 2015-06-12 18:03 GMT+09:00 Hyungwon Hwang :
> > Because of recent update, proper clock-frequency becomes mandatory
> > for validating the mode of panel. This clock-frequency must be set
> > appropriately for getting required frame rate.
> >
> > Signed-off-by: Hyungwon Hwang 
> 
> Acked-by: Krzysztof Kozlowski 
> 
> Is it a bugfix? The property is mandatory right now?

With recent kernel, yes. It is mandatory for the mode to be become
available.

Best regards,
Hyungwon Hwang

> 
> Best regards,
> Krzysztof



[PATCH 2/3] ARM: dts: fix the clock-frequency of rinato board's panel

2015-06-12 Thread Hyungwon Hwang
Because of recent update, proper clock-frequency becomes mandatory
for validating the mode of panel. This clock-frequency must be set
appropriately for getting required frame rate.

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

diff --git a/arch/arm/boot/dts/exynos3250-rinato.dts 
b/arch/arm/boot/dts/exynos3250-rinato.dts
index 0b99068..75aba40 100644
--- a/arch/arm/boot/dts/exynos3250-rinato.dts
+++ b/arch/arm/boot/dts/exynos3250-rinato.dts
@@ -181,7 +181,7 @@

display-timings {
timing-0 {
-   clock-frequency = <0>;
+   clock-frequency = <460>;
hactive = <320>;
vactive = <320>;
hfront-porch = <1>;
-- 
1.9.1



[PATCH 1/3] ARM: dts: Add the reference node for syscon to mipi phy for Exynos3250

2015-06-12 Thread Hyungwon Hwang
Exynos mipi phy driver needs syscon node to be probed successfully.

Signed-off-by: Hyungwon Hwang 
---
 arch/arm/boot/dts/exynos3250.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/exynos3250.dtsi 
b/arch/arm/boot/dts/exynos3250.dtsi
index e3bfb11..f8c02dd 100644
--- a/arch/arm/boot/dts/exynos3250.dtsi
+++ b/arch/arm/boot/dts/exynos3250.dtsi
@@ -140,6 +140,7 @@
compatible = "samsung,s5pv210-mipi-video-phy";
reg = <0x10020710 8>;
#phy-cells = <1>;
+   syscon = <_system_controller>;
};

pd_cam: cam-power-domain at 10023C00 {
-- 
1.9.1



[PATCH 3/3] drm/exynos: remove SoC checking code

2015-06-10 Thread Hyungwon Hwang
Hi Andrzej,

On Tue, 09 Jun 2015 16:46:52 -0300
Gustavo Padovan  wrote:

> Hi Andrzej,
> 
> 2015-06-08 Andrzej Hajda :
> 
> > SoC checking code is not necessary anymore, as exynos_drm_match_add
> > and exynos_drm_platform_probe already properly handles situation
> > when there are no Exynos DRM components.
> > 
> > Signed-off-by: Andrzej Hajda 
> > ---
> >  drivers/gpu/drm/exynos/exynos_drm_drv.c | 27
> > +-- 1 file changed, 1 insertion(+), 26
> > deletions(-)
> 
> This series looks goods to me and works fine on my snow machine:
> 
> Tested-by: Gustavo Padovan 
> 
>   Gustavo

It looks good to me.

Reviewed-by: Hyungwon Hwang 

> ___
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel



[PATCH 2/2] drm/exynos: ipp: validate a GEM handle with multiple planes

2015-06-09 Thread Hyungwon Hwang
FIMC & GSC driver can calculate the offset of planes. So there are
use cases which IPP receives just one GEM handle of an image with
multiple plane. This patch extends ipp_validate_mem_node() to validate
this case.

Signed-off-by: Hyungwon Hwang 
---
 drivers/gpu/drm/exynos/exynos_drm_ipp.c | 51 -
 1 file changed, 38 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c 
b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
index 54c5cf4..b3dc778 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
@@ -482,8 +482,8 @@ static int ipp_validate_mem_node(struct drm_device *drm_dev,
 {
struct drm_exynos_ipp_config *ipp_cfg;
unsigned int num_plane;
-   unsigned long min_size, size;
-   unsigned int bpp;
+   unsigned long size, buf_size = 0, plane_size, img_size = 0;
+   unsigned int bpp, width, height;
int i;

ipp_cfg = _node->property.config[m_node->ops_id];
@@ -497,20 +497,45 @@ static int ipp_validate_mem_node(struct drm_device 
*drm_dev,
 * but it seems more than enough
 */
for (i = 0; i < num_plane; ++i) {
-   if (!m_node->buf_info.handles[i]) {
-   DRM_ERROR("invalid handle for plane %d\n", i);
-   return -EINVAL;
-   }
+   width = ipp_cfg->sz.hsize;
+   height = ipp_cfg->sz.vsize;
bpp = drm_format_plane_cpp(ipp_cfg->fmt, i);
-   min_size = (ipp_cfg->sz.hsize * ipp_cfg->sz.vsize * bpp) >> 3;
-   size = exynos_drm_gem_get_size(drm_dev,
-  m_node->buf_info.handles[i],
-  c_node->filp);
-   if (min_size > size) {
-   DRM_ERROR("invalid size for plane %d\n", i);
-   return -EINVAL;
+
+   /*
+* The result of drm_format_plane_cpp() for chroma planes must
+* be used with drm_format__chroma_subsampling() for
+* correct result.
+*/
+   if (i > 0) {
+   width /= drm_format_horz_chroma_subsampling(
+   ipp_cfg->fmt);
+   height /= drm_format_vert_chroma_subsampling(
+   ipp_cfg->fmt);
}
+   plane_size = width * height * bpp;
+   img_size += plane_size;
+
+   if (m_node->buf_info.handles[i]) {
+   size = exynos_drm_gem_get_size(drm_dev,
+   m_node->buf_info.handles[i],
+   c_node->filp);
+   if (plane_size > size) {
+   DRM_ERROR(
+   "buffer %d is smaller than required\n",
+   i);
+   return -EINVAL;
+   }
+
+   buf_size += size;
+   }
+   }
+
+   if (buf_size < img_size) {
+   DRM_ERROR("size of buffers(%lu) is smaller than image(%lu)\n",
+   buf_size, img_size);
+   return -EINVAL;
}
+
return 0;
 }

-- 
1.9.1



[PATCH 1/2] drm/exynos: ipp: fix wrong index referencing a config element

2015-06-09 Thread Hyungwon Hwang
Config depends on the opreation. So it must be referenced by an
operation id, not a property id.

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

diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c 
b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
index b7f1cbc..54c5cf4 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
@@ -486,8 +486,7 @@ static int ipp_validate_mem_node(struct drm_device *drm_dev,
unsigned int bpp;
int i;

-   /* The property id should already be varified */
-   ipp_cfg = _node->property.config[m_node->prop_id];
+   ipp_cfg = _node->property.config[m_node->ops_id];
num_plane = drm_format_num_planes(ipp_cfg->fmt);

/**
-- 
1.9.1



[PATCH v3] drm/exynos: dsi: check whether dsi is enabled before sending data

2015-06-09 Thread Hyungwon Hwang
exynos_dsi_host_transfer() can be called through a panel driver while
DSI is turning down. It is possible because the function checks only
whether DSI is initialized or not, and there is a moment which DSI is
set by uninitialized, but DSI is still turning down. To prevent it,
DSI must be set by disabled before starting to be turned down, and
exynos_dsi_host_transfer() must check whether DSI is enabled or not.

Kernel dump:
[ 4721.351448] Unhandled fault: synchronous external abort (0x96000210) at 
0xff800015e018
[ 4721.351809] Internal error: : 96000210 [#1] PREEMPT SMP
[ 4721.352031] Modules linked in:
[ 4721.352173] CPU: 2 PID: 300 Comm: deviced Tainted: GW   
4.0.4-01017-g7964a87 #1
[ 4721.353989] Hardware name: Samsung DRACO board (DT)
[ 4721.358852] task: ffc0a0b7 ti: ffc0a00ec000 task.ti: 
ffc0a00ec000
[ 4721.366327] PC is at exynos_dsi_enable_lane+0x14/0x5c
[ 4721.371353] LR is at exynos_dsi_host_transfer+0x834/0x8d8
[ 4721.376731] pc : [] lr : [] pstate: 
6145
[ 4721.384107] sp : ffc0a00efbe0
[ 4721.387405] x29: ffc0a00efbe0 x28: ffc0a00ec000
[ 4721.392699] x27: ffc000968000 x26: 0040
[ 4721.397994] x25: ffc000f74dc0 x24: ffc0a00efec8
[ 4721.403290] x23: ffc0a4815400 x22: ffc0009f2729
[ 4721.408584] x21: ffc0a00efcc8 x20: ffc0a4a2a848
[ 4721.413879] x19: ffc0a4a2a818 x18: 0004
[ 4721.419173] x17: 007faa5cddf0 x16: ffc0001a40a8
[ 4721.424469] x15: 0009 x14: 000d
[ 4721.429762] x13: 6e6e6f63206b726f x12: 0010
[ 4721.435058] x11: 0101010101010101 x10: 
[ 4721.440353] x9 : 000a x8 : 8386838282818381
[ 4721.445648] x7 : ffc0a201efe8 x6 : 
[ 4721.450943] x5 : fffa x4 : ffc0a201f170
[ 4721.456237] x3 : ff800015e000 x2 : ff800015e018
[ 4721.461531] x1 : 000f x0 : ffc0a4a2a818
[ 4721.466826]
[ 4721.468305] Process deviced (pid: 300, stack limit = 0xffc0a00ec028)
[ 4721.474989] Stack: (0xffc0a00efbe0 to 0xffc0a00f)
[ 4721.480720] fbe0: a00efca0 ffc0 0042c944 ffc0 a0f2d680 ffc0 
0024 
[ 4721.488895] fc00: a4b6d000 ffc0 009f2729 ffc0 a4815400 ffc0 
a00efec8 ffc0

Signed-off-by: Hyungwon Hwang 
---
Changes for v2:
 - Previous version of this patch makes a problem in initializing the DSI. This
   patch fixes it, by moving the point which DSI is set by enabled to the
   point before drm_panel_prepare() called. This is where the setting must
   be done, because to call drm_panel_prepare() successfully, DSI must be
   enabled. Also this patch adds the condition to TE irq handler. DSI must be
   enabled and initialized, not just enabled before calling te_handler in
   the display driver.
Changes for v3:
 - New state DSIM_STATE_VIDOUT_AVAILABLE for representing video output
   availability is introduced. Because DSIM_STATE_ENABLED becomes to
   represent whether DSI can be used for data transfer or not, this
   state can be used for checking whether video ouput is available or
   not anymore. So new state have to be introduced. The stete
   DSIM_STATE_VIDOUT_AVAILABLE represents whether DSI is prepared for
   outputting video to a panel or not.

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

diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c 
b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 1cfc4be07..9250356 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -241,6 +241,7 @@ struct exynos_dsi_transfer {
 #define DSIM_STATE_ENABLED BIT(0)
 #define DSIM_STATE_INITIALIZED BIT(1)
 #define DSIM_STATE_CMD_LPM BIT(2)
+#define DSIM_STATE_VIDOUT_AVAILABLEBIT(3)

 struct exynos_dsi_driver_data {
unsigned int *regs;
@@ -1268,7 +1269,7 @@ static irqreturn_t exynos_dsi_te_irq_handler(int irq, 
void *dev_id)
struct exynos_dsi *dsi = (struct exynos_dsi *)dev_id;
struct drm_encoder *encoder = dsi->display.encoder;

-   if (dsi->state & DSIM_STATE_ENABLED)
+   if (dsi->state & DSIM_STATE_VIDOUT_AVAILABLE)
exynos_drm_crtc_te_handler(encoder->crtc);

return IRQ_HANDLED;
@@ -1408,6 +1409,9 @@ static ssize_t exynos_dsi_host_transfer(struct 
mipi_dsi_host *host,
struct exynos_dsi_transfer xfer;
int ret;

+   if (!(dsi->state & DSIM_STATE_ENABLED))
+   return -EINVAL;
+
if (!(dsi->state & DSIM_STATE_INITIALIZED)) {
ret = exynos_dsi_init(dsi);
if (ret)
@@ -1520,8 +1524,11 @@ static int exynos_dsi_enable(struct exynos_dsi *dsi)
if (ret < 0)
return ret;

+   dsi->state |= DSIM_STATE_ENABLED;
+
ret = drm_panel_prepare(dsi->panel);
if (ret < 0) {
+   dsi->state &= ~DS

[PATCH v2] drm/exynos: dsi: check whether dsi is enabled before sending data

2015-06-08 Thread Hyungwon Hwang
exynos_dsi_host_transfer() can be called through a panel driver while
DSI is turning down. It is possible because the function checks only
whether DSI is initialized or not, and there is a moment which DSI is
set by uninitialized, but DSI is still turning down. To prevent it,
DSI must be set by disabled before starting to be turned down, and
exynos_dsi_host_transfer() must check whether DSI is enabled or not.

Kernel dump:
[ 4721.351448] Unhandled fault: synchronous external abort (0x96000210) at 
0xff800015e018
[ 4721.351809] Internal error: : 96000210 [#1] PREEMPT SMP
[ 4721.352031] Modules linked in:
[ 4721.352173] CPU: 2 PID: 300 Comm: deviced Tainted: GW   
4.0.4-01017-g7964a87 #1
[ 4721.353989] Hardware name: Samsung DRACO board (DT)
[ 4721.358852] task: ffc0a0b7 ti: ffc0a00ec000 task.ti: 
ffc0a00ec000
[ 4721.366327] PC is at exynos_dsi_enable_lane+0x14/0x5c
[ 4721.371353] LR is at exynos_dsi_host_transfer+0x834/0x8d8
[ 4721.376731] pc : [] lr : [] pstate: 
6145
[ 4721.384107] sp : ffc0a00efbe0
[ 4721.387405] x29: ffc0a00efbe0 x28: ffc0a00ec000
[ 4721.392699] x27: ffc000968000 x26: 0040
[ 4721.397994] x25: ffc000f74dc0 x24: ffc0a00efec8
[ 4721.403290] x23: ffc0a4815400 x22: ffc0009f2729
[ 4721.408584] x21: ffc0a00efcc8 x20: ffc0a4a2a848
[ 4721.413879] x19: ffc0a4a2a818 x18: 0004
[ 4721.419173] x17: 007faa5cddf0 x16: ffc0001a40a8
[ 4721.424469] x15: 0009 x14: 000d
[ 4721.429762] x13: 6e6e6f63206b726f x12: 0010
[ 4721.435058] x11: 0101010101010101 x10: 
[ 4721.440353] x9 : 000a x8 : 8386838282818381
[ 4721.445648] x7 : ffc0a201efe8 x6 : 
[ 4721.450943] x5 : fffa x4 : ffc0a201f170
[ 4721.456237] x3 : ff800015e000 x2 : ff800015e018
[ 4721.461531] x1 : 000f x0 : ffc0a4a2a818
[ 4721.466826]
[ 4721.468305] Process deviced (pid: 300, stack limit = 0xffc0a00ec028)
[ 4721.474989] Stack: (0xffc0a00efbe0 to 0xffc0a00f)
[ 4721.480720] fbe0: a00efca0 ffc0 0042c944 ffc0 a0f2d680 ffc0 
0024 
[ 4721.488895] fc00: a4b6d000 ffc0 009f2729 ffc0 a4815400 ffc0 
a00efec8 ffc0

Signed-off-by: Hyungwon Hwang 
---
Changes for v2:
 - Previous version of this patch makes a problem in initializing the DSI. This
   patch fixes it, by moving the point which DSI is set by enabled to the
   point before drm_panel_prepare() called. This is where the setting must
   be done, because to call drm_panel_prepare() successfully, DSI must be
   enabled. Also this patch adds the condition to TE irq handler. DSI must be
   enabled and initialized, not just enabled before calling te_handler in
   the display driver.

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

diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c 
b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 1cfc4be07..a2ca956 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -1268,7 +1268,8 @@ static irqreturn_t exynos_dsi_te_irq_handler(int irq, 
void *dev_id)
struct exynos_dsi *dsi = (struct exynos_dsi *)dev_id;
struct drm_encoder *encoder = dsi->display.encoder;

-   if (dsi->state & DSIM_STATE_ENABLED)
+   if ((dsi->state & DSIM_STATE_ENABLED) &&
+   (dsi->state & DSIM_STATE_INITIALIZED))
exynos_drm_crtc_te_handler(encoder->crtc);

return IRQ_HANDLED;
@@ -1408,6 +1409,9 @@ static ssize_t exynos_dsi_host_transfer(struct 
mipi_dsi_host *host,
struct exynos_dsi_transfer xfer;
int ret;

+   if (!(dsi->state & DSIM_STATE_ENABLED))
+   return -EINVAL;
+
if (!(dsi->state & DSIM_STATE_INITIALIZED)) {
ret = exynos_dsi_init(dsi);
if (ret)
@@ -1520,8 +1524,11 @@ static int exynos_dsi_enable(struct exynos_dsi *dsi)
if (ret < 0)
return ret;

+   dsi->state |= DSIM_STATE_ENABLED;
+
ret = drm_panel_prepare(dsi->panel);
if (ret < 0) {
+   dsi->state &= ~DSIM_STATE_ENABLED;
exynos_dsi_poweroff(dsi);
return ret;
}
@@ -1529,8 +1536,6 @@ static int exynos_dsi_enable(struct exynos_dsi *dsi)
exynos_dsi_set_display_mode(dsi);
exynos_dsi_set_display_enable(dsi, true);

-   dsi->state |= DSIM_STATE_ENABLED;
-
ret = drm_panel_enable(dsi->panel);
if (ret < 0) {
dsi->state &= ~DSIM_STATE_ENABLED;
@@ -1551,9 +1556,10 @@ static void exynos_dsi_disable(struct exynos_dsi *dsi)
drm_panel_disable(dsi->panel);
exynos_dsi_set_display_enable(dsi, false);
drm_panel_unprepare(dsi->panel);
-   exynos_dsi_poweroff(dsi);


[PATCH] drm/exynos: dsi: check whether dsi is enabled before sending data

2015-06-04 Thread Hyungwon Hwang
exynos_dsi_host_transfer() can be called through a panel driver while
DSI is turning down. It is possible because the function checks only
whether DSI is initialized or not, and there is a moment which DSI is
set by uninitialized, but DSI is still turning down. To prevent it,
DSI must be set by disabled before starting to be turned down, and
exynos_dsi_host_transfer() must check whether DSI is enabled or not.

Kernel dump:
[ 4721.351448] Unhandled fault: synchronous external abort (0x96000210) at 
0xff800015e018
[ 4721.351809] Internal error: : 96000210 [#1] PREEMPT SMP
[ 4721.352031] Modules linked in:
[ 4721.352173] CPU: 2 PID: 300 Comm: deviced Tainted: GW   
4.0.4-01017-g7964a87 #1
[ 4721.353989] Hardware name: Samsung DRACO board (DT)
[ 4721.358852] task: ffc0a0b7 ti: ffc0a00ec000 task.ti: 
ffc0a00ec000
[ 4721.366327] PC is at exynos_dsi_enable_lane+0x14/0x5c
[ 4721.371353] LR is at exynos_dsi_host_transfer+0x834/0x8d8
[ 4721.376731] pc : [] lr : [] pstate: 
6145
[ 4721.384107] sp : ffc0a00efbe0
[ 4721.387405] x29: ffc0a00efbe0 x28: ffc0a00ec000
[ 4721.392699] x27: ffc000968000 x26: 0040
[ 4721.397994] x25: ffc000f74dc0 x24: ffc0a00efec8
[ 4721.403290] x23: ffc0a4815400 x22: ffc0009f2729
[ 4721.408584] x21: ffc0a00efcc8 x20: ffc0a4a2a848
[ 4721.413879] x19: ffc0a4a2a818 x18: 0004
[ 4721.419173] x17: 007faa5cddf0 x16: ffc0001a40a8
[ 4721.424469] x15: 0009 x14: 000d
[ 4721.429762] x13: 6e6e6f63206b726f x12: 0010
[ 4721.435058] x11: 0101010101010101 x10: 
[ 4721.440353] x9 : 000a x8 : 8386838282818381
[ 4721.445648] x7 : ffc0a201efe8 x6 : 
[ 4721.450943] x5 : fffa x4 : ffc0a201f170
[ 4721.456237] x3 : ff800015e000 x2 : ff800015e018
[ 4721.461531] x1 : 000f x0 : ffc0a4a2a818
[ 4721.466826]
[ 4721.468305] Process deviced (pid: 300, stack limit = 0xffc0a00ec028)
[ 4721.474989] Stack: (0xffc0a00efbe0 to 0xffc0a00f)
[ 4721.480720] fbe0: a00efca0 ffc0 0042c944 ffc0 a0f2d680 ffc0 
0024 
[ 4721.488895] fc00: a4b6d000 ffc0 009f2729 ffc0 a4815400 ffc0 
a00efec8 ffc0

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

diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c 
b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 1cfc4be07..6413339 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -1408,6 +1408,9 @@ static ssize_t exynos_dsi_host_transfer(struct 
mipi_dsi_host *host,
struct exynos_dsi_transfer xfer;
int ret;

+   if (!(dsi->state & DSIM_STATE_ENABLED))
+   return -EINVAL;
+
if (!(dsi->state & DSIM_STATE_INITIALIZED)) {
ret = exynos_dsi_init(dsi);
if (ret)
@@ -1551,9 +1554,10 @@ static void exynos_dsi_disable(struct exynos_dsi *dsi)
drm_panel_disable(dsi->panel);
exynos_dsi_set_display_enable(dsi, false);
drm_panel_unprepare(dsi->panel);
-   exynos_dsi_poweroff(dsi);

dsi->state &= ~DSIM_STATE_ENABLED;
+
+   exynos_dsi_poweroff(dsi);
 }

 static void exynos_dsi_dpms(struct exynos_drm_display *display, int mode)
-- 
1.9.1



[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 = <_reg>;
+   vci-supply = <_reg>;
+   reset-gpio = < 0 GPIO_ACTIVE_LOW>;
+   enable-gpio = < 5 GPIO_ACTIVE_HIGH>;
+   te-gpio = < 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 and/or modify
+ * it under the terms of the

[PATCH v5 01/12] drm/exynos: add Exynos5433 decon driver

2015-04-10 Thread Hyungwon Hwang
Dear Varka Bhadram,

On Fri, 10 Apr 2015 11:35:02 +0530
Varka Bhadram  wrote:

> On 04/10/2015 11:25 AM, Hyungwon Hwang wrote:
> 
> > 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
> >
> > Changes for v4:
> > - rebased to exynos-drm-next with the clean-up patchset by Gustavo
> > Padovan.
> >
> > Changes for v5:
> > - None
> >  .../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  | 617
> > +
> > 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, 856 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
> >
> (...)
> 
> > +   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +   if (!res) {
> > +   dev_err(dev, "cannot find IO resource\n");
> > +   return -ENXIO;
> > +   }
> > +
> 
> Remove the above check. Check one *res* will be done by
> *devm_ioremap_resource()*

OK.

> 
> > +   ctx->addr = devm_ioremap_resource(dev, res);
> > +   if (IS_ERR(ctx->addr)) {
> > +   dev_err(dev, "ioremap failed\n");
> > +   return PTR_ERR(ctx->addr);
> > +   }
> > +
> > +   res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
> > +   ctx->i80_if ? "lcd_sys" : "vsync");
> > +   if (!res) {
> > +   dev_err(dev, "cannot find IRQ resource\n");
> > +   return -ENXIO;
> > +   }
> > +
> > +   ret = devm_request_irq(dev, res->start, ctx->i80_if ?
> > +   decon_lcd_sys_irq_handler :
> > decon_vsync_irq_handler, 0,
> > +   "drm_decon", ctx);
> > +   if (ret < 0) {
> > +   dev_err(dev, "lcd_sys irq request failed\n");
> > +   return ret;
> > +   }
> > +
> > +   ret = exynos_drm_component_add(dev,
> > EXYNOS_DEVICE_TYPE_CRTC,
> > +  EXYNOS_DISPLAY_TYPE_LCD);
> > +   if (ret < 0)
> > +   return ret;
> > +
> > +   platform_set_drvdata(pdev, ctx);
> > +
> > +   ret = component_add(dev, _component_ops);
> > +   if (ret < 0) {
> > +   exynos_drm_component_del(dev,
> > EXYNOS_DEVICE_TYPE_CRTC);
> > +   return ret;
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> > +static int exynos5433_decon_remove(struct platform_device *pdev)
> > +{
> > +   component_del(>dev, _component_ops);
> > +   exynos_drm_component_del(>dev,
> > EXYNOS_DEVICE_TYPE_CRTC); +
> > +   return 0;
> > +}
> > +
> > +static const struct of_device_id
> > exynos5433_decon_driver_dt_match[] = {
> > +   { .compatible = "samsung,exynos5433-decon" },
> > +   {},
> > +};
> > +MODULE_DEVICE_TABLE(of, exynos5433_decon_driver_dt_match);
> > +
> > +struct platform_driver exynos5433_decon_driver = {
> > +   .probe  = exynos5433_decon_probe,
> > +   .remove = exynos5433_decon_remove,
> > +   .driver = {
> > +   .name   = "exynos5433-decon",
> > +   .owner  = THIS_MODULE,
> 
> Remove this field. It will be updated by platform core.
> 

OK.

Thanks for your review.

Best regards,
Hyungwon Hwang

> > +   .of_match_table = exynos5433_decon_driver_dt_match,
> > +   },
> > +};
> 



  1   2   >