lkml.org 
[lkml]   [2023]   [May]   [10]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v6 3/6] drm: lcdif: Determine bus format and flags in ->atomic_check()
    Date
    Instead of determining LCDIF output bus format and bus flags in
    ->atomic_enable(), do that in ->atomic_check(). This is a
    preparation for the upcoming patch to check consistent bus format
    and bus flags across all first downstream bridges in ->atomic_check().
    New lcdif_crtc_state structure is introduced to cache bus format
    and bus flags states in ->atomic_check() so that they can be read
    in ->atomic_enable().

    Tested-by: Alexander Stein <alexander.stein@ew.tq-group.com>
    Reviewed-by: Alexander Stein <alexander.stein@ew.tq-group.com>
    Reviewed-by: Marek Vasut <marex@denx.de>
    Signed-off-by: Liu Ying <victor.liu@nxp.com>
    ---
    v5->v6:
    * Add Marek's R-b tag.
    * A slight change brought from the update in patch 2/6 to keep default
    MEDIA_BUS_FMT_RGB888_1X24 bus format.

    v4->v5:
    * Add Alexander's R-b and T-b tags.

    v3->v4:
    * Use 'new_{c,p}state' instead of 'new_{crtc,plane}_state'. (Alexander)
    * Simplify lcdif_crtc_reset() by calling lcdif_crtc_atomic_destroy_state().
    (Alexander)
    * Add '!crtc->state' check in lcdif_crtc_atomic_duplicate_state(). (Alexander)

    v2->v3:
    * No change.

    v1->v2:
    * Split from patch 2/2 in v1. (Marek, Alexander)
    * Add comment on the 'base' member of lcdif_crtc_state structure to
    note it should always be the first member. (Lothar)

    drivers/gpu/drm/mxsfb/lcdif_kms.c | 140 ++++++++++++++++++++++--------
    1 file changed, 102 insertions(+), 38 deletions(-)

    diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c b/drivers/gpu/drm/mxsfb/lcdif_kms.c
    index ba00a155d9b6..fab2253e4786 100644
    --- a/drivers/gpu/drm/mxsfb/lcdif_kms.c
    +++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c
    @@ -30,6 +30,18 @@
    #include "lcdif_drv.h"
    #include "lcdif_regs.h"

    +struct lcdif_crtc_state {
    + struct drm_crtc_state base; /* always be the first member */
    + u32 bus_format;
    + u32 bus_flags;
    +};
    +
    +static inline struct lcdif_crtc_state *
    +to_lcdif_crtc_state(struct drm_crtc_state *s)
    +{
    + return container_of(s, struct lcdif_crtc_state, base);
    +}
    +
    /* -----------------------------------------------------------------------------
    * CRTC
    */
    @@ -385,48 +397,75 @@ static void lcdif_reset_block(struct lcdif_drm_private *lcdif)
    readl(lcdif->base + LCDC_V8_CTRL);
    }

    -static void lcdif_crtc_mode_set_nofb(struct lcdif_drm_private *lcdif,
    - struct drm_plane_state *plane_state,
    - struct drm_bridge_state *bridge_state,
    - const u32 bus_format)
    +static void lcdif_crtc_mode_set_nofb(struct drm_crtc_state *crtc_state,
    + struct drm_plane_state *plane_state)
    {
    - struct drm_device *drm = lcdif->crtc.dev;
    - struct drm_display_mode *m = &lcdif->crtc.state->adjusted_mode;
    - u32 bus_flags = 0;
    -
    - if (lcdif->bridge->timings)
    - bus_flags = lcdif->bridge->timings->input_bus_flags;
    - else if (bridge_state)
    - bus_flags = bridge_state->input_bus_cfg.flags;
    + struct lcdif_crtc_state *lcdif_crtc_state = to_lcdif_crtc_state(crtc_state);
    + struct drm_device *drm = crtc_state->crtc->dev;
    + struct lcdif_drm_private *lcdif = to_lcdif_drm_private(drm);
    + struct drm_display_mode *m = &crtc_state->adjusted_mode;

    DRM_DEV_DEBUG_DRIVER(drm->dev, "Pixel clock: %dkHz (actual: %dkHz)\n",
    m->crtc_clock,
    (int)(clk_get_rate(lcdif->clk) / 1000));
    DRM_DEV_DEBUG_DRIVER(drm->dev, "Bridge bus_flags: 0x%08X\n",
    - bus_flags);
    + lcdif_crtc_state->bus_flags);
    DRM_DEV_DEBUG_DRIVER(drm->dev, "Mode flags: 0x%08X\n", m->flags);

    /* Mandatory eLCDIF reset as per the Reference Manual */
    lcdif_reset_block(lcdif);

    - lcdif_set_formats(lcdif, plane_state, bus_format);
    + lcdif_set_formats(lcdif, plane_state, lcdif_crtc_state->bus_format);

    - lcdif_set_mode(lcdif, bus_flags);
    + lcdif_set_mode(lcdif, lcdif_crtc_state->bus_flags);
    }

    static int lcdif_crtc_atomic_check(struct drm_crtc *crtc,
    struct drm_atomic_state *state)
    {
    + struct drm_device *drm = crtc->dev;
    + struct lcdif_drm_private *lcdif = to_lcdif_drm_private(drm);
    struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
    crtc);
    + struct lcdif_crtc_state *lcdif_crtc_state = to_lcdif_crtc_state(crtc_state);
    bool has_primary = crtc_state->plane_mask &
    drm_plane_mask(crtc->primary);
    + struct drm_bridge_state *bridge_state;
    + struct drm_bridge *bridge = lcdif->bridge;
    + int ret;

    /* The primary plane has to be enabled when the CRTC is active. */
    if (crtc_state->active && !has_primary)
    return -EINVAL;

    - return drm_atomic_add_affected_planes(state, crtc);
    + ret = drm_atomic_add_affected_planes(state, crtc);
    + if (ret)
    + return ret;
    +
    + bridge_state = drm_atomic_get_new_bridge_state(state, bridge);
    + if (!bridge_state)
    + lcdif_crtc_state->bus_format = MEDIA_BUS_FMT_FIXED;
    + else
    + lcdif_crtc_state->bus_format = bridge_state->input_bus_cfg.format;
    +
    + if (lcdif_crtc_state->bus_format == MEDIA_BUS_FMT_FIXED) {
    + dev_warn_once(drm->dev,
    + "Bridge does not provide bus format, assuming MEDIA_BUS_FMT_RGB888_1X24.\n"
    + "Please fix bridge driver by handling atomic_get_input_bus_fmts.\n");
    + lcdif_crtc_state->bus_format = MEDIA_BUS_FMT_RGB888_1X24;
    + } else if (!lcdif_crtc_state->bus_format) {
    + /* If all else fails, default to RGB888_1X24 */
    + lcdif_crtc_state->bus_format = MEDIA_BUS_FMT_RGB888_1X24;
    + }
    +
    + if (bridge->timings)
    + lcdif_crtc_state->bus_flags = bridge->timings->input_bus_flags;
    + else if (bridge_state)
    + lcdif_crtc_state->bus_flags = bridge_state->input_bus_cfg.flags;
    + else
    + lcdif_crtc_state->bus_flags = 0;
    +
    + return 0;
    }

    static void lcdif_crtc_atomic_flush(struct drm_crtc *crtc,
    @@ -458,35 +497,18 @@ static void lcdif_crtc_atomic_enable(struct drm_crtc *crtc,
    struct drm_atomic_state *state)
    {
    struct lcdif_drm_private *lcdif = to_lcdif_drm_private(crtc->dev);
    + struct drm_crtc_state *new_cstate = drm_atomic_get_new_crtc_state(state, crtc);
    struct drm_plane_state *new_pstate = drm_atomic_get_new_plane_state(state,
    crtc->primary);
    struct drm_display_mode *m = &lcdif->crtc.state->adjusted_mode;
    - struct drm_bridge_state *bridge_state = NULL;
    struct drm_device *drm = lcdif->drm;
    - u32 bus_format;
    dma_addr_t paddr;

    - bridge_state = drm_atomic_get_new_bridge_state(state, lcdif->bridge);
    - if (!bridge_state)
    - bus_format = MEDIA_BUS_FMT_FIXED;
    - else
    - bus_format = bridge_state->input_bus_cfg.format;
    -
    - if (bus_format == MEDIA_BUS_FMT_FIXED) {
    - dev_warn_once(drm->dev,
    - "Bridge does not provide bus format, assuming MEDIA_BUS_FMT_RGB888_1X24.\n"
    - "Please fix bridge driver by handling atomic_get_input_bus_fmts.\n");
    - bus_format = MEDIA_BUS_FMT_RGB888_1X24;
    - } else if (!bus_format) {
    - /* If all else fails, default to RGB888_1X24 */
    - bus_format = MEDIA_BUS_FMT_RGB888_1X24;
    - }
    -
    clk_set_rate(lcdif->clk, m->crtc_clock * 1000);

    pm_runtime_get_sync(drm->dev);

    - lcdif_crtc_mode_set_nofb(lcdif, new_pstate, bridge_state, bus_format);
    + lcdif_crtc_mode_set_nofb(new_cstate, new_pstate);

    /* Write cur_buf as well to avoid an initial corrupt frame */
    paddr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0);
    @@ -523,6 +545,48 @@ static void lcdif_crtc_atomic_disable(struct drm_crtc *crtc,
    pm_runtime_put_sync(drm->dev);
    }

    +static void lcdif_crtc_atomic_destroy_state(struct drm_crtc *crtc,
    + struct drm_crtc_state *state)
    +{
    + __drm_atomic_helper_crtc_destroy_state(state);
    + kfree(to_lcdif_crtc_state(state));
    +}
    +
    +static void lcdif_crtc_reset(struct drm_crtc *crtc)
    +{
    + struct lcdif_crtc_state *state;
    +
    + if (crtc->state)
    + lcdif_crtc_atomic_destroy_state(crtc, crtc->state);
    +
    + crtc->state = NULL;
    +
    + state = kzalloc(sizeof(*state), GFP_KERNEL);
    + if (state)
    + __drm_atomic_helper_crtc_reset(crtc, &state->base);
    +}
    +
    +static struct drm_crtc_state *
    +lcdif_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
    +{
    + struct lcdif_crtc_state *old = to_lcdif_crtc_state(crtc->state);
    + struct lcdif_crtc_state *new;
    +
    + if (WARN_ON(!crtc->state))
    + return NULL;
    +
    + new = kzalloc(sizeof(*new), GFP_KERNEL);
    + if (!new)
    + return NULL;
    +
    + __drm_atomic_helper_crtc_duplicate_state(crtc, &new->base);
    +
    + new->bus_format = old->bus_format;
    + new->bus_flags = old->bus_flags;
    +
    + return &new->base;
    +}
    +
    static int lcdif_crtc_enable_vblank(struct drm_crtc *crtc)
    {
    struct lcdif_drm_private *lcdif = to_lcdif_drm_private(crtc->dev);
    @@ -551,12 +615,12 @@ static const struct drm_crtc_helper_funcs lcdif_crtc_helper_funcs = {
    };

    static const struct drm_crtc_funcs lcdif_crtc_funcs = {
    - .reset = drm_atomic_helper_crtc_reset,
    + .reset = lcdif_crtc_reset,
    .destroy = drm_crtc_cleanup,
    .set_config = drm_atomic_helper_set_config,
    .page_flip = drm_atomic_helper_page_flip,
    - .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
    - .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
    + .atomic_duplicate_state = lcdif_crtc_atomic_duplicate_state,
    + .atomic_destroy_state = lcdif_crtc_atomic_destroy_state,
    .enable_vblank = lcdif_crtc_enable_vblank,
    .disable_vblank = lcdif_crtc_disable_vblank,
    };
    --
    2.37.1
    \
     
     \ /
      Last update: 2023-05-10 11:22    [W:3.416 / U:0.184 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site