[PATCH v3 3/8] drm/rockchip: Convert to support atomic API

2015-12-16 Thread Mark Yao
Rockchip vop not support hw vblank counter, needed check the committed
register if it's really take effect.

Signed-off-by: Mark Yao 
Signed-off-by: Tomasz Figa 
---
Changes in v3:
Reported by kbuild test robot
- fix rockchip_crtc_wait_for_update undefined when build drm rockchip as 
modules.

Changes in v2:
- Optimization commit planes sequence.
- Get vblank count on atomic_begin to protect vblank event.
Adviced by Daniel Stone
- Direct return -EINVAL when yuv address is not support, instead of adjust it.
- code formating and cleanup.
Adviced by Thierry Reding & Daniel Vetter
- Hook mode_set into crtc enable instead of hack crtc enable on mode set.

 drivers/gpu/drm/rockchip/rockchip_drm_drv.c |5 +-
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |3 +-
 drivers/gpu/drm/rockchip/rockchip_drm_fb.c  |   95 
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c |  657 +++
 4 files changed, 363 insertions(+), 397 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index cfd9b83..ab3e0f6 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -213,6 +213,8 @@ static int rockchip_drm_load(struct drm_device *drm_dev, 
unsigned long flags)
 */
drm_dev->vblank_disable_allowed = true;
 
+   drm_mode_config_reset(drm_dev);
+
ret = rockchip_drm_fbdev_init(drm_dev);
if (ret)
goto err_vblank_cleanup;
@@ -276,7 +278,8 @@ const struct vm_operations_struct rockchip_drm_vm_ops = {
 };
 
 static struct drm_driver rockchip_drm_driver = {
-   .driver_features= DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME,
+   .driver_features= DRIVER_MODESET | DRIVER_GEM |
+ DRIVER_PRIME | DRIVER_ATOMIC,
.load   = rockchip_drm_load,
.unload = rockchip_drm_unload,
.lastclose  = rockchip_drm_lastclose,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index 069d6d4..4468f98 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -18,6 +18,7 @@
 #define _ROCKCHIP_DRM_DRV_H
 
 #include 
+#include 
 #include 
 
 #include 
@@ -38,6 +39,7 @@ struct drm_connector;
 struct rockchip_crtc_funcs {
int (*enable_vblank)(struct drm_crtc *crtc);
void (*disable_vblank)(struct drm_crtc *crtc);
+   void (*wait_for_update)(struct drm_crtc *crtc);
 };
 
 /*
@@ -63,5 +65,4 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
   struct device *dev);
 void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
struct device *dev);
-
 #endif /* _ROCKCHIP_DRM_DRV_H_ */
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
index b8ac591..7c974a4 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -166,9 +167,103 @@ static void rockchip_drm_output_poll_changed(struct 
drm_device *dev)
drm_fb_helper_hotplug_event(fb_helper);
 }
 
