lkml.org 
[lkml]   [2019]   [Dec]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v3 6/6] drm/mediatek: apply CMDQ control flow
    Date
    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 | 80 ++++++++++++++++++++++++-
    1 file changed, 77 insertions(+), 3 deletions(-)

    diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
    index 9f1ff2f3f104..9340346e2727 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;
    @@ -59,6 +64,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)
    @@ -233,6 +243,47 @@ 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;
    @@ -393,7 +444,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;
    }
    @@ -413,7 +465,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;
    @@ -452,6 +505,13 @@ static void mtk_drm_crtc_hw_config(struct mtk_drm_crtc *mtk_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
    mutex_unlock(&mtk_crtc->hw_lock);
    }

    @@ -528,6 +588,7 @@ static void mtk_drm_crtc_atomic_disable(struct drm_crtc *crtc,
    mtk_crtc->pending_planes = true;

    /* Wait for planes to be disabled */
    + mtk_drm_crtc_hw_config(mtk_crtc);
    drm_crtc_wait_one_vblank(crtc);

    drm_crtc_vblank_off(crtc);
    @@ -619,7 +680,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);
    @@ -763,5 +824,18 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
    priv->num_pipes++;
    mutex_init(&mtk_crtc->hw_lock);

    +#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;
    }
    --
    2.18.0
    \
     
     \ /
      Last update: 2019-12-04 10:45    [W:6.542 / U:0.024 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site