The CMDQ (Command Queue) in MT8183 is used to help update all relevant display controller registers with critical time limation. This patch add cmdq interface in ddp_comp interface, let all ddp_comp interface can support cpu/cmdq function at the same time.
These patches also can fixup cursor moving is not smooth when heavy load in webgl.
This patch depends on ptach: add drm support for MT8183 (https://patchwork.kernel.org/cover/11121519/) support gce on mt8183 platform (https://patchwork.kernel.org/cover/11255147) drm/mediatek: Refactor plane init/check and support rotation (https://pw-emeril.freedesktop.org/series/69015/) drm/mediatek: Check return value of mtk_drm_ddp_comp_for_plane (https://lore.kernel.org/patchwork/patch/1154517/)
Changes since v0: - remove redundant code - remove patch "drm/mediatek: fix atomic_state reference counting" After remove this patch, the issue we met before is gone. So I do not add any extra code to do something.
Bibby Hsieh (6): drm/mediatek: put "event" in critical section drm/mediatek: use DRM core's atomic commit helper drm/mediatek: handle events when enabling/disabling crtc drm/mediatek: update cursors by using async atomic update drm/mediatek: support CMDQ interface in ddp component drm/mediatek: apply CMDQ control flow
drivers/gpu/drm/mediatek/mtk_disp_color.c | 7 +- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 65 +++++---- drivers/gpu/drm/mediatek/mtk_disp_rdma.c | 43 +++--- drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 139 +++++++++++++++++- drivers/gpu/drm/mediatek/mtk_drm_crtc.h | 2 + drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 151 +++++++++++++++----- drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 55 ++++--- drivers/gpu/drm/mediatek/mtk_drm_drv.c | 96 +++---------- drivers/gpu/drm/mediatek/mtk_drm_drv.h | 9 +- drivers/gpu/drm/mediatek/mtk_drm_plane.c | 50 +++++++ drivers/gpu/drm/mediatek/mtk_drm_plane.h | 2 + 11 files changed, 423 insertions(+), 196 deletions(-)
The state->base.event variable would be access by thread context in mtk_drm_crtc_atomic_begin() or by interrupt context in mtk_drm_crtc_finish_page_flip(), so each part should be a critical section. Fix it.
Fixes: 119f5173628a ("drm/mediatek: Add DRM Driver for Mediatek SoC MT8173.")
Signed-off-by: Bibby Hsieh bibby.hsieh@mediatek.com --- drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index 29d0582e90e9..71f4089a8117 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -483,12 +483,15 @@ static void mtk_drm_crtc_atomic_begin(struct drm_crtc *crtc, if (mtk_crtc->event && state->base.event) DRM_ERROR("new event while there is still a pending event\n");
+ spin_lock_irq(&crtc->dev->event_lock); if (state->base.event) { state->base.event->pipe = drm_crtc_index(crtc); WARN_ON(drm_crtc_vblank_get(crtc) != 0); + WARN_ON(mtk_crtc->event); mtk_crtc->event = state->base.event; state->base.event = NULL; } + spin_unlock_irq(&crtc->dev->event_lock); }
static void mtk_drm_crtc_atomic_flush(struct drm_crtc *crtc,
The DRM core atomic helper now supports asynchronous commits natively. The custom drm implementation isn't needed anymore, remove it.
Signed-off-by: Bibby Hsieh bibby.hsieh@mediatek.com --- drivers/gpu/drm/mediatek/mtk_drm_drv.c | 86 ++------------------------ drivers/gpu/drm/mediatek/mtk_drm_drv.h | 7 --- 2 files changed, 5 insertions(+), 88 deletions(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index 6588dc6dd5e3..16e5771d182e 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -36,89 +36,14 @@ #define DRIVER_MAJOR 1 #define DRIVER_MINOR 0
-static void mtk_atomic_schedule(struct mtk_drm_private *private, - struct drm_atomic_state *state) -{ - private->commit.state = state; - schedule_work(&private->commit.work); -} - -static void mtk_atomic_complete(struct mtk_drm_private *private, - struct drm_atomic_state *state) -{ - struct drm_device *drm = private->drm; - - drm_atomic_helper_wait_for_fences(drm, state, false); - - /* - * Mediatek drm supports runtime PM, so plane registers cannot be - * written when their crtc is disabled. - * - * The comment for drm_atomic_helper_commit states: - * For drivers supporting runtime PM the recommended sequence is - * - * drm_atomic_helper_commit_modeset_disables(dev, state); - * drm_atomic_helper_commit_modeset_enables(dev, state); - * drm_atomic_helper_commit_planes(dev, state, - * DRM_PLANE_COMMIT_ACTIVE_ONLY); - * - * See the kerneldoc entries for these three functions for more details. - */ - drm_atomic_helper_commit_modeset_disables(drm, state); - drm_atomic_helper_commit_modeset_enables(drm, state); - drm_atomic_helper_commit_planes(drm, state, - DRM_PLANE_COMMIT_ACTIVE_ONLY); - - drm_atomic_helper_wait_for_vblanks(drm, state); - - drm_atomic_helper_cleanup_planes(drm, state); - drm_atomic_state_put(state); -} - -static void mtk_atomic_work(struct work_struct *work) -{ - struct mtk_drm_private *private = container_of(work, - struct mtk_drm_private, commit.work); - - mtk_atomic_complete(private, private->commit.state); -} - -static int mtk_atomic_commit(struct drm_device *drm, - struct drm_atomic_state *state, - bool async) -{ - struct mtk_drm_private *private = drm->dev_private; - int ret; - - ret = drm_atomic_helper_prepare_planes(drm, state); - if (ret) - return ret; - - mutex_lock(&private->commit.lock); - flush_work(&private->commit.work); - - ret = drm_atomic_helper_swap_state(state, true); - if (ret) { - mutex_unlock(&private->commit.lock); - drm_atomic_helper_cleanup_planes(drm, state); - return ret; - } - - drm_atomic_state_get(state); - if (async) - mtk_atomic_schedule(private, state); - else - mtk_atomic_complete(private, state); - - mutex_unlock(&private->commit.lock); - - return 0; -} +static const struct drm_mode_config_helper_funcs mtk_drm_mode_config_helpers = { + .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm, +};
static const struct drm_mode_config_funcs mtk_drm_mode_config_funcs = { .fb_create = mtk_drm_mode_fb_create, .atomic_check = drm_atomic_helper_check, - .atomic_commit = mtk_atomic_commit, + .atomic_commit = drm_atomic_helper_commit, };
static const enum mtk_ddp_comp_id mt2701_mtk_ddp_main[] = { @@ -265,6 +190,7 @@ static int mtk_drm_kms_init(struct drm_device *drm) drm->mode_config.max_width = 4096; drm->mode_config.max_height = 4096; drm->mode_config.funcs = &mtk_drm_mode_config_funcs; + drm->mode_config.helper_private = &mtk_drm_mode_config_helpers;
ret = component_bind_all(drm->dev, drm); if (ret) @@ -540,8 +466,6 @@ static int mtk_drm_probe(struct platform_device *pdev) if (!private) return -ENOMEM;
- mutex_init(&private->commit.lock); - INIT_WORK(&private->commit.work, mtk_atomic_work); private->data = of_device_get_match_data(dev);
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h index b6a82728d563..9f4ce60174f6 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h @@ -46,13 +46,6 @@ struct mtk_drm_private { struct device_node *comp_node[DDP_COMPONENT_ID_MAX]; struct mtk_ddp_comp *ddp_comp[DDP_COMPONENT_ID_MAX]; const struct mtk_mmsys_driver_data *data; - - struct { - struct drm_atomic_state *state; - struct work_struct work; - struct mutex lock; - } commit; - struct drm_atomic_state *suspend_state;
bool dma_parms_allocated;
Hi, Bibby:
On Thu, 2019-11-28 at 10:42 +0800, Bibby Hsieh wrote:
The DRM core atomic helper now supports asynchronous commits natively. The custom drm implementation isn't needed anymore, remove it.
Reviewed-by: CK Hu ck.hu@mediatek.com
Regards, CK
Signed-off-by: Bibby Hsieh bibby.hsieh@mediatek.com
drivers/gpu/drm/mediatek/mtk_drm_drv.c | 86 ++------------------------ drivers/gpu/drm/mediatek/mtk_drm_drv.h | 7 --- 2 files changed, 5 insertions(+), 88 deletions(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index 6588dc6dd5e3..16e5771d182e 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -36,89 +36,14 @@ #define DRIVER_MAJOR 1 #define DRIVER_MINOR 0
-static void mtk_atomic_schedule(struct mtk_drm_private *private,
struct drm_atomic_state *state)
-{
- private->commit.state = state;
- schedule_work(&private->commit.work);
-}
-static void mtk_atomic_complete(struct mtk_drm_private *private,
struct drm_atomic_state *state)
-{
- struct drm_device *drm = private->drm;
- drm_atomic_helper_wait_for_fences(drm, state, false);
- /*
* Mediatek drm supports runtime PM, so plane registers cannot be
* written when their crtc is disabled.
*
* The comment for drm_atomic_helper_commit states:
* For drivers supporting runtime PM the recommended sequence is
*
* drm_atomic_helper_commit_modeset_disables(dev, state);
* drm_atomic_helper_commit_modeset_enables(dev, state);
* drm_atomic_helper_commit_planes(dev, state,
* DRM_PLANE_COMMIT_ACTIVE_ONLY);
*
* See the kerneldoc entries for these three functions for more details.
*/
- drm_atomic_helper_commit_modeset_disables(drm, state);
- drm_atomic_helper_commit_modeset_enables(drm, state);
- drm_atomic_helper_commit_planes(drm, state,
DRM_PLANE_COMMIT_ACTIVE_ONLY);
- drm_atomic_helper_wait_for_vblanks(drm, state);
- drm_atomic_helper_cleanup_planes(drm, state);
- drm_atomic_state_put(state);
-}
-static void mtk_atomic_work(struct work_struct *work) -{
- struct mtk_drm_private *private = container_of(work,
struct mtk_drm_private, commit.work);
- mtk_atomic_complete(private, private->commit.state);
-}
-static int mtk_atomic_commit(struct drm_device *drm,
struct drm_atomic_state *state,
bool async)
-{
- struct mtk_drm_private *private = drm->dev_private;
- int ret;
- ret = drm_atomic_helper_prepare_planes(drm, state);
- if (ret)
return ret;
- mutex_lock(&private->commit.lock);
- flush_work(&private->commit.work);
- ret = drm_atomic_helper_swap_state(state, true);
- if (ret) {
mutex_unlock(&private->commit.lock);
drm_atomic_helper_cleanup_planes(drm, state);
return ret;
- }
- drm_atomic_state_get(state);
- if (async)
mtk_atomic_schedule(private, state);
- else
mtk_atomic_complete(private, state);
- mutex_unlock(&private->commit.lock);
- return 0;
-} +static const struct drm_mode_config_helper_funcs mtk_drm_mode_config_helpers = {
- .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
+};
static const struct drm_mode_config_funcs mtk_drm_mode_config_funcs = { .fb_create = mtk_drm_mode_fb_create, .atomic_check = drm_atomic_helper_check,
- .atomic_commit = mtk_atomic_commit,
- .atomic_commit = drm_atomic_helper_commit,
};
static const enum mtk_ddp_comp_id mt2701_mtk_ddp_main[] = { @@ -265,6 +190,7 @@ static int mtk_drm_kms_init(struct drm_device *drm) drm->mode_config.max_width = 4096; drm->mode_config.max_height = 4096; drm->mode_config.funcs = &mtk_drm_mode_config_funcs;
drm->mode_config.helper_private = &mtk_drm_mode_config_helpers;
ret = component_bind_all(drm->dev, drm); if (ret)
@@ -540,8 +466,6 @@ static int mtk_drm_probe(struct platform_device *pdev) if (!private) return -ENOMEM;
mutex_init(&private->commit.lock);
INIT_WORK(&private->commit.work, mtk_atomic_work); private->data = of_device_get_match_data(dev);
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h index b6a82728d563..9f4ce60174f6 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h @@ -46,13 +46,6 @@ struct mtk_drm_private { struct device_node *comp_node[DDP_COMPONENT_ID_MAX]; struct mtk_ddp_comp *ddp_comp[DDP_COMPONENT_ID_MAX]; const struct mtk_mmsys_driver_data *data;
struct {
struct drm_atomic_state *state;
struct work_struct work;
struct mutex lock;
} commit;
struct drm_atomic_state *suspend_state;
bool dma_parms_allocated;
The driver currently handles vblank events only when updating planes on an already enabled CRTC. The atomic update API however allows requesting an event when enabling or disabling a CRTC. This currently leads to event objects being leaked in the kernel and to events not being sent out. Fix it.
Signed-off-by: Bibby Hsieh bibby.hsieh@mediatek.com --- drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index 71f4089a8117..cb87a538b8ff 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -334,6 +334,7 @@ static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc) static void mtk_crtc_ddp_hw_fini(struct mtk_drm_crtc *mtk_crtc) { struct drm_device *drm = mtk_crtc->base.dev; + struct drm_crtc *crtc = &mtk_crtc->base; int i;
DRM_DEBUG_DRIVER("%s\n", __func__); @@ -357,6 +358,13 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_drm_crtc *mtk_crtc) mtk_disp_mutex_unprepare(mtk_crtc->mutex);
pm_runtime_put(drm->dev); + + if (crtc->state->event && !crtc->state->active) { + spin_lock_irq(&crtc->dev->event_lock); + drm_crtc_send_vblank_event(crtc, crtc->state->event); + crtc->state->event = NULL; + spin_unlock_irq(&crtc->dev->event_lock); + } }
static void mtk_crtc_ddp_config(struct drm_crtc *crtc)
Hi, Bibby:
On Thu, 2019-11-28 at 10:42 +0800, Bibby Hsieh wrote:
The driver currently handles vblank events only when updating planes on an already enabled CRTC. The atomic update API however allows requesting an event when enabling or disabling a CRTC. This currently leads to event objects being leaked in the kernel and to events not being sent out. Fix it.
Reviewed-by: CK Hu ck.hu@mediatek.com
Signed-off-by: Bibby Hsieh bibby.hsieh@mediatek.com
drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index 71f4089a8117..cb87a538b8ff 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -334,6 +334,7 @@ static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc) static void mtk_crtc_ddp_hw_fini(struct mtk_drm_crtc *mtk_crtc) { struct drm_device *drm = mtk_crtc->base.dev;
struct drm_crtc *crtc = &mtk_crtc->base; int i;
DRM_DEBUG_DRIVER("%s\n", __func__);
@@ -357,6 +358,13 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_drm_crtc *mtk_crtc) mtk_disp_mutex_unprepare(mtk_crtc->mutex);
pm_runtime_put(drm->dev);
- if (crtc->state->event && !crtc->state->active) {
spin_lock_irq(&crtc->dev->event_lock);
drm_crtc_send_vblank_event(crtc, crtc->state->event);
crtc->state->event = NULL;
spin_unlock_irq(&crtc->dev->event_lock);
- }
}
static void mtk_crtc_ddp_config(struct drm_crtc *crtc)
Support to async updates of cursors by using the new atomic interface for that.
Signed-off-by: Bibby Hsieh bibby.hsieh@mediatek.com --- drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 35 +++++++++++++++++ drivers/gpu/drm/mediatek/mtk_drm_crtc.h | 2 + drivers/gpu/drm/mediatek/mtk_drm_drv.c | 22 ++++++++++- drivers/gpu/drm/mediatek/mtk_drm_drv.h | 2 + drivers/gpu/drm/mediatek/mtk_drm_plane.c | 50 ++++++++++++++++++++++++ drivers/gpu/drm/mediatek/mtk_drm_plane.h | 2 + 6 files changed, 112 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index cb87a538b8ff..b26b7a98587b 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -422,6 +422,41 @@ int mtk_drm_crtc_plane_check(struct drm_crtc *crtc, struct drm_plane *plane, return 0; }
+void mtk_drm_crtc_cursor_update(struct drm_crtc *crtc, struct drm_plane *plane, + struct drm_plane_state *new_state) +{ + struct mtk_drm_private *priv = crtc->dev->dev_private; + struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); + const struct drm_plane_helper_funcs *plane_helper_funcs = + plane->helper_private; + int i; + + if (!mtk_crtc->enabled) + return; + + mutex_lock(&priv->hw_lock); + plane_helper_funcs->atomic_update(plane, new_state); + + for (i = 0; i < mtk_crtc->layer_nr; i++) { + struct drm_plane *plane = &mtk_crtc->planes[i]; + struct mtk_plane_state *plane_state; + + plane_state = to_mtk_plane_state(plane->state); + if (plane_state->pending.cursor_dirty) { + plane_state->pending.config = true; + plane_state->pending.cursor_update = false; + plane_state->pending.cursor_dirty = false; + } + } + mtk_crtc->pending_planes = true; + if (priv->data->shadow_register) { + mtk_disp_mutex_acquire(mtk_crtc->mutex); + mtk_crtc_ddp_config(crtc); + mtk_disp_mutex_release(mtk_crtc->mutex); + } + mutex_unlock(&priv->hw_lock); +} + static void mtk_drm_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state) { diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.h b/drivers/gpu/drm/mediatek/mtk_drm_crtc.h index 6afe1c19557a..d57958f0b7b5 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.h @@ -21,5 +21,7 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev, unsigned int path_len); int mtk_drm_crtc_plane_check(struct drm_crtc *crtc, struct drm_plane *plane, struct mtk_plane_state *state); +void mtk_drm_crtc_cursor_update(struct drm_crtc *crtc, struct drm_plane *plane, + struct drm_plane_state *plane_state);
#endif /* MTK_DRM_CRTC_H */ diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index 16e5771d182e..0f7fbb68295d 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -36,8 +36,27 @@ #define DRIVER_MAJOR 1 #define DRIVER_MINOR 0
+static void +mtk_drm_atomic_helper_commit_tail_rpm(struct drm_atomic_state *old_state) +{ + struct drm_device *dev = old_state->dev; + struct mtk_drm_private *private = dev->dev_private; + + drm_atomic_helper_wait_for_fences(dev, old_state, false); + mutex_lock(&private->hw_lock); + drm_atomic_helper_commit_modeset_disables(dev, old_state); + drm_atomic_helper_commit_modeset_enables(dev, old_state); + drm_atomic_helper_commit_planes(dev, old_state, + DRM_PLANE_COMMIT_ACTIVE_ONLY); + mutex_unlock(&private->hw_lock); + drm_atomic_helper_fake_vblank(old_state); + drm_atomic_helper_commit_hw_done(old_state); + drm_atomic_helper_wait_for_vblanks(dev, old_state); + drm_atomic_helper_cleanup_planes(dev, old_state); +} + static const struct drm_mode_config_helper_funcs mtk_drm_mode_config_helpers = { - .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm, + .atomic_commit_tail = mtk_drm_atomic_helper_commit_tail_rpm, };
static const struct drm_mode_config_funcs mtk_drm_mode_config_funcs = { @@ -262,6 +281,7 @@ static int mtk_drm_kms_init(struct drm_device *drm)
drm_kms_helper_poll_init(drm); drm_mode_config_reset(drm); + mutex_init(&private->hw_lock);
return 0;
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h index 9f4ce60174f6..c61adaa92626 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h @@ -48,6 +48,8 @@ struct mtk_drm_private { const struct mtk_mmsys_driver_data *data; struct drm_atomic_state *suspend_state;
+ /* lock for display hw access */ + struct mutex hw_lock; bool dma_parms_allocated; };
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_plane.c b/drivers/gpu/drm/mediatek/mtk_drm_plane.c index cd7c97eb7ee6..d7a8853d94a1 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_plane.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_plane.c @@ -7,6 +7,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_atomic_uapi.h> #include <drm/drm_plane_helper.h> #include <drm/drm_gem_framebuffer_helper.h>
@@ -70,6 +71,50 @@ static void mtk_drm_plane_destroy_state(struct drm_plane *plane, kfree(to_mtk_plane_state(state)); }
+static int mtk_plane_atomic_async_check(struct drm_plane *plane, + struct drm_plane_state *state) +{ + struct drm_crtc_state *crtc_state; + + if (plane != state->crtc->cursor) + return -EINVAL; + + if (!plane->state) + return -EINVAL; + + if (!plane->state->fb) + return -EINVAL; + + if (state->state) + crtc_state = drm_atomic_get_existing_crtc_state(state->state, + state->crtc); + else /* Special case for asynchronous cursor updates. */ + crtc_state = state->crtc->state; + + return drm_atomic_helper_check_plane_state(plane->state, crtc_state, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + true, true); +} + +static void mtk_plane_atomic_async_update(struct drm_plane *plane, + struct drm_plane_state *new_state) +{ + struct mtk_plane_state *state = to_mtk_plane_state(plane->state); + + plane->state->crtc_x = new_state->crtc_x; + plane->state->crtc_y = new_state->crtc_y; + plane->state->crtc_h = new_state->crtc_h; + plane->state->crtc_w = new_state->crtc_w; + plane->state->src_x = new_state->src_x; + plane->state->src_y = new_state->src_y; + plane->state->src_h = new_state->src_h; + plane->state->src_w = new_state->src_w; + state->pending.cursor_update = true; + + mtk_drm_crtc_cursor_update(new_state->crtc, plane, new_state); +} + static const struct drm_plane_funcs mtk_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, @@ -141,6 +186,9 @@ static void mtk_plane_atomic_update(struct drm_plane *plane, state->pending.rotation = plane->state->rotation; wmb(); /* Make sure the above parameters are set before update */ state->pending.dirty = true; + + if (state->pending.cursor_update) + state->pending.cursor_dirty = true; }
static void mtk_plane_atomic_disable(struct drm_plane *plane, @@ -158,6 +206,8 @@ static const struct drm_plane_helper_funcs mtk_plane_helper_funcs = { .atomic_check = mtk_plane_atomic_check, .atomic_update = mtk_plane_atomic_update, .atomic_disable = mtk_plane_atomic_disable, + .atomic_async_update = mtk_plane_atomic_async_update, + .atomic_async_check = mtk_plane_atomic_async_check, };
int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane, diff --git a/drivers/gpu/drm/mediatek/mtk_drm_plane.h b/drivers/gpu/drm/mediatek/mtk_drm_plane.h index 760885e35b27..113a10344805 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_plane.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_plane.h @@ -22,6 +22,8 @@ struct mtk_plane_pending_state { unsigned int height; unsigned int rotation; bool dirty; + bool cursor_dirty; + bool cursor_update; };
struct mtk_plane_state {
Hi, Bibby:
On Thu, 2019-11-28 at 10:42 +0800, Bibby Hsieh wrote:
Support to async updates of cursors by using the new atomic interface for that.
Signed-off-by: Bibby Hsieh bibby.hsieh@mediatek.com
drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 35 +++++++++++++++++ drivers/gpu/drm/mediatek/mtk_drm_crtc.h | 2 + drivers/gpu/drm/mediatek/mtk_drm_drv.c | 22 ++++++++++- drivers/gpu/drm/mediatek/mtk_drm_drv.h | 2 + drivers/gpu/drm/mediatek/mtk_drm_plane.c | 50 ++++++++++++++++++++++++ drivers/gpu/drm/mediatek/mtk_drm_plane.h | 2 + 6 files changed, 112 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index cb87a538b8ff..b26b7a98587b 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -422,6 +422,41 @@ int mtk_drm_crtc_plane_check(struct drm_crtc *crtc, struct drm_plane *plane, return 0; }
+void mtk_drm_crtc_cursor_update(struct drm_crtc *crtc, struct drm_plane *plane,
struct drm_plane_state *new_state)
I do not like to use 'cursor' for naming. The async function may be not just used for cursor. The name 'async' is more general.
+{
- struct mtk_drm_private *priv = crtc->dev->dev_private;
- struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
- const struct drm_plane_helper_funcs *plane_helper_funcs =
plane->helper_private;
- int i;
- if (!mtk_crtc->enabled)
return;
- mutex_lock(&priv->hw_lock);
Please make sure what variable you want to protect, and make critical section smaller.
- plane_helper_funcs->atomic_update(plane, new_state);
- for (i = 0; i < mtk_crtc->layer_nr; i++) {
struct drm_plane *plane = &mtk_crtc->planes[i];
struct mtk_plane_state *plane_state;
plane_state = to_mtk_plane_state(plane->state);
if (plane_state->pending.cursor_dirty) {
plane_state->pending.config = true;
plane_state->pending.cursor_update = false;
plane_state->pending.cursor_dirty = false;
}
- }
- mtk_crtc->pending_planes = true;
- if (priv->data->shadow_register) {
mtk_disp_mutex_acquire(mtk_crtc->mutex);
mtk_crtc_ddp_config(crtc);
mtk_disp_mutex_release(mtk_crtc->mutex);
- }
- mutex_unlock(&priv->hw_lock);
+}
static void mtk_drm_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state) { diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.h b/drivers/gpu/drm/mediatek/mtk_drm_crtc.h index 6afe1c19557a..d57958f0b7b5 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.h @@ -21,5 +21,7 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev, unsigned int path_len); int mtk_drm_crtc_plane_check(struct drm_crtc *crtc, struct drm_plane *plane, struct mtk_plane_state *state); +void mtk_drm_crtc_cursor_update(struct drm_crtc *crtc, struct drm_plane *plane,
struct drm_plane_state *plane_state);
#endif /* MTK_DRM_CRTC_H */ diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index 16e5771d182e..0f7fbb68295d 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -36,8 +36,27 @@ #define DRIVER_MAJOR 1 #define DRIVER_MINOR 0
+static void +mtk_drm_atomic_helper_commit_tail_rpm(struct drm_atomic_state *old_state) +{
- struct drm_device *dev = old_state->dev;
- struct mtk_drm_private *private = dev->dev_private;
- drm_atomic_helper_wait_for_fences(dev, old_state, false);
- mutex_lock(&private->hw_lock);
- drm_atomic_helper_commit_modeset_disables(dev, old_state);
- drm_atomic_helper_commit_modeset_enables(dev, old_state);
- drm_atomic_helper_commit_planes(dev, old_state,
DRM_PLANE_COMMIT_ACTIVE_ONLY);
- mutex_unlock(&private->hw_lock);
You implement mtk version just want to add mutex protect. But I think you should not protect here because what you should protect is the common variable touched by sync plane and async plane. In mtk_drm_crtc_cursor_update(), you already know what is the variable you need to protect, and these variable is touched in mtk_drm_crtc_atomic_flush() or mtk_plane_atomic_update(), so I think you should just protect inside these function and need not to implement this function.
Regards, CK
- drm_atomic_helper_fake_vblank(old_state);
- drm_atomic_helper_commit_hw_done(old_state);
- drm_atomic_helper_wait_for_vblanks(dev, old_state);
- drm_atomic_helper_cleanup_planes(dev, old_state);
+}
static const struct drm_mode_config_helper_funcs mtk_drm_mode_config_helpers = {
- .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
- .atomic_commit_tail = mtk_drm_atomic_helper_commit_tail_rpm,
};
static const struct drm_mode_config_funcs mtk_drm_mode_config_funcs = { @@ -262,6 +281,7 @@ static int mtk_drm_kms_init(struct drm_device *drm)
drm_kms_helper_poll_init(drm); drm_mode_config_reset(drm);
mutex_init(&private->hw_lock);
return 0;
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h index 9f4ce60174f6..c61adaa92626 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h @@ -48,6 +48,8 @@ struct mtk_drm_private { const struct mtk_mmsys_driver_data *data; struct drm_atomic_state *suspend_state;
- /* lock for display hw access */
- struct mutex hw_lock; bool dma_parms_allocated;
};
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_plane.c b/drivers/gpu/drm/mediatek/mtk_drm_plane.c index cd7c97eb7ee6..d7a8853d94a1 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_plane.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_plane.c @@ -7,6 +7,7 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_fourcc.h> +#include <drm/drm_atomic_uapi.h> #include <drm/drm_plane_helper.h> #include <drm/drm_gem_framebuffer_helper.h>
@@ -70,6 +71,50 @@ static void mtk_drm_plane_destroy_state(struct drm_plane *plane, kfree(to_mtk_plane_state(state)); }
+static int mtk_plane_atomic_async_check(struct drm_plane *plane,
struct drm_plane_state *state)
+{
- struct drm_crtc_state *crtc_state;
- if (plane != state->crtc->cursor)
return -EINVAL;
- if (!plane->state)
return -EINVAL;
- if (!plane->state->fb)
return -EINVAL;
- if (state->state)
crtc_state = drm_atomic_get_existing_crtc_state(state->state,
state->crtc);
- else /* Special case for asynchronous cursor updates. */
crtc_state = state->crtc->state;
- return drm_atomic_helper_check_plane_state(plane->state, crtc_state,
DRM_PLANE_HELPER_NO_SCALING,
DRM_PLANE_HELPER_NO_SCALING,
true, true);
+}
+static void mtk_plane_atomic_async_update(struct drm_plane *plane,
struct drm_plane_state *new_state)
+{
- struct mtk_plane_state *state = to_mtk_plane_state(plane->state);
- plane->state->crtc_x = new_state->crtc_x;
- plane->state->crtc_y = new_state->crtc_y;
- plane->state->crtc_h = new_state->crtc_h;
- plane->state->crtc_w = new_state->crtc_w;
- plane->state->src_x = new_state->src_x;
- plane->state->src_y = new_state->src_y;
- plane->state->src_h = new_state->src_h;
- plane->state->src_w = new_state->src_w;
- state->pending.cursor_update = true;
- mtk_drm_crtc_cursor_update(new_state->crtc, plane, new_state);
+}
static const struct drm_plane_funcs mtk_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, @@ -141,6 +186,9 @@ static void mtk_plane_atomic_update(struct drm_plane *plane, state->pending.rotation = plane->state->rotation; wmb(); /* Make sure the above parameters are set before update */ state->pending.dirty = true;
- if (state->pending.cursor_update)
state->pending.cursor_dirty = true;
}
static void mtk_plane_atomic_disable(struct drm_plane *plane, @@ -158,6 +206,8 @@ static const struct drm_plane_helper_funcs mtk_plane_helper_funcs = { .atomic_check = mtk_plane_atomic_check, .atomic_update = mtk_plane_atomic_update, .atomic_disable = mtk_plane_atomic_disable,
- .atomic_async_update = mtk_plane_atomic_async_update,
- .atomic_async_check = mtk_plane_atomic_async_check,
};
int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane, diff --git a/drivers/gpu/drm/mediatek/mtk_drm_plane.h b/drivers/gpu/drm/mediatek/mtk_drm_plane.h index 760885e35b27..113a10344805 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_plane.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_plane.h @@ -22,6 +22,8 @@ struct mtk_plane_pending_state { unsigned int height; unsigned int rotation; bool dirty;
- bool cursor_dirty;
- bool cursor_update;
};
struct mtk_plane_state {
The CMDQ (Command Queue) in MT8183 is used to help update all relevant display controller registers with critical time limation. This patch add cmdq interface in ddp_comp interface, let all ddp_comp interface can support cpu/cmdq function at the same time.
Signed-off-by: YT Shen yt.shen@mediatek.com Signed-off-by: CK Hu ck.hu@mediatek.com Signed-off-by: Philipp Zabel p.zabel@pengutronix.de Signed-off-by: Bibby Hsieh bibby.hsieh@mediatek.com Signed-off-by: Yongqiang Niu yongqiang.niu@mediatek.com --- drivers/gpu/drm/mediatek/mtk_disp_color.c | 7 +- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 65 ++++++----- drivers/gpu/drm/mediatek/mtk_disp_rdma.c | 43 ++++--- drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 11 +- drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 120 ++++++++++++++------ drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 55 ++++++--- 6 files changed, 190 insertions(+), 111 deletions(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_color.c b/drivers/gpu/drm/mediatek/mtk_disp_color.c index 59de2a46aa49..6fb0d6983a4a 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_color.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_color.c @@ -9,6 +9,7 @@ #include <linux/of_device.h> #include <linux/of_irq.h> #include <linux/platform_device.h> +#include <linux/soc/mediatek/mtk-cmdq.h>
#include "mtk_drm_crtc.h" #include "mtk_drm_ddp_comp.h" @@ -45,12 +46,12 @@ static inline struct mtk_disp_color *comp_to_color(struct mtk_ddp_comp *comp)
static void mtk_color_config(struct mtk_ddp_comp *comp, unsigned int w, unsigned int h, unsigned int vrefresh, - unsigned int bpc) + unsigned int bpc, struct cmdq_pkt *cmdq_pkt) { struct mtk_disp_color *color = comp_to_color(comp);
- writel(w, comp->regs + DISP_COLOR_WIDTH(color)); - writel(h, comp->regs + DISP_COLOR_HEIGHT(color)); + mtk_ddp_write(cmdq_pkt, w, comp, DISP_COLOR_WIDTH(color)); + mtk_ddp_write(cmdq_pkt, h, comp, DISP_COLOR_HEIGHT(color)); }
static void mtk_color_start(struct mtk_ddp_comp *comp) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index 722a5adb79dc..0732cd3ee4c8 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -12,6 +12,7 @@ #include <linux/of_irq.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> +#include <linux/soc/mediatek/mtk-cmdq.h>
#include "mtk_drm_crtc.h" #include "mtk_drm_ddp_comp.h" @@ -125,14 +126,15 @@ static void mtk_ovl_stop(struct mtk_ddp_comp *comp)
static void mtk_ovl_config(struct mtk_ddp_comp *comp, unsigned int w, unsigned int h, unsigned int vrefresh, - unsigned int bpc) + unsigned int bpc, struct cmdq_pkt *cmdq_pkt) { if (w != 0 && h != 0) - writel_relaxed(h << 16 | w, comp->regs + DISP_REG_OVL_ROI_SIZE); - writel_relaxed(0x0, comp->regs + DISP_REG_OVL_ROI_BGCLR); + mtk_ddp_write_relaxed(cmdq_pkt, h << 16 | w, comp, + DISP_REG_OVL_ROI_SIZE); + mtk_ddp_write_relaxed(cmdq_pkt, 0x0, comp, DISP_REG_OVL_ROI_BGCLR);
- writel(0x1, comp->regs + DISP_REG_OVL_RST); - writel(0x0, comp->regs + DISP_REG_OVL_RST); + mtk_ddp_write(cmdq_pkt, 0x1, comp, DISP_REG_OVL_RST); + mtk_ddp_write(cmdq_pkt, 0x0, comp, DISP_REG_OVL_RST); }
static unsigned int mtk_ovl_layer_nr(struct mtk_ddp_comp *comp) @@ -176,16 +178,16 @@ static int mtk_ovl_layer_check(struct mtk_ddp_comp *comp, unsigned int idx, return 0; }
-static void mtk_ovl_layer_on(struct mtk_ddp_comp *comp, unsigned int idx) +static void mtk_ovl_layer_on(struct mtk_ddp_comp *comp, unsigned int idx, + struct cmdq_pkt *cmdq_pkt) { - unsigned int reg; unsigned int gmc_thrshd_l; unsigned int gmc_thrshd_h; unsigned int gmc_value; struct mtk_disp_ovl *ovl = comp_to_ovl(comp);
- writel(0x1, comp->regs + DISP_REG_OVL_RDMA_CTRL(idx)); - + mtk_ddp_write(cmdq_pkt, 0x1, comp, + DISP_REG_OVL_RDMA_CTRL(idx)); gmc_thrshd_l = GMC_THRESHOLD_LOW >> (GMC_THRESHOLD_BITS - ovl->data->gmc_bits); gmc_thrshd_h = GMC_THRESHOLD_HIGH >> @@ -195,22 +197,19 @@ static void mtk_ovl_layer_on(struct mtk_ddp_comp *comp, unsigned int idx) else gmc_value = gmc_thrshd_l | gmc_thrshd_l << 8 | gmc_thrshd_h << 16 | gmc_thrshd_h << 24; - writel(gmc_value, comp->regs + DISP_REG_OVL_RDMA_GMC(idx)); - - reg = readl(comp->regs + DISP_REG_OVL_SRC_CON); - reg = reg | BIT(idx); - writel(reg, comp->regs + DISP_REG_OVL_SRC_CON); + mtk_ddp_write(cmdq_pkt, gmc_value, + comp, DISP_REG_OVL_RDMA_GMC(idx)); + mtk_ddp_write_mask(cmdq_pkt, BIT(idx), comp, + DISP_REG_OVL_SRC_CON, BIT(idx)); }
-static void mtk_ovl_layer_off(struct mtk_ddp_comp *comp, unsigned int idx) +static void mtk_ovl_layer_off(struct mtk_ddp_comp *comp, unsigned int idx, + struct cmdq_pkt *cmdq_pkt) { - unsigned int reg; - - reg = readl(comp->regs + DISP_REG_OVL_SRC_CON); - reg = reg & ~BIT(idx); - writel(reg, comp->regs + DISP_REG_OVL_SRC_CON); - - writel(0x0, comp->regs + DISP_REG_OVL_RDMA_CTRL(idx)); + mtk_ddp_write_mask(cmdq_pkt, 0, comp, + DISP_REG_OVL_SRC_CON, BIT(idx)); + mtk_ddp_write(cmdq_pkt, 0, comp, + DISP_REG_OVL_RDMA_CTRL(idx)); }
static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt) @@ -250,7 +249,8 @@ static unsigned int ovl_fmt_convert(struct mtk_disp_ovl *ovl, unsigned int fmt) }
static void mtk_ovl_layer_config(struct mtk_ddp_comp *comp, unsigned int idx, - struct mtk_plane_state *state) + struct mtk_plane_state *state, + struct cmdq_pkt *cmdq_pkt) { struct mtk_disp_ovl *ovl = comp_to_ovl(comp); struct mtk_plane_pending_state *pending = &state->pending; @@ -262,7 +262,7 @@ static void mtk_ovl_layer_config(struct mtk_ddp_comp *comp, unsigned int idx, unsigned int con;
if (!pending->enable) - mtk_ovl_layer_off(comp, idx); + mtk_ovl_layer_off(comp, idx, cmdq_pkt);
con = ovl_fmt_convert(ovl, fmt); if (idx != 0) @@ -278,14 +278,19 @@ static void mtk_ovl_layer_config(struct mtk_ddp_comp *comp, unsigned int idx, addr += pending->pitch - 1; }
- writel_relaxed(con, comp->regs + DISP_REG_OVL_CON(idx)); - writel_relaxed(pitch, comp->regs + DISP_REG_OVL_PITCH(idx)); - writel_relaxed(src_size, comp->regs + DISP_REG_OVL_SRC_SIZE(idx)); - writel_relaxed(offset, comp->regs + DISP_REG_OVL_OFFSET(idx)); - writel_relaxed(addr, comp->regs + DISP_REG_OVL_ADDR(ovl, idx)); + mtk_ddp_write_relaxed(cmdq_pkt, con, comp, + DISP_REG_OVL_CON(idx)); + mtk_ddp_write_relaxed(cmdq_pkt, pitch, comp, + DISP_REG_OVL_PITCH(idx)); + mtk_ddp_write_relaxed(cmdq_pkt, src_size, comp, + DISP_REG_OVL_SRC_SIZE(idx)); + mtk_ddp_write_relaxed(cmdq_pkt, offset, comp, + DISP_REG_OVL_OFFSET(idx)); + mtk_ddp_write_relaxed(cmdq_pkt, addr, comp, + DISP_REG_OVL_ADDR(ovl, idx));
if (pending->enable) - mtk_ovl_layer_on(comp, idx); + mtk_ovl_layer_on(comp, idx, cmdq_pkt); }
static void mtk_ovl_bgclr_in_on(struct mtk_ddp_comp *comp) diff --git a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c index 15cc4ae84aee..c1abde3743bf 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c @@ -10,6 +10,7 @@ #include <linux/of_irq.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> +#include <linux/soc/mediatek/mtk-cmdq.h>
#include "mtk_drm_crtc.h" #include "mtk_drm_ddp_comp.h" @@ -127,15 +128,17 @@ static void mtk_rdma_stop(struct mtk_ddp_comp *comp)
static void mtk_rdma_config(struct mtk_ddp_comp *comp, unsigned int width, unsigned int height, unsigned int vrefresh, - unsigned int bpc) + unsigned int bpc, struct cmdq_pkt *cmdq_pkt) { unsigned int threshold; unsigned int reg; struct mtk_disp_rdma *rdma = comp_to_rdma(comp); u32 rdma_fifo_size;
- rdma_update_bits(comp, DISP_REG_RDMA_SIZE_CON_0, 0xfff, width); - rdma_update_bits(comp, DISP_REG_RDMA_SIZE_CON_1, 0xfffff, height); + mtk_ddp_write_mask(cmdq_pkt, width, comp, + DISP_REG_RDMA_SIZE_CON_0, 0xfff); + mtk_ddp_write_mask(cmdq_pkt, height, comp, + DISP_REG_RDMA_SIZE_CON_1, 0xfffff);
if (rdma->fifo_size) rdma_fifo_size = rdma->fifo_size; @@ -152,7 +155,7 @@ static void mtk_rdma_config(struct mtk_ddp_comp *comp, unsigned int width, reg = RDMA_FIFO_UNDERFLOW_EN | RDMA_FIFO_PSEUDO_SIZE(rdma_fifo_size) | RDMA_OUTPUT_VALID_FIFO_THRESHOLD(threshold); - writel(reg, comp->regs + DISP_REG_RDMA_FIFO_CON); + mtk_ddp_write(cmdq_pkt, reg, comp, DISP_REG_RDMA_FIFO_CON); }
static unsigned int rdma_fmt_convert(struct mtk_disp_rdma *rdma, @@ -198,7 +201,8 @@ static unsigned int mtk_rdma_layer_nr(struct mtk_ddp_comp *comp) }
static void mtk_rdma_layer_config(struct mtk_ddp_comp *comp, unsigned int idx, - struct mtk_plane_state *state) + struct mtk_plane_state *state, + struct cmdq_pkt *cmdq_pkt) { struct mtk_disp_rdma *rdma = comp_to_rdma(comp); struct mtk_plane_pending_state *pending = &state->pending; @@ -208,24 +212,27 @@ static void mtk_rdma_layer_config(struct mtk_ddp_comp *comp, unsigned int idx, unsigned int con;
con = rdma_fmt_convert(rdma, fmt); - writel_relaxed(con, comp->regs + DISP_RDMA_MEM_CON); + mtk_ddp_write_relaxed(cmdq_pkt, con, comp, DISP_RDMA_MEM_CON);
if (fmt == DRM_FORMAT_UYVY || fmt == DRM_FORMAT_YUYV) { - rdma_update_bits(comp, DISP_REG_RDMA_SIZE_CON_0, - RDMA_MATRIX_ENABLE, RDMA_MATRIX_ENABLE); - rdma_update_bits(comp, DISP_REG_RDMA_SIZE_CON_0, - RDMA_MATRIX_INT_MTX_SEL, - RDMA_MATRIX_INT_MTX_BT601_to_RGB); + mtk_ddp_write_mask(cmdq_pkt, RDMA_MATRIX_ENABLE, comp, + DISP_REG_RDMA_SIZE_CON_0, + RDMA_MATRIX_ENABLE); + mtk_ddp_write_mask(cmdq_pkt, RDMA_MATRIX_INT_MTX_BT601_to_RGB, + comp, DISP_REG_RDMA_SIZE_CON_0, + RDMA_MATRIX_INT_MTX_SEL); } else { - rdma_update_bits(comp, DISP_REG_RDMA_SIZE_CON_0, - RDMA_MATRIX_ENABLE, 0); + mtk_ddp_write_mask(cmdq_pkt, 0, comp, + DISP_REG_RDMA_SIZE_CON_0, + RDMA_MATRIX_ENABLE); } + mtk_ddp_write_relaxed(cmdq_pkt, addr, comp, DISP_RDMA_MEM_START_ADDR); + mtk_ddp_write_relaxed(cmdq_pkt, pitch, comp, DISP_RDMA_MEM_SRC_PITCH); + mtk_ddp_write(cmdq_pkt, RDMA_MEM_GMC, comp, + DISP_RDMA_MEM_GMC_SETTING_0); + mtk_ddp_write_mask(cmdq_pkt, RDMA_MODE_MEMORY, comp, + DISP_REG_RDMA_GLOBAL_CON, RDMA_MODE_MEMORY);
- writel_relaxed(addr, comp->regs + DISP_RDMA_MEM_START_ADDR); - writel_relaxed(pitch, comp->regs + DISP_RDMA_MEM_SRC_PITCH); - writel(RDMA_MEM_GMC, comp->regs + DISP_RDMA_MEM_GMC_SETTING_0); - rdma_update_bits(comp, DISP_REG_RDMA_GLOBAL_CON, - RDMA_MODE_MEMORY, RDMA_MODE_MEMORY); }
static const struct mtk_ddp_comp_funcs mtk_disp_rdma_funcs = { diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index b26b7a98587b..fcf4e755e0bd 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -304,7 +304,7 @@ static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc) if (prev == DDP_COMPONENT_OVL0) mtk_ddp_comp_bgclr_in_on(comp);
- mtk_ddp_comp_config(comp, width, height, vrefresh, bpc); + mtk_ddp_comp_config(comp, width, height, vrefresh, bpc, NULL); mtk_ddp_comp_start(comp); }
@@ -319,7 +319,7 @@ static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc) comp = mtk_drm_ddp_comp_for_plane(crtc, plane, &local_layer); if (comp) mtk_ddp_comp_layer_config(comp, local_layer, - plane_state); + plane_state, NULL); }
return 0; @@ -383,7 +383,7 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc) if (state->pending_config) { mtk_ddp_comp_config(comp, state->pending_width, state->pending_height, - state->pending_vrefresh, 0); + state->pending_vrefresh, 0, NULL);
state->pending_config = false; } @@ -403,7 +403,7 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc)
if (comp) mtk_ddp_comp_layer_config(comp, local_layer, - plane_state); + plane_state, NULL); plane_state->pending.config = false; } mtk_crtc->pending_planes = false; @@ -562,7 +562,8 @@ static void mtk_drm_crtc_atomic_flush(struct drm_crtc *crtc, mtk_crtc->pending_planes = true; if (crtc->state->color_mgmt_changed) for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) - mtk_ddp_gamma_set(mtk_crtc->ddp_comp[i], crtc->state); + mtk_ddp_gamma_set(mtk_crtc->ddp_comp[i], + crtc->state, NULL);
if (priv->data->shadow_register) { mtk_disp_mutex_acquire(mtk_crtc->mutex); diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c index 3407d38aff8f..6d0f349ddf82 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c @@ -12,7 +12,8 @@ #include <linux/of_irq.h> #include <linux/of_platform.h> #include <linux/platform_device.h> - +#include <drm/drmP.h> +#include <linux/soc/mediatek/mtk-cmdq.h> #include "mtk_drm_drv.h" #include "mtk_drm_plane.h" #include "mtk_drm_ddp_comp.h" @@ -76,36 +77,82 @@ #define DITHER_ADD_LSHIFT_G(x) (((x) & 0x7) << 4) #define DITHER_ADD_RSHIFT_G(x) (((x) & 0x7) << 0)
+void mtk_ddp_write(struct cmdq_pkt *cmdq_pkt, unsigned int value, + struct mtk_ddp_comp *comp, unsigned int offset) +{ + if (cmdq_pkt) +#ifdef CONFIG_MTK_CMDQ + cmdq_pkt_write(cmdq_pkt, comp->subsys, + comp->regs_pa + offset, value); +#endif + else + writel(value, comp->regs + offset); +} + +void mtk_ddp_write_relaxed(struct cmdq_pkt *cmdq_pkt, unsigned int value, + struct mtk_ddp_comp *comp, + unsigned int offset) +{ + if (cmdq_pkt) +#ifdef CONFIG_MTK_CMDQ + cmdq_pkt_write(cmdq_pkt, comp->subsys, + comp->regs_pa + offset, value); +#endif + else + writel_relaxed(value, comp->regs + offset); +} + +void mtk_ddp_write_mask(struct cmdq_pkt *cmdq_pkt, + unsigned int value, + struct mtk_ddp_comp *comp, + unsigned int offset, + unsigned int mask) +{ + if (cmdq_pkt) { +#ifdef CONFIG_MTK_CMDQ + cmdq_pkt_write_mask(cmdq_pkt, comp->subsys, + comp->regs_pa + offset, value, mask); +#endif + } else { + u32 tmp = readl(comp->regs + offset); + + tmp = (tmp & ~mask) | (value & mask); + writel(tmp, comp->regs + offset); + } +} + void mtk_dither_set(struct mtk_ddp_comp *comp, unsigned int bpc, - unsigned int CFG) + unsigned int CFG, struct cmdq_pkt *cmdq_pkt) { /* If bpc equal to 0, the dithering function didn't be enabled */ if (bpc == 0) return;
if (bpc >= MTK_MIN_BPC) { - writel(0, comp->regs + DISP_DITHER_5); - writel(0, comp->regs + DISP_DITHER_7); - writel(DITHER_LSB_ERR_SHIFT_R(MTK_MAX_BPC - bpc) | - DITHER_ADD_LSHIFT_R(MTK_MAX_BPC - bpc) | - DITHER_NEW_BIT_MODE, - comp->regs + DISP_DITHER_15); - writel(DITHER_LSB_ERR_SHIFT_B(MTK_MAX_BPC - bpc) | - DITHER_ADD_LSHIFT_B(MTK_MAX_BPC - bpc) | - DITHER_LSB_ERR_SHIFT_G(MTK_MAX_BPC - bpc) | - DITHER_ADD_LSHIFT_G(MTK_MAX_BPC - bpc), - comp->regs + DISP_DITHER_16); - writel(DISP_DITHERING, comp->regs + CFG); + mtk_ddp_write(cmdq_pkt, 0, comp, DISP_DITHER_5); + mtk_ddp_write(cmdq_pkt, 0, comp, DISP_DITHER_7); + mtk_ddp_write(cmdq_pkt, + DITHER_LSB_ERR_SHIFT_R(MTK_MAX_BPC - bpc) | + DITHER_ADD_LSHIFT_R(MTK_MAX_BPC - bpc) | + DITHER_NEW_BIT_MODE, + comp, DISP_DITHER_15); + mtk_ddp_write(cmdq_pkt, + DITHER_LSB_ERR_SHIFT_B(MTK_MAX_BPC - bpc) | + DITHER_ADD_LSHIFT_B(MTK_MAX_BPC - bpc) | + DITHER_LSB_ERR_SHIFT_G(MTK_MAX_BPC - bpc) | + DITHER_ADD_LSHIFT_G(MTK_MAX_BPC - bpc), + comp, DISP_DITHER_16); + mtk_ddp_write(cmdq_pkt, DISP_DITHERING, comp, CFG); } }
static void mtk_od_config(struct mtk_ddp_comp *comp, unsigned int w, unsigned int h, unsigned int vrefresh, - unsigned int bpc) + unsigned int bpc, struct cmdq_pkt *cmdq_pkt) { - writel(w << 16 | h, comp->regs + DISP_OD_SIZE); - writel(OD_RELAYMODE, comp->regs + DISP_OD_CFG); - mtk_dither_set(comp, bpc, DISP_OD_CFG); + mtk_ddp_write(cmdq_pkt, w << 16 | h, comp, DISP_OD_SIZE); + mtk_ddp_write(cmdq_pkt, OD_RELAYMODE, comp, DISP_OD_CFG); + mtk_dither_set(comp, bpc, DISP_OD_CFG, cmdq_pkt); }
static void mtk_od_start(struct mtk_ddp_comp *comp) @@ -120,9 +167,9 @@ static void mtk_ufoe_start(struct mtk_ddp_comp *comp)
static void mtk_aal_config(struct mtk_ddp_comp *comp, unsigned int w, unsigned int h, unsigned int vrefresh, - unsigned int bpc) + unsigned int bpc, struct cmdq_pkt *cmdq_pkt) { - writel(h << 16 | w, comp->regs + DISP_AAL_SIZE); + mtk_ddp_write(cmdq_pkt, h << 16 | w, comp, DISP_AAL_SIZE); }
static void mtk_aal_start(struct mtk_ddp_comp *comp) @@ -137,10 +184,10 @@ static void mtk_aal_stop(struct mtk_ddp_comp *comp)
static void mtk_ccorr_config(struct mtk_ddp_comp *comp, unsigned int w, unsigned int h, unsigned int vrefresh, - unsigned int bpc) + unsigned int bpc, struct cmdq_pkt *cmdq_pkt) { - writel(h << 16 | w, comp->regs + DISP_CCORR_SIZE); - writel(CCORR_RELAY_MODE, comp->regs + DISP_CCORR_CFG); + mtk_ddp_write(cmdq_pkt, h << 16 | w, comp, DISP_CCORR_SIZE); + mtk_ddp_write(cmdq_pkt, CCORR_RELAY_MODE, comp, DISP_CCORR_CFG); }
static void mtk_ccorr_start(struct mtk_ddp_comp *comp) @@ -155,10 +202,10 @@ static void mtk_ccorr_stop(struct mtk_ddp_comp *comp)
static void mtk_dither_config(struct mtk_ddp_comp *comp, unsigned int w, unsigned int h, unsigned int vrefresh, - unsigned int bpc) + unsigned int bpc, struct cmdq_pkt *cmdq_pkt) { - writel(h << 16 | w, comp->regs + DISP_DITHER_SIZE); - writel(DITHER_RELAY_MODE, comp->regs + DISP_DITHER_CFG); + mtk_ddp_write(cmdq_pkt, h << 16 | w, comp, DISP_DITHER_SIZE); + mtk_ddp_write(cmdq_pkt, DITHER_RELAY_MODE, comp, DISP_DITHER_CFG); }
static void mtk_dither_start(struct mtk_ddp_comp *comp) @@ -173,10 +220,10 @@ static void mtk_dither_stop(struct mtk_ddp_comp *comp)
static void mtk_gamma_config(struct mtk_ddp_comp *comp, unsigned int w, unsigned int h, unsigned int vrefresh, - unsigned int bpc) + unsigned int bpc, struct cmdq_pkt *cmdq_pkt) { - writel(h << 16 | w, comp->regs + DISP_GAMMA_SIZE); - mtk_dither_set(comp, bpc, DISP_GAMMA_CFG); + mtk_ddp_write(cmdq_pkt, h << 16 | w, comp, DISP_GAMMA_SIZE); + mtk_dither_set(comp, bpc, DISP_GAMMA_CFG, cmdq_pkt); }
static void mtk_gamma_start(struct mtk_ddp_comp *comp) @@ -190,24 +237,23 @@ static void mtk_gamma_stop(struct mtk_ddp_comp *comp) }
static void mtk_gamma_set(struct mtk_ddp_comp *comp, - struct drm_crtc_state *state) + struct drm_crtc_state *state, + struct cmdq_pkt *cmdq_pkt) { - unsigned int i, reg; + unsigned int i; struct drm_color_lut *lut; - void __iomem *lut_base; u32 word;
if (state->gamma_lut) { - reg = readl(comp->regs + DISP_GAMMA_CFG); - reg = reg | GAMMA_LUT_EN; - writel(reg, comp->regs + DISP_GAMMA_CFG); - lut_base = comp->regs + DISP_GAMMA_LUT; + mtk_ddp_write_mask(cmdq_pkt, GAMMA_LUT_EN, comp, + DISP_GAMMA_CFG, GAMMA_LUT_EN); lut = (struct drm_color_lut *)state->gamma_lut->data; for (i = 0; i < MTK_LUT_SIZE; i++) { word = (((lut[i].red >> 6) & LUT_10BIT_MASK) << 20) + (((lut[i].green >> 6) & LUT_10BIT_MASK) << 10) + ((lut[i].blue >> 6) & LUT_10BIT_MASK); - writel(word, (lut_base + i * 4)); + mtk_ddp_write(cmdq_pkt, word, comp, + DISP_GAMMA_LUT + i * 4); } } } diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h index ec55c7488cc3..5b0a3d48dfa6 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h @@ -69,25 +69,30 @@ enum mtk_ddp_comp_id { };
struct mtk_ddp_comp; - +struct cmdq_pkt; struct mtk_ddp_comp_funcs { void (*config)(struct mtk_ddp_comp *comp, unsigned int w, - unsigned int h, unsigned int vrefresh, unsigned int bpc); + unsigned int h, unsigned int vrefresh, + unsigned int bpc, struct cmdq_pkt *cmdq_pkt); void (*start)(struct mtk_ddp_comp *comp); void (*stop)(struct mtk_ddp_comp *comp); void (*enable_vblank)(struct mtk_ddp_comp *comp, struct drm_crtc *crtc); void (*disable_vblank)(struct mtk_ddp_comp *comp); unsigned int (*supported_rotations)(struct mtk_ddp_comp *comp); unsigned int (*layer_nr)(struct mtk_ddp_comp *comp); - void (*layer_on)(struct mtk_ddp_comp *comp, unsigned int idx); - void (*layer_off)(struct mtk_ddp_comp *comp, unsigned int idx); + void (*layer_on)(struct mtk_ddp_comp *comp, unsigned int idx, + struct cmdq_pkt *cmdq_pkt); + void (*layer_off)(struct mtk_ddp_comp *comp, unsigned int idx, + struct cmdq_pkt *cmdq_pkt); int (*layer_check)(struct mtk_ddp_comp *comp, unsigned int idx, struct mtk_plane_state *state); void (*layer_config)(struct mtk_ddp_comp *comp, unsigned int idx, - struct mtk_plane_state *state); + struct mtk_plane_state *state, + struct cmdq_pkt *cmdq_pkt); void (*gamma_set)(struct mtk_ddp_comp *comp, - struct drm_crtc_state *state); + struct drm_crtc_state *state, + struct cmdq_pkt *cmdq_pkt); void (*bgclr_in_on)(struct mtk_ddp_comp *comp); void (*bgclr_in_off)(struct mtk_ddp_comp *comp); }; @@ -99,14 +104,17 @@ struct mtk_ddp_comp { struct device *dev; enum mtk_ddp_comp_id id; const struct mtk_ddp_comp_funcs *funcs; + resource_size_t regs_pa; + u8 subsys; };
static inline void mtk_ddp_comp_config(struct mtk_ddp_comp *comp, unsigned int w, unsigned int h, - unsigned int vrefresh, unsigned int bpc) + unsigned int vrefresh, unsigned int bpc, + struct cmdq_pkt *cmdq_pkt) { if (comp->funcs && comp->funcs->config) - comp->funcs->config(comp, w, h, vrefresh, bpc); + comp->funcs->config(comp, w, h, vrefresh, bpc, cmdq_pkt); }
static inline void mtk_ddp_comp_start(struct mtk_ddp_comp *comp) @@ -152,17 +160,19 @@ static inline unsigned int mtk_ddp_comp_layer_nr(struct mtk_ddp_comp *comp) }
static inline void mtk_ddp_comp_layer_on(struct mtk_ddp_comp *comp, - unsigned int idx) + unsigned int idx, + struct cmdq_pkt *cmdq_pkt) { if (comp->funcs && comp->funcs->layer_on) - comp->funcs->layer_on(comp, idx); + comp->funcs->layer_on(comp, idx, cmdq_pkt); }
static inline void mtk_ddp_comp_layer_off(struct mtk_ddp_comp *comp, - unsigned int idx) + unsigned int idx, + struct cmdq_pkt *cmdq_pkt) { if (comp->funcs && comp->funcs->layer_off) - comp->funcs->layer_off(comp, idx); + comp->funcs->layer_off(comp, idx, cmdq_pkt); }
static inline int mtk_ddp_comp_layer_check(struct mtk_ddp_comp *comp, @@ -176,17 +186,19 @@ static inline int mtk_ddp_comp_layer_check(struct mtk_ddp_comp *comp,
static inline void mtk_ddp_comp_layer_config(struct mtk_ddp_comp *comp, unsigned int idx, - struct mtk_plane_state *state) + struct mtk_plane_state *state, + struct cmdq_pkt *cmdq_pkt) { if (comp->funcs && comp->funcs->layer_config) - comp->funcs->layer_config(comp, idx, state); + comp->funcs->layer_config(comp, idx, state, cmdq_pkt); }
static inline void mtk_ddp_gamma_set(struct mtk_ddp_comp *comp, - struct drm_crtc_state *state) + struct drm_crtc_state *state, + struct cmdq_pkt *cmdq_pkt) { if (comp->funcs && comp->funcs->gamma_set) - comp->funcs->gamma_set(comp, state); + comp->funcs->gamma_set(comp, state, cmdq_pkt); }
static inline void mtk_ddp_comp_bgclr_in_on(struct mtk_ddp_comp *comp) @@ -209,6 +221,13 @@ int mtk_ddp_comp_init(struct device *dev, struct device_node *comp_node, int mtk_ddp_comp_register(struct drm_device *drm, struct mtk_ddp_comp *comp); void mtk_ddp_comp_unregister(struct drm_device *drm, struct mtk_ddp_comp *comp); void mtk_dither_set(struct mtk_ddp_comp *comp, unsigned int bpc, - unsigned int CFG); - + unsigned int CFG, struct cmdq_pkt *cmdq_pkt); +enum mtk_ddp_comp_type mtk_ddp_comp_get_type(enum mtk_ddp_comp_id comp_id); +void mtk_ddp_write(struct cmdq_pkt *cmdq_pkt, unsigned int value, + struct mtk_ddp_comp *comp, unsigned int offset); +void mtk_ddp_write_relaxed(struct cmdq_pkt *cmdq_pkt, unsigned int value, + struct mtk_ddp_comp *comp, unsigned int offset); +void mtk_ddp_write_mask(struct cmdq_pkt *cmdq_pkt, unsigned int value, + struct mtk_ddp_comp *comp, unsigned int offset, + unsigned int mask); #endif /* MTK_DRM_DDP_COMP_H */
Hi, Bibby:
On Thu, 2019-11-28 at 10:42 +0800, Bibby Hsieh wrote:
The CMDQ (Command Queue) in MT8183 is used to help update all relevant display controller registers with critical time limation. This patch add cmdq interface in ddp_comp interface, let all ddp_comp interface can support cpu/cmdq function at the same time.
Signed-off-by: YT Shen yt.shen@mediatek.com Signed-off-by: CK Hu ck.hu@mediatek.com Signed-off-by: Philipp Zabel p.zabel@pengutronix.de Signed-off-by: Bibby Hsieh bibby.hsieh@mediatek.com Signed-off-by: Yongqiang Niu yongqiang.niu@mediatek.com
drivers/gpu/drm/mediatek/mtk_disp_color.c | 7 +- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 65 ++++++----- drivers/gpu/drm/mediatek/mtk_disp_rdma.c | 43 ++++--- drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 11 +- drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 120 ++++++++++++++------ drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 55 ++++++--- 6 files changed, 190 insertions(+), 111 deletions(-)
[snip]
static const struct mtk_ddp_comp_funcs mtk_disp_rdma_funcs = { diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index b26b7a98587b..fcf4e755e0bd 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -304,7 +304,7 @@ static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc) if (prev == DDP_COMPONENT_OVL0) mtk_ddp_comp_bgclr_in_on(comp);
mtk_ddp_comp_config(comp, width, height, vrefresh, bpc);
mtk_ddp_comp_start(comp); }mtk_ddp_comp_config(comp, width, height, vrefresh, bpc, NULL);
@@ -319,7 +319,7 @@ static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc) comp = mtk_drm_ddp_comp_for_plane(crtc, plane, &local_layer); if (comp) mtk_ddp_comp_layer_config(comp, local_layer,
plane_state);
plane_state, NULL);
}
return 0;
@@ -383,7 +383,7 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc) if (state->pending_config) { mtk_ddp_comp_config(comp, state->pending_width, state->pending_height,
state->pending_vrefresh, 0);
state->pending_vrefresh, 0, NULL);
state->pending_config = false; }
@@ -403,7 +403,7 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc)
if (comp) mtk_ddp_comp_layer_config(comp, local_layer,
plane_state);
} mtk_crtc->pending_planes = false;plane_state, NULL); plane_state->pending.config = false;
@@ -562,7 +562,8 @@ static void mtk_drm_crtc_atomic_flush(struct drm_crtc *crtc, mtk_crtc->pending_planes = true; if (crtc->state->color_mgmt_changed) for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
mtk_ddp_gamma_set(mtk_crtc->ddp_comp[i], crtc->state);
mtk_ddp_gamma_set(mtk_crtc->ddp_comp[i],
crtc->state, NULL);
If gamm_set is always with NULL packet, I think you need not to change the interface of gamma_set.
Regards, CK
if (priv->data->shadow_register) { mtk_disp_mutex_acquire(mtk_crtc->mutex); diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c index 3407d38aff8f..6d0f349ddf82 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c @@ -12,7 +12,8 @@ #include <linux/of_irq.h> #include <linux/of_platform.h> #include <linux/platform_device.h>
+#include <drm/drmP.h> +#include <linux/soc/mediatek/mtk-cmdq.h> #include "mtk_drm_drv.h" #include "mtk_drm_plane.h" #include "mtk_drm_ddp_comp.h" @@ -76,36 +77,82 @@ #define DITHER_ADD_LSHIFT_G(x) (((x) & 0x7) << 4) #define DITHER_ADD_RSHIFT_G(x) (((x) & 0x7) << 0)
+void mtk_ddp_write(struct cmdq_pkt *cmdq_pkt, unsigned int value,
struct mtk_ddp_comp *comp, unsigned int offset)
+{
- if (cmdq_pkt)
+#ifdef CONFIG_MTK_CMDQ
cmdq_pkt_write(cmdq_pkt, comp->subsys,
comp->regs_pa + offset, value);
+#endif
- else
writel(value, comp->regs + offset);
+}
+void mtk_ddp_write_relaxed(struct cmdq_pkt *cmdq_pkt, unsigned int value,
struct mtk_ddp_comp *comp,
unsigned int offset)
+{
- if (cmdq_pkt)
+#ifdef CONFIG_MTK_CMDQ
cmdq_pkt_write(cmdq_pkt, comp->subsys,
comp->regs_pa + offset, value);
+#endif
- else
writel_relaxed(value, comp->regs + offset);
+}
+void mtk_ddp_write_mask(struct cmdq_pkt *cmdq_pkt,
unsigned int value,
struct mtk_ddp_comp *comp,
unsigned int offset,
unsigned int mask)
+{
- if (cmdq_pkt) {
+#ifdef CONFIG_MTK_CMDQ
cmdq_pkt_write_mask(cmdq_pkt, comp->subsys,
comp->regs_pa + offset, value, mask);
+#endif
- } else {
u32 tmp = readl(comp->regs + offset);
tmp = (tmp & ~mask) | (value & mask);
writel(tmp, comp->regs + offset);
- }
+}
void mtk_dither_set(struct mtk_ddp_comp *comp, unsigned int bpc,
unsigned int CFG)
unsigned int CFG, struct cmdq_pkt *cmdq_pkt)
{ /* If bpc equal to 0, the dithering function didn't be enabled */ if (bpc == 0) return;
if (bpc >= MTK_MIN_BPC) {
writel(0, comp->regs + DISP_DITHER_5);
writel(0, comp->regs + DISP_DITHER_7);
writel(DITHER_LSB_ERR_SHIFT_R(MTK_MAX_BPC - bpc) |
DITHER_ADD_LSHIFT_R(MTK_MAX_BPC - bpc) |
DITHER_NEW_BIT_MODE,
comp->regs + DISP_DITHER_15);
writel(DITHER_LSB_ERR_SHIFT_B(MTK_MAX_BPC - bpc) |
DITHER_ADD_LSHIFT_B(MTK_MAX_BPC - bpc) |
DITHER_LSB_ERR_SHIFT_G(MTK_MAX_BPC - bpc) |
DITHER_ADD_LSHIFT_G(MTK_MAX_BPC - bpc),
comp->regs + DISP_DITHER_16);
writel(DISP_DITHERING, comp->regs + CFG);
mtk_ddp_write(cmdq_pkt, 0, comp, DISP_DITHER_5);
mtk_ddp_write(cmdq_pkt, 0, comp, DISP_DITHER_7);
mtk_ddp_write(cmdq_pkt,
DITHER_LSB_ERR_SHIFT_R(MTK_MAX_BPC - bpc) |
DITHER_ADD_LSHIFT_R(MTK_MAX_BPC - bpc) |
DITHER_NEW_BIT_MODE,
comp, DISP_DITHER_15);
mtk_ddp_write(cmdq_pkt,
DITHER_LSB_ERR_SHIFT_B(MTK_MAX_BPC - bpc) |
DITHER_ADD_LSHIFT_B(MTK_MAX_BPC - bpc) |
DITHER_LSB_ERR_SHIFT_G(MTK_MAX_BPC - bpc) |
DITHER_ADD_LSHIFT_G(MTK_MAX_BPC - bpc),
comp, DISP_DITHER_16);
}mtk_ddp_write(cmdq_pkt, DISP_DITHERING, comp, CFG);
}
static void mtk_od_config(struct mtk_ddp_comp *comp, unsigned int w, unsigned int h, unsigned int vrefresh,
unsigned int bpc)
unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
{
- writel(w << 16 | h, comp->regs + DISP_OD_SIZE);
- writel(OD_RELAYMODE, comp->regs + DISP_OD_CFG);
- mtk_dither_set(comp, bpc, DISP_OD_CFG);
- mtk_ddp_write(cmdq_pkt, w << 16 | h, comp, DISP_OD_SIZE);
- mtk_ddp_write(cmdq_pkt, OD_RELAYMODE, comp, DISP_OD_CFG);
- mtk_dither_set(comp, bpc, DISP_OD_CFG, cmdq_pkt);
}
static void mtk_od_start(struct mtk_ddp_comp *comp) @@ -120,9 +167,9 @@ static void mtk_ufoe_start(struct mtk_ddp_comp *comp)
static void mtk_aal_config(struct mtk_ddp_comp *comp, unsigned int w, unsigned int h, unsigned int vrefresh,
unsigned int bpc)
unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
{
- writel(h << 16 | w, comp->regs + DISP_AAL_SIZE);
- mtk_ddp_write(cmdq_pkt, h << 16 | w, comp, DISP_AAL_SIZE);
}
static void mtk_aal_start(struct mtk_ddp_comp *comp) @@ -137,10 +184,10 @@ static void mtk_aal_stop(struct mtk_ddp_comp *comp)
static void mtk_ccorr_config(struct mtk_ddp_comp *comp, unsigned int w, unsigned int h, unsigned int vrefresh,
unsigned int bpc)
unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
{
- writel(h << 16 | w, comp->regs + DISP_CCORR_SIZE);
- writel(CCORR_RELAY_MODE, comp->regs + DISP_CCORR_CFG);
- mtk_ddp_write(cmdq_pkt, h << 16 | w, comp, DISP_CCORR_SIZE);
- mtk_ddp_write(cmdq_pkt, CCORR_RELAY_MODE, comp, DISP_CCORR_CFG);
}
static void mtk_ccorr_start(struct mtk_ddp_comp *comp) @@ -155,10 +202,10 @@ static void mtk_ccorr_stop(struct mtk_ddp_comp *comp)
static void mtk_dither_config(struct mtk_ddp_comp *comp, unsigned int w, unsigned int h, unsigned int vrefresh,
unsigned int bpc)
unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
{
- writel(h << 16 | w, comp->regs + DISP_DITHER_SIZE);
- writel(DITHER_RELAY_MODE, comp->regs + DISP_DITHER_CFG);
- mtk_ddp_write(cmdq_pkt, h << 16 | w, comp, DISP_DITHER_SIZE);
- mtk_ddp_write(cmdq_pkt, DITHER_RELAY_MODE, comp, DISP_DITHER_CFG);
}
static void mtk_dither_start(struct mtk_ddp_comp *comp) @@ -173,10 +220,10 @@ static void mtk_dither_stop(struct mtk_ddp_comp *comp)
static void mtk_gamma_config(struct mtk_ddp_comp *comp, unsigned int w, unsigned int h, unsigned int vrefresh,
unsigned int bpc)
unsigned int bpc, struct cmdq_pkt *cmdq_pkt)
{
- writel(h << 16 | w, comp->regs + DISP_GAMMA_SIZE);
- mtk_dither_set(comp, bpc, DISP_GAMMA_CFG);
- mtk_ddp_write(cmdq_pkt, h << 16 | w, comp, DISP_GAMMA_SIZE);
- mtk_dither_set(comp, bpc, DISP_GAMMA_CFG, cmdq_pkt);
}
static void mtk_gamma_start(struct mtk_ddp_comp *comp) @@ -190,24 +237,23 @@ static void mtk_gamma_stop(struct mtk_ddp_comp *comp) }
static void mtk_gamma_set(struct mtk_ddp_comp *comp,
struct drm_crtc_state *state)
struct drm_crtc_state *state,
struct cmdq_pkt *cmdq_pkt)
{
- unsigned int i, reg;
- unsigned int i; struct drm_color_lut *lut;
void __iomem *lut_base; u32 word;
if (state->gamma_lut) {
reg = readl(comp->regs + DISP_GAMMA_CFG);
reg = reg | GAMMA_LUT_EN;
writel(reg, comp->regs + DISP_GAMMA_CFG);
lut_base = comp->regs + DISP_GAMMA_LUT;
mtk_ddp_write_mask(cmdq_pkt, GAMMA_LUT_EN, comp,
lut = (struct drm_color_lut *)state->gamma_lut->data; for (i = 0; i < MTK_LUT_SIZE; i++) { word = (((lut[i].red >> 6) & LUT_10BIT_MASK) << 20) + (((lut[i].green >> 6) & LUT_10BIT_MASK) << 10) + ((lut[i].blue >> 6) & LUT_10BIT_MASK);DISP_GAMMA_CFG, GAMMA_LUT_EN);
writel(word, (lut_base + i * 4));
mtk_ddp_write(cmdq_pkt, word, comp,
} }DISP_GAMMA_LUT + i * 4);
} diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h index ec55c7488cc3..5b0a3d48dfa6 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h @@ -69,25 +69,30 @@ enum mtk_ddp_comp_id { };
struct mtk_ddp_comp;
+struct cmdq_pkt; struct mtk_ddp_comp_funcs { void (*config)(struct mtk_ddp_comp *comp, unsigned int w,
unsigned int h, unsigned int vrefresh, unsigned int bpc);
unsigned int h, unsigned int vrefresh,
void (*start)(struct mtk_ddp_comp *comp); void (*stop)(struct mtk_ddp_comp *comp); void (*enable_vblank)(struct mtk_ddp_comp *comp, struct drm_crtc *crtc); void (*disable_vblank)(struct mtk_ddp_comp *comp); unsigned int (*supported_rotations)(struct mtk_ddp_comp *comp); unsigned int (*layer_nr)(struct mtk_ddp_comp *comp);unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
- void (*layer_on)(struct mtk_ddp_comp *comp, unsigned int idx);
- void (*layer_off)(struct mtk_ddp_comp *comp, unsigned int idx);
- void (*layer_on)(struct mtk_ddp_comp *comp, unsigned int idx,
struct cmdq_pkt *cmdq_pkt);
- void (*layer_off)(struct mtk_ddp_comp *comp, unsigned int idx,
int (*layer_check)(struct mtk_ddp_comp *comp, unsigned int idx, struct mtk_plane_state *state); void (*layer_config)(struct mtk_ddp_comp *comp, unsigned int idx,struct cmdq_pkt *cmdq_pkt);
struct mtk_plane_state *state);
struct mtk_plane_state *state,
void (*gamma_set)(struct mtk_ddp_comp *comp,struct cmdq_pkt *cmdq_pkt);
struct drm_crtc_state *state);
struct drm_crtc_state *state,
void (*bgclr_in_on)(struct mtk_ddp_comp *comp); void (*bgclr_in_off)(struct mtk_ddp_comp *comp);struct cmdq_pkt *cmdq_pkt);
}; @@ -99,14 +104,17 @@ struct mtk_ddp_comp { struct device *dev; enum mtk_ddp_comp_id id; const struct mtk_ddp_comp_funcs *funcs;
- resource_size_t regs_pa;
- u8 subsys;
};
static inline void mtk_ddp_comp_config(struct mtk_ddp_comp *comp, unsigned int w, unsigned int h,
unsigned int vrefresh, unsigned int bpc)
unsigned int vrefresh, unsigned int bpc,
struct cmdq_pkt *cmdq_pkt)
{ if (comp->funcs && comp->funcs->config)
comp->funcs->config(comp, w, h, vrefresh, bpc);
comp->funcs->config(comp, w, h, vrefresh, bpc, cmdq_pkt);
}
static inline void mtk_ddp_comp_start(struct mtk_ddp_comp *comp) @@ -152,17 +160,19 @@ static inline unsigned int mtk_ddp_comp_layer_nr(struct mtk_ddp_comp *comp) }
static inline void mtk_ddp_comp_layer_on(struct mtk_ddp_comp *comp,
unsigned int idx)
unsigned int idx,
struct cmdq_pkt *cmdq_pkt)
{ if (comp->funcs && comp->funcs->layer_on)
comp->funcs->layer_on(comp, idx);
comp->funcs->layer_on(comp, idx, cmdq_pkt);
}
static inline void mtk_ddp_comp_layer_off(struct mtk_ddp_comp *comp,
unsigned int idx)
unsigned int idx,
struct cmdq_pkt *cmdq_pkt)
{ if (comp->funcs && comp->funcs->layer_off)
comp->funcs->layer_off(comp, idx);
comp->funcs->layer_off(comp, idx, cmdq_pkt);
}
static inline int mtk_ddp_comp_layer_check(struct mtk_ddp_comp *comp, @@ -176,17 +186,19 @@ static inline int mtk_ddp_comp_layer_check(struct mtk_ddp_comp *comp,
static inline void mtk_ddp_comp_layer_config(struct mtk_ddp_comp *comp, unsigned int idx,
struct mtk_plane_state *state)
struct mtk_plane_state *state,
struct cmdq_pkt *cmdq_pkt)
{ if (comp->funcs && comp->funcs->layer_config)
comp->funcs->layer_config(comp, idx, state);
comp->funcs->layer_config(comp, idx, state, cmdq_pkt);
}
static inline void mtk_ddp_gamma_set(struct mtk_ddp_comp *comp,
struct drm_crtc_state *state)
struct drm_crtc_state *state,
struct cmdq_pkt *cmdq_pkt)
{ if (comp->funcs && comp->funcs->gamma_set)
comp->funcs->gamma_set(comp, state);
comp->funcs->gamma_set(comp, state, cmdq_pkt);
}
static inline void mtk_ddp_comp_bgclr_in_on(struct mtk_ddp_comp *comp) @@ -209,6 +221,13 @@ int mtk_ddp_comp_init(struct device *dev, struct device_node *comp_node, int mtk_ddp_comp_register(struct drm_device *drm, struct mtk_ddp_comp *comp); void mtk_ddp_comp_unregister(struct drm_device *drm, struct mtk_ddp_comp *comp); void mtk_dither_set(struct mtk_ddp_comp *comp, unsigned int bpc,
unsigned int CFG);
unsigned int CFG, struct cmdq_pkt *cmdq_pkt);
+enum mtk_ddp_comp_type mtk_ddp_comp_get_type(enum mtk_ddp_comp_id comp_id); +void mtk_ddp_write(struct cmdq_pkt *cmdq_pkt, unsigned int value,
struct mtk_ddp_comp *comp, unsigned int offset);
+void mtk_ddp_write_relaxed(struct cmdq_pkt *cmdq_pkt, unsigned int value,
struct mtk_ddp_comp *comp, unsigned int offset);
+void mtk_ddp_write_mask(struct cmdq_pkt *cmdq_pkt, unsigned int value,
struct mtk_ddp_comp *comp, unsigned int offset,
unsigned int mask);
#endif /* MTK_DRM_DDP_COMP_H */
Hi, Bibby:
On Tue, 2019-12-03 at 10:56 +0800, CK Hu wrote:
Hi, Bibby:
On Thu, 2019-11-28 at 10:42 +0800, Bibby Hsieh wrote:
The CMDQ (Command Queue) in MT8183 is used to help update all relevant display controller registers with critical time limation. This patch add cmdq interface in ddp_comp interface, let all ddp_comp interface can support cpu/cmdq function at the same time.
Signed-off-by: YT Shen yt.shen@mediatek.com Signed-off-by: CK Hu ck.hu@mediatek.com Signed-off-by: Philipp Zabel p.zabel@pengutronix.de Signed-off-by: Bibby Hsieh bibby.hsieh@mediatek.com Signed-off-by: Yongqiang Niu yongqiang.niu@mediatek.com
drivers/gpu/drm/mediatek/mtk_disp_color.c | 7 +- drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 65 ++++++----- drivers/gpu/drm/mediatek/mtk_disp_rdma.c | 43 ++++--- drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 11 +- drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 120 ++++++++++++++------ drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 55 ++++++--- 6 files changed, 190 insertions(+), 111 deletions(-)
[snip]
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h index ec55c7488cc3..5b0a3d48dfa6 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h @@ -69,25 +69,30 @@ enum mtk_ddp_comp_id { };
struct mtk_ddp_comp;
+struct cmdq_pkt; struct mtk_ddp_comp_funcs { void (*config)(struct mtk_ddp_comp *comp, unsigned int w,
unsigned int h, unsigned int vrefresh, unsigned int bpc);
unsigned int h, unsigned int vrefresh,
void (*start)(struct mtk_ddp_comp *comp); void (*stop)(struct mtk_ddp_comp *comp); void (*enable_vblank)(struct mtk_ddp_comp *comp, struct drm_crtc *crtc); void (*disable_vblank)(struct mtk_ddp_comp *comp); unsigned int (*supported_rotations)(struct mtk_ddp_comp *comp); unsigned int (*layer_nr)(struct mtk_ddp_comp *comp);unsigned int bpc, struct cmdq_pkt *cmdq_pkt);
- void (*layer_on)(struct mtk_ddp_comp *comp, unsigned int idx);
- void (*layer_off)(struct mtk_ddp_comp *comp, unsigned int idx);
- void (*layer_on)(struct mtk_ddp_comp *comp, unsigned int idx,
struct cmdq_pkt *cmdq_pkt);
- void (*layer_off)(struct mtk_ddp_comp *comp, unsigned int idx,
struct cmdq_pkt *cmdq_pkt);
layer_on() and layer_off() looks useless, so I would like you just remove this interface in another patch.
Regards, CK
int (*layer_check)(struct mtk_ddp_comp *comp, unsigned int idx, struct mtk_plane_state *state); void (*layer_config)(struct mtk_ddp_comp *comp, unsigned int idx,
struct mtk_plane_state *state);
struct mtk_plane_state *state,
void (*gamma_set)(struct mtk_ddp_comp *comp,struct cmdq_pkt *cmdq_pkt);
struct drm_crtc_state *state);
struct drm_crtc_state *state,
void (*bgclr_in_on)(struct mtk_ddp_comp *comp); void (*bgclr_in_off)(struct mtk_ddp_comp *comp);struct cmdq_pkt *cmdq_pkt);
}; @@ -99,14 +104,17 @@ struct mtk_ddp_comp { struct device *dev; enum mtk_ddp_comp_id id; const struct mtk_ddp_comp_funcs *funcs;
- resource_size_t regs_pa;
- u8 subsys;
};
static inline void mtk_ddp_comp_config(struct mtk_ddp_comp *comp, unsigned int w, unsigned int h,
unsigned int vrefresh, unsigned int bpc)
unsigned int vrefresh, unsigned int bpc,
struct cmdq_pkt *cmdq_pkt)
{ if (comp->funcs && comp->funcs->config)
comp->funcs->config(comp, w, h, vrefresh, bpc);
comp->funcs->config(comp, w, h, vrefresh, bpc, cmdq_pkt);
}
static inline void mtk_ddp_comp_start(struct mtk_ddp_comp *comp) @@ -152,17 +160,19 @@ static inline unsigned int mtk_ddp_comp_layer_nr(struct mtk_ddp_comp *comp) }
static inline void mtk_ddp_comp_layer_on(struct mtk_ddp_comp *comp,
unsigned int idx)
unsigned int idx,
struct cmdq_pkt *cmdq_pkt)
{ if (comp->funcs && comp->funcs->layer_on)
comp->funcs->layer_on(comp, idx);
comp->funcs->layer_on(comp, idx, cmdq_pkt);
}
static inline void mtk_ddp_comp_layer_off(struct mtk_ddp_comp *comp,
unsigned int idx)
unsigned int idx,
struct cmdq_pkt *cmdq_pkt)
{ if (comp->funcs && comp->funcs->layer_off)
comp->funcs->layer_off(comp, idx);
comp->funcs->layer_off(comp, idx, cmdq_pkt);
}
static inline int mtk_ddp_comp_layer_check(struct mtk_ddp_comp *comp, @@ -176,17 +186,19 @@ static inline int mtk_ddp_comp_layer_check(struct mtk_ddp_comp *comp,
static inline void mtk_ddp_comp_layer_config(struct mtk_ddp_comp *comp, unsigned int idx,
struct mtk_plane_state *state)
struct mtk_plane_state *state,
struct cmdq_pkt *cmdq_pkt)
{ if (comp->funcs && comp->funcs->layer_config)
comp->funcs->layer_config(comp, idx, state);
comp->funcs->layer_config(comp, idx, state, cmdq_pkt);
}
static inline void mtk_ddp_gamma_set(struct mtk_ddp_comp *comp,
struct drm_crtc_state *state)
struct drm_crtc_state *state,
struct cmdq_pkt *cmdq_pkt)
{ if (comp->funcs && comp->funcs->gamma_set)
comp->funcs->gamma_set(comp, state);
comp->funcs->gamma_set(comp, state, cmdq_pkt);
}
static inline void mtk_ddp_comp_bgclr_in_on(struct mtk_ddp_comp *comp) @@ -209,6 +221,13 @@ int mtk_ddp_comp_init(struct device *dev, struct device_node *comp_node, int mtk_ddp_comp_register(struct drm_device *drm, struct mtk_ddp_comp *comp); void mtk_ddp_comp_unregister(struct drm_device *drm, struct mtk_ddp_comp *comp); void mtk_dither_set(struct mtk_ddp_comp *comp, unsigned int bpc,
unsigned int CFG);
unsigned int CFG, struct cmdq_pkt *cmdq_pkt);
+enum mtk_ddp_comp_type mtk_ddp_comp_get_type(enum mtk_ddp_comp_id comp_id); +void mtk_ddp_write(struct cmdq_pkt *cmdq_pkt, unsigned int value,
struct mtk_ddp_comp *comp, unsigned int offset);
+void mtk_ddp_write_relaxed(struct cmdq_pkt *cmdq_pkt, unsigned int value,
struct mtk_ddp_comp *comp, unsigned int offset);
+void mtk_ddp_write_mask(struct cmdq_pkt *cmdq_pkt, unsigned int value,
struct mtk_ddp_comp *comp, unsigned int offset,
unsigned int mask);
#endif /* MTK_DRM_DDP_COMP_H */
Unlike other SoCs, MT8183 does not have "shadow" registers for performaing an atomic video mode set or page flip at vblank/vsync.
The CMDQ (Commend Queue) in MT8183 is used to help update all relevant display controller registers with critical time limation.
Signed-off-by: YT Shen yt.shen@mediatek.com Signed-off-by: CK Hu ck.hu@mediatek.com Signed-off-by: Philipp Zabel p.zabel@pengutronix.de Signed-off-by: Bibby Hsieh bibby.hsieh@mediatek.com Signed-off-by: Yongqiang Niu yongqiang.niu@mediatek.com --- drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 86 ++++++++++++++++++++- drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 31 ++++++++ 2 files changed, 113 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index fcf4e755e0bd..1b4e537ac3c1 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -12,6 +12,8 @@ #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> #include <drm/drm_vblank.h> +#include <linux/of_address.h> +#include <linux/soc/mediatek/mtk-cmdq.h>
#include "mtk_drm_drv.h" #include "mtk_drm_crtc.h" @@ -42,6 +44,9 @@ struct mtk_drm_crtc { unsigned int layer_nr; bool pending_planes;
+ struct cmdq_client *cmdq_client; + u32 cmdq_event; + void __iomem *config_regs; const struct mtk_mmsys_reg_data *mmsys_reg_data; struct mtk_disp_mutex *mutex; @@ -56,6 +61,11 @@ struct mtk_crtc_state { unsigned int pending_width; unsigned int pending_height; unsigned int pending_vrefresh; + struct cmdq_pkt *cmdq_handle; +}; + +struct mtk_cmdq_cb_data { + struct cmdq_pkt *cmdq_handle; };
static inline struct mtk_drm_crtc *to_mtk_crtc(struct drm_crtc *c) @@ -229,6 +239,46 @@ struct mtk_ddp_comp *mtk_drm_ddp_comp_for_plane(struct drm_crtc *crtc, return NULL; }
+#ifdef CONFIG_MTK_CMDQ +static void ddp_cmdq_cb(struct cmdq_cb_data data) +{ + struct mtk_cmdq_cb_data *cb_data = data.data; + + cmdq_pkt_destroy(cb_data->cmdq_handle); + kfree(cb_data); +} + +static void mtk_cmdq_acquire(struct drm_crtc *crtc) +{ + struct mtk_crtc_state *mtk_crtc_state = + to_mtk_crtc_state(crtc->state); + struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); + + mtk_crtc_state->cmdq_handle = + cmdq_pkt_create(mtk_crtc->cmdq_client, + PAGE_SIZE); + cmdq_pkt_clear_event(mtk_crtc_state->cmdq_handle, + mtk_crtc->cmdq_event); + cmdq_pkt_wfe(mtk_crtc_state->cmdq_handle, mtk_crtc->cmdq_event); +} + +static void mtk_cmdq_release(struct drm_crtc *crtc) +{ + struct mtk_crtc_state *mtk_crtc_state = + to_mtk_crtc_state(crtc->state); + struct mtk_cmdq_cb_data *cb_data; + + cb_data = kmalloc(sizeof(*cb_data), GFP_KERNEL); + if (!cb_data) { + DRM_DEV_ERROR(crtc->dev->dev, "Failed to alloc cb_data\n"); + return; + } + + cb_data->cmdq_handle = mtk_crtc_state->cmdq_handle; + cmdq_pkt_flush_async(mtk_crtc_state->cmdq_handle, + ddp_cmdq_cb, cb_data); +} +#endif static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc) { struct drm_crtc *crtc = &mtk_crtc->base; @@ -383,7 +433,8 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc) if (state->pending_config) { mtk_ddp_comp_config(comp, state->pending_width, state->pending_height, - state->pending_vrefresh, 0, NULL); + state->pending_vrefresh, 0, + state->cmdq_handle);
state->pending_config = false; } @@ -403,7 +454,8 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc)
if (comp) mtk_ddp_comp_layer_config(comp, local_layer, - plane_state, NULL); + plane_state, + state->cmdq_handle); plane_state->pending.config = false; } mtk_crtc->pending_planes = false; @@ -454,6 +506,13 @@ void mtk_drm_crtc_cursor_update(struct drm_crtc *crtc, struct drm_plane *plane, mtk_crtc_ddp_config(crtc); mtk_disp_mutex_release(mtk_crtc->mutex); } +#ifdef CONFIG_MTK_CMDQ + if (mtk_crtc->cmdq_client) { + mtk_cmdq_acquire(crtc); + mtk_crtc_ddp_config(crtc); + mtk_cmdq_release(crtc); + } +#endif mutex_unlock(&priv->hw_lock); }
@@ -570,6 +629,13 @@ static void mtk_drm_crtc_atomic_flush(struct drm_crtc *crtc, mtk_crtc_ddp_config(crtc); mtk_disp_mutex_release(mtk_crtc->mutex); } +#ifdef CONFIG_MTK_CMDQ + if (mtk_crtc->cmdq_client) { + mtk_cmdq_acquire(crtc); + mtk_crtc_ddp_config(crtc); + mtk_cmdq_release(crtc); + } +#endif }
static const struct drm_crtc_funcs mtk_crtc_funcs = { @@ -619,7 +685,7 @@ void mtk_crtc_ddp_irq(struct drm_crtc *crtc, struct mtk_ddp_comp *comp) struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); struct mtk_drm_private *priv = crtc->dev->dev_private;
- if (!priv->data->shadow_register) + if (!priv->data->shadow_register && !mtk_crtc->cmdq_client) mtk_crtc_ddp_config(crtc);
mtk_drm_finish_page_flip(mtk_crtc); @@ -761,6 +827,18 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev, drm_mode_crtc_set_gamma_size(&mtk_crtc->base, MTK_LUT_SIZE); drm_crtc_enable_color_mgmt(&mtk_crtc->base, 0, false, MTK_LUT_SIZE); priv->num_pipes++; - +#ifdef CONFIG_MTK_CMDQ + mtk_crtc->cmdq_client = + cmdq_mbox_create(dev, drm_crtc_index(&mtk_crtc->base), + 2000); + of_property_read_u32_index(dev->of_node, "mediatek,gce-events", + drm_crtc_index(&mtk_crtc->base), + &mtk_crtc->cmdq_event); + if (IS_ERR(mtk_crtc->cmdq_client)) { + dev_dbg(dev, "mtk_crtc %d failed to create mailbox client, writing register by CPU now\n", + drm_crtc_index(&mtk_crtc->base)); + mtk_crtc->cmdq_client = NULL; + } +#endif return 0; } diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c index 6d0f349ddf82..9cc12af2bc06 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c @@ -370,6 +370,9 @@ int mtk_ddp_comp_init(struct device *dev, struct device_node *node, const struct mtk_ddp_comp_funcs *funcs) { struct platform_device *comp_pdev; + struct resource res; + struct cmdq_client_reg *cmdq_reg; + int ret = 0;
if (comp_id < 0 || comp_id >= DDP_COMPONENT_ID_MAX) return -EINVAL; @@ -404,6 +407,34 @@ int mtk_ddp_comp_init(struct device *dev, struct device_node *node, } comp->dev = &comp_pdev->dev;
+#ifdef CONFIG_MTK_CMDQ + if (of_address_to_resource(node, 0, &res) != 0) { + dev_err(dev, "Missing reg in %s node\n", + node->full_name); + return -EINVAL; + } + comp->regs_pa = res.start; + + comp_pdev = of_find_device_by_node(node); + if (!comp_pdev) { + dev_warn(dev, "Waiting for component device %s\n", + node->full_name); + return -EPROBE_DEFER; + } + + cmdq_reg = kzalloc(sizeof(*cmdq_reg), GFP_KERNEL); + if (!cmdq_reg) + return -EINVAL; + + ret = cmdq_dev_get_client_reg(&comp_pdev->dev, cmdq_reg, 0); + if (ret != 0) + dev_dbg(&comp_pdev->dev, + "get mediatek,gce-client-reg fail!\n"); + else + comp->subsys = cmdq_reg->subsys; + + kfree(cmdq_reg); +#endif return 0; }
Hi, Bibby:
On Thu, 2019-11-28 at 10:42 +0800, Bibby Hsieh wrote:
Unlike other SoCs, MT8183 does not have "shadow" registers for performaing an atomic video mode set or page flip at vblank/vsync.
The CMDQ (Commend Queue) in MT8183 is used to help update all relevant display controller registers with critical time limation.
Signed-off-by: YT Shen yt.shen@mediatek.com Signed-off-by: CK Hu ck.hu@mediatek.com Signed-off-by: Philipp Zabel p.zabel@pengutronix.de Signed-off-by: Bibby Hsieh bibby.hsieh@mediatek.com Signed-off-by: Yongqiang Niu yongqiang.niu@mediatek.com
drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 86 ++++++++++++++++++++- drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 31 ++++++++ 2 files changed, 113 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index fcf4e755e0bd..1b4e537ac3c1 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -12,6 +12,8 @@ #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> #include <drm/drm_vblank.h> +#include <linux/of_address.h> +#include <linux/soc/mediatek/mtk-cmdq.h>
#include "mtk_drm_drv.h" #include "mtk_drm_crtc.h" @@ -42,6 +44,9 @@ struct mtk_drm_crtc { unsigned int layer_nr; bool pending_planes;
- struct cmdq_client *cmdq_client;
- u32 cmdq_event;
- void __iomem *config_regs; const struct mtk_mmsys_reg_data *mmsys_reg_data; struct mtk_disp_mutex *mutex;
@@ -56,6 +61,11 @@ struct mtk_crtc_state { unsigned int pending_width; unsigned int pending_height; unsigned int pending_vrefresh;
- struct cmdq_pkt *cmdq_handle;
+};
+struct mtk_cmdq_cb_data {
- struct cmdq_pkt *cmdq_handle;
};
static inline struct mtk_drm_crtc *to_mtk_crtc(struct drm_crtc *c) @@ -229,6 +239,46 @@ struct mtk_ddp_comp *mtk_drm_ddp_comp_for_plane(struct drm_crtc *crtc, return NULL; }
+#ifdef CONFIG_MTK_CMDQ +static void ddp_cmdq_cb(struct cmdq_cb_data data) +{
- struct mtk_cmdq_cb_data *cb_data = data.data;
- cmdq_pkt_destroy(cb_data->cmdq_handle);
- kfree(cb_data);
+}
+static void mtk_cmdq_acquire(struct drm_crtc *crtc) +{
- struct mtk_crtc_state *mtk_crtc_state =
to_mtk_crtc_state(crtc->state);
- struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
- mtk_crtc_state->cmdq_handle =
cmdq_pkt_create(mtk_crtc->cmdq_client,
PAGE_SIZE);
I would like to remove atomic feature in cmdq driver and drm driver could reuse the pkt. Please refer to [1] for detail.
[1] http://lists.infradead.org/pipermail/linux-mediatek/2019-January/016866.html
- cmdq_pkt_clear_event(mtk_crtc_state->cmdq_handle,
mtk_crtc->cmdq_event);
- cmdq_pkt_wfe(mtk_crtc_state->cmdq_handle, mtk_crtc->cmdq_event);
+}
+static void mtk_cmdq_release(struct drm_crtc *crtc) +{
- struct mtk_crtc_state *mtk_crtc_state =
to_mtk_crtc_state(crtc->state);
- struct mtk_cmdq_cb_data *cb_data;
- cb_data = kmalloc(sizeof(*cb_data), GFP_KERNEL);
- if (!cb_data) {
DRM_DEV_ERROR(crtc->dev->dev, "Failed to alloc cb_data\n");
return;
- }
- cb_data->cmdq_handle = mtk_crtc_state->cmdq_handle;
- cmdq_pkt_flush_async(mtk_crtc_state->cmdq_handle,
ddp_cmdq_cb, cb_data);
+} +#endif static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc) { struct drm_crtc *crtc = &mtk_crtc->base; @@ -383,7 +433,8 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc) if (state->pending_config) { mtk_ddp_comp_config(comp, state->pending_width, state->pending_height,
state->pending_vrefresh, 0, NULL);
state->pending_vrefresh, 0,
state->cmdq_handle);
state->pending_config = false; }
@@ -403,7 +454,8 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc)
if (comp) mtk_ddp_comp_layer_config(comp, local_layer,
plane_state, NULL);
plane_state,
} mtk_crtc->pending_planes = false;state->cmdq_handle); plane_state->pending.config = false;
@@ -454,6 +506,13 @@ void mtk_drm_crtc_cursor_update(struct drm_crtc *crtc, struct drm_plane *plane, mtk_crtc_ddp_config(crtc); mtk_disp_mutex_release(mtk_crtc->mutex); } +#ifdef CONFIG_MTK_CMDQ
- if (mtk_crtc->cmdq_client) {
mtk_cmdq_acquire(crtc);
mtk_crtc_ddp_config(crtc);
mtk_cmdq_release(crtc);
- }
+#endif mutex_unlock(&priv->hw_lock); }
@@ -570,6 +629,13 @@ static void mtk_drm_crtc_atomic_flush(struct drm_crtc *crtc, mtk_crtc_ddp_config(crtc); mtk_disp_mutex_release(mtk_crtc->mutex); } +#ifdef CONFIG_MTK_CMDQ
- if (mtk_crtc->cmdq_client) {
mtk_cmdq_acquire(crtc);
mtk_crtc_ddp_config(crtc);
mtk_cmdq_release(crtc);
- }
+#endif
This part is almost the same as the one in mtk_drm_crtc_cursor_update(), try to merge them.
}
static const struct drm_crtc_funcs mtk_crtc_funcs = { @@ -619,7 +685,7 @@ void mtk_crtc_ddp_irq(struct drm_crtc *crtc, struct mtk_ddp_comp *comp) struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); struct mtk_drm_private *priv = crtc->dev->dev_private;
- if (!priv->data->shadow_register)
if (!priv->data->shadow_register && !mtk_crtc->cmdq_client) mtk_crtc_ddp_config(crtc);
mtk_drm_finish_page_flip(mtk_crtc);
@@ -761,6 +827,18 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev, drm_mode_crtc_set_gamma_size(&mtk_crtc->base, MTK_LUT_SIZE); drm_crtc_enable_color_mgmt(&mtk_crtc->base, 0, false, MTK_LUT_SIZE); priv->num_pipes++;
+#ifdef CONFIG_MTK_CMDQ
- mtk_crtc->cmdq_client =
cmdq_mbox_create(dev, drm_crtc_index(&mtk_crtc->base),
2000);
- of_property_read_u32_index(dev->of_node, "mediatek,gce-events",
drm_crtc_index(&mtk_crtc->base),
&mtk_crtc->cmdq_event);
- if (IS_ERR(mtk_crtc->cmdq_client)) {
dev_dbg(dev, "mtk_crtc %d failed to create mailbox client, writing register by CPU now\n",
drm_crtc_index(&mtk_crtc->base));
mtk_crtc->cmdq_client = NULL;
- }
+#endif return 0; } diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c index 6d0f349ddf82..9cc12af2bc06 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c @@ -370,6 +370,9 @@ int mtk_ddp_comp_init(struct device *dev, struct device_node *node, const struct mtk_ddp_comp_funcs *funcs) { struct platform_device *comp_pdev;
struct resource res;
struct cmdq_client_reg *cmdq_reg;
int ret = 0;
if (comp_id < 0 || comp_id >= DDP_COMPONENT_ID_MAX) return -EINVAL;
@@ -404,6 +407,34 @@ int mtk_ddp_comp_init(struct device *dev, struct device_node *node, } comp->dev = &comp_pdev->dev;
+#ifdef CONFIG_MTK_CMDQ
- if (of_address_to_resource(node, 0, &res) != 0) {
dev_err(dev, "Missing reg in %s node\n",
node->full_name);
return -EINVAL;
- }
- comp->regs_pa = res.start;
- comp_pdev = of_find_device_by_node(node);
- if (!comp_pdev) {
dev_warn(dev, "Waiting for component device %s\n",
node->full_name);
return -EPROBE_DEFER;
- }
- cmdq_reg = kzalloc(sizeof(*cmdq_reg), GFP_KERNEL);
- if (!cmdq_reg)
return -EINVAL;
- ret = cmdq_dev_get_client_reg(&comp_pdev->dev, cmdq_reg, 0);
- if (ret != 0)
dev_dbg(&comp_pdev->dev,
"get mediatek,gce-client-reg fail!\n");
- else
comp->subsys = cmdq_reg->subsys;
- kfree(cmdq_reg);
+#endif
I would like to move this part to the patch "drm/mediatek: support CMDQ interface in ddp component".
Regards, CK
return 0; }
On Tue, 2019-12-03 at 09:38 +0800, CK Hu wrote:
Hi, Bibby:
On Thu, 2019-11-28 at 10:42 +0800, Bibby Hsieh wrote:
Unlike other SoCs, MT8183 does not have "shadow" registers for performaing an atomic video mode set or page flip at vblank/vsync.
The CMDQ (Commend Queue) in MT8183 is used to help update all relevant display controller registers with critical time limation.
Signed-off-by: YT Shen yt.shen@mediatek.com Signed-off-by: CK Hu ck.hu@mediatek.com Signed-off-by: Philipp Zabel p.zabel@pengutronix.de Signed-off-by: Bibby Hsieh bibby.hsieh@mediatek.com Signed-off-by: Yongqiang Niu yongqiang.niu@mediatek.com
drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 86 ++++++++++++++++++++- drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 31 ++++++++ 2 files changed, 113 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index fcf4e755e0bd..1b4e537ac3c1 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -12,6 +12,8 @@ #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> #include <drm/drm_vblank.h> +#include <linux/of_address.h> +#include <linux/soc/mediatek/mtk-cmdq.h>
#include "mtk_drm_drv.h" #include "mtk_drm_crtc.h" @@ -42,6 +44,9 @@ struct mtk_drm_crtc { unsigned int layer_nr; bool pending_planes;
- struct cmdq_client *cmdq_client;
- u32 cmdq_event;
- void __iomem *config_regs; const struct mtk_mmsys_reg_data *mmsys_reg_data; struct mtk_disp_mutex *mutex;
@@ -56,6 +61,11 @@ struct mtk_crtc_state { unsigned int pending_width; unsigned int pending_height; unsigned int pending_vrefresh;
- struct cmdq_pkt *cmdq_handle;
+};
+struct mtk_cmdq_cb_data {
- struct cmdq_pkt *cmdq_handle;
};
static inline struct mtk_drm_crtc *to_mtk_crtc(struct drm_crtc *c) @@ -229,6 +239,46 @@ struct mtk_ddp_comp *mtk_drm_ddp_comp_for_plane(struct drm_crtc *crtc, return NULL; }
+#ifdef CONFIG_MTK_CMDQ +static void ddp_cmdq_cb(struct cmdq_cb_data data) +{
- struct mtk_cmdq_cb_data *cb_data = data.data;
- cmdq_pkt_destroy(cb_data->cmdq_handle);
- kfree(cb_data);
+}
+static void mtk_cmdq_acquire(struct drm_crtc *crtc) +{
- struct mtk_crtc_state *mtk_crtc_state =
to_mtk_crtc_state(crtc->state);
- struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
- mtk_crtc_state->cmdq_handle =
cmdq_pkt_create(mtk_crtc->cmdq_client,
PAGE_SIZE);
I would like to remove atomic feature in cmdq driver and drm driver could reuse the pkt. Please refer to [1] for detail.
[1] http://lists.infradead.org/pipermail/linux-mediatek/2019-January/016866.html
Hi, CK,
Thanks for all the comments. I will change them in my next version.
About the atomic feature removing, I think we already made note at here. Let's fix them after the atomic feature removed really.
Bibby
- cmdq_pkt_clear_event(mtk_crtc_state->cmdq_handle,
mtk_crtc->cmdq_event);
- cmdq_pkt_wfe(mtk_crtc_state->cmdq_handle, mtk_crtc->cmdq_event);
+}
+static void mtk_cmdq_release(struct drm_crtc *crtc) +{
- struct mtk_crtc_state *mtk_crtc_state =
to_mtk_crtc_state(crtc->state);
- struct mtk_cmdq_cb_data *cb_data;
- cb_data = kmalloc(sizeof(*cb_data), GFP_KERNEL);
- if (!cb_data) {
DRM_DEV_ERROR(crtc->dev->dev, "Failed to alloc cb_data\n");
return;
- }
- cb_data->cmdq_handle = mtk_crtc_state->cmdq_handle;
- cmdq_pkt_flush_async(mtk_crtc_state->cmdq_handle,
ddp_cmdq_cb, cb_data);
+} +#endif static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc) { struct drm_crtc *crtc = &mtk_crtc->base; @@ -383,7 +433,8 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc) if (state->pending_config) { mtk_ddp_comp_config(comp, state->pending_width, state->pending_height,
state->pending_vrefresh, 0, NULL);
state->pending_vrefresh, 0,
state->cmdq_handle);
state->pending_config = false; }
@@ -403,7 +454,8 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc)
if (comp) mtk_ddp_comp_layer_config(comp, local_layer,
plane_state, NULL);
plane_state,
} mtk_crtc->pending_planes = false;state->cmdq_handle); plane_state->pending.config = false;
@@ -454,6 +506,13 @@ void mtk_drm_crtc_cursor_update(struct drm_crtc *crtc, struct drm_plane *plane, mtk_crtc_ddp_config(crtc); mtk_disp_mutex_release(mtk_crtc->mutex); } +#ifdef CONFIG_MTK_CMDQ
- if (mtk_crtc->cmdq_client) {
mtk_cmdq_acquire(crtc);
mtk_crtc_ddp_config(crtc);
mtk_cmdq_release(crtc);
- }
+#endif mutex_unlock(&priv->hw_lock); }
@@ -570,6 +629,13 @@ static void mtk_drm_crtc_atomic_flush(struct drm_crtc *crtc, mtk_crtc_ddp_config(crtc); mtk_disp_mutex_release(mtk_crtc->mutex); } +#ifdef CONFIG_MTK_CMDQ
- if (mtk_crtc->cmdq_client) {
mtk_cmdq_acquire(crtc);
mtk_crtc_ddp_config(crtc);
mtk_cmdq_release(crtc);
- }
+#endif
This part is almost the same as the one in mtk_drm_crtc_cursor_update(), try to merge them.
}
static const struct drm_crtc_funcs mtk_crtc_funcs = { @@ -619,7 +685,7 @@ void mtk_crtc_ddp_irq(struct drm_crtc *crtc, struct mtk_ddp_comp *comp) struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); struct mtk_drm_private *priv = crtc->dev->dev_private;
- if (!priv->data->shadow_register)
if (!priv->data->shadow_register && !mtk_crtc->cmdq_client) mtk_crtc_ddp_config(crtc);
mtk_drm_finish_page_flip(mtk_crtc);
@@ -761,6 +827,18 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev, drm_mode_crtc_set_gamma_size(&mtk_crtc->base, MTK_LUT_SIZE); drm_crtc_enable_color_mgmt(&mtk_crtc->base, 0, false, MTK_LUT_SIZE); priv->num_pipes++;
+#ifdef CONFIG_MTK_CMDQ
- mtk_crtc->cmdq_client =
cmdq_mbox_create(dev, drm_crtc_index(&mtk_crtc->base),
2000);
- of_property_read_u32_index(dev->of_node, "mediatek,gce-events",
drm_crtc_index(&mtk_crtc->base),
&mtk_crtc->cmdq_event);
- if (IS_ERR(mtk_crtc->cmdq_client)) {
dev_dbg(dev, "mtk_crtc %d failed to create mailbox client, writing register by CPU now\n",
drm_crtc_index(&mtk_crtc->base));
mtk_crtc->cmdq_client = NULL;
- }
+#endif return 0; } diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c index 6d0f349ddf82..9cc12af2bc06 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c @@ -370,6 +370,9 @@ int mtk_ddp_comp_init(struct device *dev, struct device_node *node, const struct mtk_ddp_comp_funcs *funcs) { struct platform_device *comp_pdev;
struct resource res;
struct cmdq_client_reg *cmdq_reg;
int ret = 0;
if (comp_id < 0 || comp_id >= DDP_COMPONENT_ID_MAX) return -EINVAL;
@@ -404,6 +407,34 @@ int mtk_ddp_comp_init(struct device *dev, struct device_node *node, } comp->dev = &comp_pdev->dev;
+#ifdef CONFIG_MTK_CMDQ
- if (of_address_to_resource(node, 0, &res) != 0) {
dev_err(dev, "Missing reg in %s node\n",
node->full_name);
return -EINVAL;
- }
- comp->regs_pa = res.start;
- comp_pdev = of_find_device_by_node(node);
- if (!comp_pdev) {
dev_warn(dev, "Waiting for component device %s\n",
node->full_name);
return -EPROBE_DEFER;
- }
- cmdq_reg = kzalloc(sizeof(*cmdq_reg), GFP_KERNEL);
- if (!cmdq_reg)
return -EINVAL;
- ret = cmdq_dev_get_client_reg(&comp_pdev->dev, cmdq_reg, 0);
- if (ret != 0)
dev_dbg(&comp_pdev->dev,
"get mediatek,gce-client-reg fail!\n");
- else
comp->subsys = cmdq_reg->subsys;
- kfree(cmdq_reg);
+#endif
I would like to move this part to the patch "drm/mediatek: support CMDQ interface in ddp component".
Regards, CK
return 0; }
Hi, Bibby:
On Tue, 2019-12-03 at 13:58 +0800, Bibby Hsieh wrote:
On Tue, 2019-12-03 at 09:38 +0800, CK Hu wrote:
Hi, Bibby:
On Thu, 2019-11-28 at 10:42 +0800, Bibby Hsieh wrote:
Unlike other SoCs, MT8183 does not have "shadow" registers for performaing an atomic video mode set or page flip at vblank/vsync.
The CMDQ (Commend Queue) in MT8183 is used to help update all relevant display controller registers with critical time limation.
Signed-off-by: YT Shen yt.shen@mediatek.com Signed-off-by: CK Hu ck.hu@mediatek.com Signed-off-by: Philipp Zabel p.zabel@pengutronix.de Signed-off-by: Bibby Hsieh bibby.hsieh@mediatek.com Signed-off-by: Yongqiang Niu yongqiang.niu@mediatek.com
drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 86 ++++++++++++++++++++- drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 31 ++++++++ 2 files changed, 113 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index fcf4e755e0bd..1b4e537ac3c1 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -12,6 +12,8 @@ #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> #include <drm/drm_vblank.h> +#include <linux/of_address.h> +#include <linux/soc/mediatek/mtk-cmdq.h>
#include "mtk_drm_drv.h" #include "mtk_drm_crtc.h" @@ -42,6 +44,9 @@ struct mtk_drm_crtc { unsigned int layer_nr; bool pending_planes;
- struct cmdq_client *cmdq_client;
- u32 cmdq_event;
- void __iomem *config_regs; const struct mtk_mmsys_reg_data *mmsys_reg_data; struct mtk_disp_mutex *mutex;
@@ -56,6 +61,11 @@ struct mtk_crtc_state { unsigned int pending_width; unsigned int pending_height; unsigned int pending_vrefresh;
- struct cmdq_pkt *cmdq_handle;
+};
+struct mtk_cmdq_cb_data {
- struct cmdq_pkt *cmdq_handle;
};
static inline struct mtk_drm_crtc *to_mtk_crtc(struct drm_crtc *c) @@ -229,6 +239,46 @@ struct mtk_ddp_comp *mtk_drm_ddp_comp_for_plane(struct drm_crtc *crtc, return NULL; }
+#ifdef CONFIG_MTK_CMDQ +static void ddp_cmdq_cb(struct cmdq_cb_data data) +{
- struct mtk_cmdq_cb_data *cb_data = data.data;
- cmdq_pkt_destroy(cb_data->cmdq_handle);
- kfree(cb_data);
+}
+static void mtk_cmdq_acquire(struct drm_crtc *crtc) +{
- struct mtk_crtc_state *mtk_crtc_state =
to_mtk_crtc_state(crtc->state);
- struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
- mtk_crtc_state->cmdq_handle =
cmdq_pkt_create(mtk_crtc->cmdq_client,
PAGE_SIZE);
I would like to remove atomic feature in cmdq driver and drm driver could reuse the pkt. Please refer to [1] for detail.
[1] http://lists.infradead.org/pipermail/linux-mediatek/2019-January/016866.html
Hi, CK,
Thanks for all the comments. I will change them in my next version.
About the atomic feature removing, I think we already made note at here. Let's fix them after the atomic feature removed really.
Removing atomic feature would modify the device tree, and I'm worry that device tree setting could not be modified at that time. I think we could modify the device tree now because there no client use cmdq in upstream.
Regards, CK
Bibby
- cmdq_pkt_clear_event(mtk_crtc_state->cmdq_handle,
mtk_crtc->cmdq_event);
- cmdq_pkt_wfe(mtk_crtc_state->cmdq_handle, mtk_crtc->cmdq_event);
+}
+static void mtk_cmdq_release(struct drm_crtc *crtc) +{
- struct mtk_crtc_state *mtk_crtc_state =
to_mtk_crtc_state(crtc->state);
- struct mtk_cmdq_cb_data *cb_data;
- cb_data = kmalloc(sizeof(*cb_data), GFP_KERNEL);
- if (!cb_data) {
DRM_DEV_ERROR(crtc->dev->dev, "Failed to alloc cb_data\n");
return;
- }
- cb_data->cmdq_handle = mtk_crtc_state->cmdq_handle;
- cmdq_pkt_flush_async(mtk_crtc_state->cmdq_handle,
ddp_cmdq_cb, cb_data);
+} +#endif static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc) { struct drm_crtc *crtc = &mtk_crtc->base; @@ -383,7 +433,8 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc) if (state->pending_config) { mtk_ddp_comp_config(comp, state->pending_width, state->pending_height,
state->pending_vrefresh, 0, NULL);
state->pending_vrefresh, 0,
state->cmdq_handle);
state->pending_config = false; }
@@ -403,7 +454,8 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc)
if (comp) mtk_ddp_comp_layer_config(comp, local_layer,
plane_state, NULL);
plane_state,
} mtk_crtc->pending_planes = false;state->cmdq_handle); plane_state->pending.config = false;
@@ -454,6 +506,13 @@ void mtk_drm_crtc_cursor_update(struct drm_crtc *crtc, struct drm_plane *plane, mtk_crtc_ddp_config(crtc); mtk_disp_mutex_release(mtk_crtc->mutex); } +#ifdef CONFIG_MTK_CMDQ
- if (mtk_crtc->cmdq_client) {
mtk_cmdq_acquire(crtc);
mtk_crtc_ddp_config(crtc);
mtk_cmdq_release(crtc);
- }
+#endif mutex_unlock(&priv->hw_lock); }
@@ -570,6 +629,13 @@ static void mtk_drm_crtc_atomic_flush(struct drm_crtc *crtc, mtk_crtc_ddp_config(crtc); mtk_disp_mutex_release(mtk_crtc->mutex); } +#ifdef CONFIG_MTK_CMDQ
- if (mtk_crtc->cmdq_client) {
mtk_cmdq_acquire(crtc);
mtk_crtc_ddp_config(crtc);
mtk_cmdq_release(crtc);
- }
+#endif
This part is almost the same as the one in mtk_drm_crtc_cursor_update(), try to merge them.
}
static const struct drm_crtc_funcs mtk_crtc_funcs = { @@ -619,7 +685,7 @@ void mtk_crtc_ddp_irq(struct drm_crtc *crtc, struct mtk_ddp_comp *comp) struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); struct mtk_drm_private *priv = crtc->dev->dev_private;
- if (!priv->data->shadow_register)
if (!priv->data->shadow_register && !mtk_crtc->cmdq_client) mtk_crtc_ddp_config(crtc);
mtk_drm_finish_page_flip(mtk_crtc);
@@ -761,6 +827,18 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev, drm_mode_crtc_set_gamma_size(&mtk_crtc->base, MTK_LUT_SIZE); drm_crtc_enable_color_mgmt(&mtk_crtc->base, 0, false, MTK_LUT_SIZE); priv->num_pipes++;
+#ifdef CONFIG_MTK_CMDQ
- mtk_crtc->cmdq_client =
cmdq_mbox_create(dev, drm_crtc_index(&mtk_crtc->base),
2000);
- of_property_read_u32_index(dev->of_node, "mediatek,gce-events",
drm_crtc_index(&mtk_crtc->base),
&mtk_crtc->cmdq_event);
- if (IS_ERR(mtk_crtc->cmdq_client)) {
dev_dbg(dev, "mtk_crtc %d failed to create mailbox client, writing register by CPU now\n",
drm_crtc_index(&mtk_crtc->base));
mtk_crtc->cmdq_client = NULL;
- }
+#endif return 0; } diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c index 6d0f349ddf82..9cc12af2bc06 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c @@ -370,6 +370,9 @@ int mtk_ddp_comp_init(struct device *dev, struct device_node *node, const struct mtk_ddp_comp_funcs *funcs) { struct platform_device *comp_pdev;
struct resource res;
struct cmdq_client_reg *cmdq_reg;
int ret = 0;
if (comp_id < 0 || comp_id >= DDP_COMPONENT_ID_MAX) return -EINVAL;
@@ -404,6 +407,34 @@ int mtk_ddp_comp_init(struct device *dev, struct device_node *node, } comp->dev = &comp_pdev->dev;
+#ifdef CONFIG_MTK_CMDQ
- if (of_address_to_resource(node, 0, &res) != 0) {
dev_err(dev, "Missing reg in %s node\n",
node->full_name);
return -EINVAL;
- }
- comp->regs_pa = res.start;
- comp_pdev = of_find_device_by_node(node);
- if (!comp_pdev) {
dev_warn(dev, "Waiting for component device %s\n",
node->full_name);
return -EPROBE_DEFER;
- }
- cmdq_reg = kzalloc(sizeof(*cmdq_reg), GFP_KERNEL);
- if (!cmdq_reg)
return -EINVAL;
- ret = cmdq_dev_get_client_reg(&comp_pdev->dev, cmdq_reg, 0);
- if (ret != 0)
dev_dbg(&comp_pdev->dev,
"get mediatek,gce-client-reg fail!\n");
- else
comp->subsys = cmdq_reg->subsys;
- kfree(cmdq_reg);
+#endif
I would like to move this part to the patch "drm/mediatek: support CMDQ interface in ddp component".
Regards, CK
return 0; }
dri-devel@lists.freedesktop.org