+static void rockchip_crtc_wait_for_update(struct drm_crtc *crtc)
+{
+   struct rockchip_drm_private *priv = crtc->dev->dev_private;
+   int pipe = drm_crtc_index(crtc);
+   const struct rockchip_crtc_funcs *crtc_funcs = priv->crtc_funcs[pipe];
+
+   if (crtc_funcs && crtc_funcs->wait_for_update)
+   crtc_funcs->wait_for_update(crtc);
+}
+
+static void
+rockchip_atomic_wait_for_complete(struct drm_atomic_state *old_state)
+{
+   struct drm_crtc_state *old_crtc_state;
+   struct drm_crtc *crtc;
+   int i, ret;
+
+   for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
+   /* No one cares about the old state, so abuse it for tracking
+* and store whether we hold a vblank reference (and should do a
+* vblank wait) in the ->enable boolean.
+*/
+   old_crtc_state->enable = false;
+
+   if (!crtc->state->active)
+   continue;
+
+   ret = drm_crtc_vblank_get(crtc);
+   if (ret != 0)
+   continue;
+
+   old_crtc_state->enable = true;
+   }
+
+   for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
+   if (!old_crtc_state->enable)
+   continue;
+
+   rockchip_crtc_wait_for_update(crtc);
+   drm_crtc_vblank_put(crtc);
+   }
+}
+
+int rockchip_drm_atomic_commit(struct drm_device *dev,
+  struct drm_atomic_state *state,
+  bool async)
+{
+   int ret;
+
+   if (async)
+   return 

[PATCH v3 3/8] drm/rockchip: Convert to support atomic API

2015-12-16 Thread Mark Yao
Rockchip vop not support hw vblank counter, needed check the committed
register if it's really take effect.

Signed-off-by: Mark Yao 
Signed-off-by: Tomasz Figa 
---
Changes in v3:
Reported by kbuild test robot
- fix rockchip_crtc_wait_for_update undefined when build drm rockchip as 
modules.

Changes in v2:
- Optimization commit planes sequence.
- Get vblank count on atomic_begin to protect vblank event.
Adviced by Daniel Stone
- Direct return -EINVAL when yuv address is not support, instead of adjust it.
- code formating and cleanup.
Adviced by Thierry Reding & Daniel Vetter
- Hook mode_set into crtc enable instead of hack crtc enable on mode set.

 drivers/gpu/drm/rockchip/rockchip_drm_drv.c |5 +-
 drivers/gpu/drm/rockchip/rockchip_drm_drv.h |3 +-
 drivers/gpu/drm/rockchip/rockchip_drm_fb.c  |   95 
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c |  657 +++
 4 files changed, 363 insertions(+), 397 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index cfd9b83..ab3e0f6 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -213,6 +213,8 @@ static int rockchip_drm_load(struct drm_device *drm_dev, 
unsigned long flags)
 */
drm_dev->vblank_disable_allowed = true;
 
+   drm_mode_config_reset(drm_dev);
+
ret = rockchip_drm_fbdev_init(drm_dev);
if (ret)
goto err_vblank_cleanup;
@@ -276,7 +278,8 @@ const struct vm_operations_struct rockchip_drm_vm_ops = {
 };
 
 static struct drm_driver rockchip_drm_driver = {
-   .driver_features= DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME,
+   .driver_features= DRIVER_MODESET | DRIVER_GEM |
+ DRIVER_PRIME | DRIVER_ATOMIC,
.load   = rockchip_drm_load,
.unload = rockchip_drm_unload,
.lastclose  = rockchip_drm_lastclose,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h 
b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index 069d6d4..4468f98 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -18,6 +18,7 @@
 #define _ROCKCHIP_DRM_DRV_H
 
 #include 
+#include 
 #include 
 
 #include 
@@ -38,6 +39,7 @@ struct drm_connector;
 struct rockchip_crtc_funcs {
int (*enable_vblank)(struct drm_crtc *crtc);
void (*disable_vblank)(struct drm_crtc *crtc);
+   void (*wait_for_update)(struct drm_crtc *crtc);
 };
 
 /*
@@ -63,5 +65,4 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
   struct device *dev);
 void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
struct device *dev);
-
 #endif /* _ROCKCHIP_DRM_DRV_H_ */
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c 
b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
index b8ac591..7c974a4 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -166,9 +167,103 @@ static void rockchip_drm_output_poll_changed(struct 
drm_device *dev)
drm_fb_helper_hotplug_event(fb_helper);
 }
 
+static void rockchip_crtc_wait_for_update(struct drm_crtc *crtc)
+{
+   struct rockchip_drm_private *priv = crtc->dev->dev_private;
+   int pipe = drm_crtc_index(crtc);
+   const struct rockchip_crtc_funcs *crtc_funcs = priv->crtc_funcs[pipe];
+
+   if (crtc_funcs && crtc_funcs->wait_for_update)
+   crtc_funcs->wait_for_update(crtc);
+}
+
+static void
+rockchip_atomic_wait_for_complete(struct drm_atomic_state *old_state)
+{
+   struct drm_crtc_state *old_crtc_state;
+   struct drm_crtc *crtc;
+   int i, ret;
+
+   for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
+   /* No one cares about the old state, so abuse it for tracking
+* and store whether we hold a vblank reference (and should do a
+* vblank wait) in the ->enable boolean.
+*/
+   old_crtc_state->enable = false;
+
+   if (!crtc->state->active)
+   continue;
+
+   ret = drm_crtc_vblank_get(crtc);
+   if (ret != 0)
+   continue;
+
+   old_crtc_state->enable = true;
+   }
+
+   for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
+   if (!old_crtc_state->enable)
+   continue;
+
+   rockchip_crtc_wait_for_update(crtc);
+   drm_crtc_vblank_put(crtc);
+   }
+}
+
+int rockchip_drm_atomic_commit(struct drm_device *dev,
+  struct drm_atomic_state *state,
+  bool async)
+{
+   int