Skip to content

Commit

Permalink
drm/mediatek: apply CMDQ control flow
Browse files Browse the repository at this point in the history
In some Mediatek SoC, there is no "shadow"
registers for performaing an atomic video mode
set or page flip at vblank/vsync.

The CMDQ (Commend Queue) 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: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Bibby Hsieh <bibby.hsieh@mediatek.com>
Signed-off-by: Yongqiang Niu <yongqiang.niu@mediatek.com>
Signed-off-by: CK Hu <ck.hu@mediatek.com>
  • Loading branch information
Bibby Hsieh authored and CK Hu committed Jan 9, 2020
1 parent d0afe37 commit 2f965be
Showing 1 changed file with 55 additions and 6 deletions.
61 changes: 55 additions & 6 deletions drivers/gpu/drm/mediatek/mtk_drm_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include <linux/clk.h>
#include <linux/pm_runtime.h>
#include <linux/soc/mediatek/mtk-cmdq.h>

#include <asm/barrier.h>
#include <soc/mediatek/smi.h>
Expand Down Expand Up @@ -44,6 +45,11 @@ struct mtk_drm_crtc {
bool pending_planes;
bool pending_async_planes;

#if IS_REACHABLE(CONFIG_MTK_CMDQ)
struct cmdq_client *cmdq_client;
u32 cmdq_event;
#endif

void __iomem *config_regs;
struct mtk_disp_mutex *mutex;
unsigned int ddp_comp_nr;
Expand Down Expand Up @@ -234,6 +240,13 @@ struct mtk_ddp_comp *mtk_drm_ddp_comp_for_plane(struct drm_crtc *crtc,
return NULL;
}

#if IS_REACHABLE(CONFIG_MTK_CMDQ)
static void ddp_cmdq_cb(struct cmdq_cb_data data)
{
cmdq_pkt_destroy(data.data);
}
#endif

static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc)
{
struct drm_crtc *crtc = &mtk_crtc->base;
Expand Down Expand Up @@ -367,7 +380,8 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_drm_crtc *mtk_crtc)
}
}

static void mtk_crtc_ddp_config(struct drm_crtc *crtc)
static void mtk_crtc_ddp_config(struct drm_crtc *crtc,
struct cmdq_pkt *cmdq_handle)
{
struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
struct mtk_crtc_state *state = to_mtk_crtc_state(mtk_crtc->base.state);
Expand All @@ -383,7 +397,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,
cmdq_handle);

state->pending_config = false;
}
Expand All @@ -403,7 +418,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,
cmdq_handle);
plane_state->pending.config = false;
}
mtk_crtc->pending_planes = false;
Expand All @@ -424,7 +440,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,
cmdq_handle);
plane_state->pending.async_config = false;
}
mtk_crtc->pending_async_planes = false;
Expand All @@ -433,6 +450,9 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc)

static void mtk_drm_crtc_hw_config(struct mtk_drm_crtc *mtk_crtc)
{
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
struct cmdq_pkt *cmdq_handle;
#endif
struct drm_crtc *crtc = &mtk_crtc->base;
struct mtk_drm_private *priv = crtc->dev->dev_private;
unsigned int pending_planes = 0, pending_async_planes = 0;
Expand Down Expand Up @@ -461,9 +481,18 @@ static void mtk_drm_crtc_hw_config(struct mtk_drm_crtc *mtk_crtc)

if (priv->data->shadow_register) {
mtk_disp_mutex_acquire(mtk_crtc->mutex);
mtk_crtc_ddp_config(crtc);
mtk_crtc_ddp_config(crtc, NULL);
mtk_disp_mutex_release(mtk_crtc->mutex);
}
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
if (mtk_crtc->cmdq_client) {
cmdq_handle = cmdq_pkt_create(mtk_crtc->cmdq_client, PAGE_SIZE);
cmdq_pkt_clear_event(cmdq_handle, mtk_crtc->cmdq_event);
cmdq_pkt_wfe(cmdq_handle, mtk_crtc->cmdq_event);
mtk_crtc_ddp_config(crtc, cmdq_handle);
cmdq_pkt_flush_async(cmdq_handle, ddp_cmdq_cb, cmdq_handle);
}
#endif
mutex_unlock(&mtk_crtc->hw_lock);
}

Expand Down Expand Up @@ -629,8 +658,12 @@ 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 IS_REACHABLE(CONFIG_MTK_CMDQ)
if (!priv->data->shadow_register && !mtk_crtc->cmdq_client)
#else
if (!priv->data->shadow_register)
mtk_crtc_ddp_config(crtc);
#endif
mtk_crtc_ddp_config(crtc, NULL);

mtk_drm_finish_page_flip(mtk_crtc);
}
Expand Down Expand Up @@ -772,5 +805,21 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
priv->num_pipes++;
mutex_init(&mtk_crtc->hw_lock);

#if IS_REACHABLE(CONFIG_MTK_CMDQ)
mtk_crtc->cmdq_client =
cmdq_mbox_create(dev, drm_crtc_index(&mtk_crtc->base),
2000);
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;
}
ret = of_property_read_u32_index(dev->of_node, "mediatek,gce-events",
drm_crtc_index(&mtk_crtc->base),
&mtk_crtc->cmdq_event);
if (ret)
dev_dbg(dev, "mtk_crtc %d failed to get mediatek,gce-events property\n",
drm_crtc_index(&mtk_crtc->base));
#endif
return 0;
}

0 comments on commit 2f965be

Please sign in to comment.