[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <b16761e5-be8a-42f6-8fc9-b84455716382@ideasonboard.com>
Date: Thu, 27 Mar 2025 13:18:58 +0200
From: Tomi Valkeinen <tomi.valkeinen@...asonboard.com>
To: Devarsh Thakkar <devarsht@...com>
Cc: praneeth@...com, vigneshr@...com, aradhya.bhatia@...ux.dev,
s-jain1@...com, r-donadkar@...com, j-choudhary@...com, h-shenoy@...com,
jyri.sarha@....fi, airlied@...il.com, maarten.lankhorst@...ux.intel.com,
mripard@...nel.org, tzimmermann@...e.de, dri-devel@...ts.freedesktop.org,
simona@...ll.ch, linux-kernel@...r.kernel.org, devicetree@...r.kernel.org,
robh@...nel.org, krzk+dt@...nel.org, conor+dt@...nel.org
Subject: Re: [PATCH v4 2/3] drm/tidss: Update infrastructure to support K3 DSS
cut-down versions
Hi,
On 26/03/2025 16:57, Devarsh Thakkar wrote:
> SoCs like AM62Lx support cut-down version of K3 DSS where although same
> register space is supported as in other K3 DSS supported SoCs such as
> AM65x, AM62x, AM62Ax but some of the resources such as planes and
> corresponding register spaces are truncated.
>
> For e.g. AM62Lx has only single VIDL pipeline supported, so corresponding
> register spaces for other video pipelines need to be skipped.
>
> To add a generic support for future SoCs where one or more video pipelines
> can get truncated from the parent register space, move the video plane
> related information to vid_info struct which will also have a field to
> indicate hardware index of each of the available video planes, so that
> driver only maps and programs those video pipes and skips the unavailable
> ones.
>
> While at it, also change the num_planes field in the features structure to
> num_vid so that all places in code which use vid_info structure are
> highlighted in the code.
>
> Signed-off-by: Devarsh Thakkar <devarsht@...com>
> ---
> V4:
> - Create vid_info struct only for instantiated planes
> - s/num_planes/num_vids
> - s/vid_lite/is_lite
> - Add hw_id member in vid_info struct and remove is_present
>
> V2->V3:
> - No change (patch introduced in V3)
>
> drivers/gpu/drm/tidss/tidss_crtc.c | 8 +-
> drivers/gpu/drm/tidss/tidss_dispc.c | 135 ++++++++++++++++++++--------
> drivers/gpu/drm/tidss/tidss_dispc.h | 11 ++-
> drivers/gpu/drm/tidss/tidss_kms.c | 2 +-
> drivers/gpu/drm/tidss/tidss_plane.c | 2 +-
> 5 files changed, 114 insertions(+), 44 deletions(-)
>
> diff --git a/drivers/gpu/drm/tidss/tidss_crtc.c b/drivers/gpu/drm/tidss/tidss_crtc.c
> index 94f8e3178df5..6db100b81482 100644
> --- a/drivers/gpu/drm/tidss/tidss_crtc.c
> +++ b/drivers/gpu/drm/tidss/tidss_crtc.c
> @@ -130,7 +130,7 @@ static void tidss_crtc_position_planes(struct tidss_device *tidss,
> !to_tidss_crtc_state(cstate)->plane_pos_changed)
> return;
>
> - for (layer = 0; layer < tidss->feat->num_planes; layer++) {
> + for (layer = 0; layer < tidss->feat->num_vids ; layer++) {
> struct drm_plane_state *pstate;
> struct drm_plane *plane;
> bool layer_active = false;
> @@ -271,9 +271,9 @@ static void tidss_crtc_atomic_disable(struct drm_crtc *crtc,
> * another videoport, the DSS will report sync lost issues. Disable all
> * the layers here as a work-around.
> */
> - for (u32 layer = 0; layer < tidss->feat->num_planes; layer++)
> - dispc_ovr_enable_layer(tidss->dispc, tcrtc->hw_videoport, layer,
> - false);
> + for (u32 layer = 0; layer < tidss->feat->num_vids; layer++)
> + dispc_ovr_enable_layer(tidss->dispc, tcrtc->hw_videoport,
> + tidss->feat->vid_info[layer].hw_id, false);
>
> dispc_vp_disable(tidss->dispc, tcrtc->hw_videoport);
>
> diff --git a/drivers/gpu/drm/tidss/tidss_dispc.c b/drivers/gpu/drm/tidss/tidss_dispc.c
> index cacb5f3d8085..6f0255d65a06 100644
> --- a/drivers/gpu/drm/tidss/tidss_dispc.c
> +++ b/drivers/gpu/drm/tidss/tidss_dispc.c
> @@ -103,9 +103,16 @@ const struct dispc_features dispc_k2g_feats = {
> },
> },
>
> - .num_planes = 1,
> - .vid_name = { "vid1" },
> - .vid_lite = { false },
> + .num_vids = 1,
> +
> + .vid_info = {
> + {
> + .name = "vid1",
> + .is_lite = false,
> + .hw_id = 0,
> + },
> + },
> +
> .vid_order = { 0 },
> };
>
> @@ -178,11 +185,22 @@ const struct dispc_features dispc_am65x_feats = {
> },
> },
>
> - .num_planes = 2,
> + .num_vids = 2,
> /* note: vid is plane_id 0 and vidl1 is plane_id 1 */
> - .vid_name = { "vid", "vidl1" },
> - .vid_lite = { false, true, },
> - .vid_order = { 1, 0 },
> + .vid_info = {
> + {
> + .name = "vid",
> + .is_lite = false,
> + .hw_id = 0,
> + },
> + {
> + .name = "vidl1",
> + .is_lite = true,
> + .hw_id = 1,
> + },
> + },
> +
> + .vid_order = {1, 0},
> };
>
> static const u16 tidss_j721e_common_regs[DISPC_COMMON_REG_TABLE_LEN] = {
> @@ -267,9 +285,32 @@ const struct dispc_features dispc_j721e_feats = {
> .gamma_type = TIDSS_GAMMA_10BIT,
> },
> },
> - .num_planes = 4,
> - .vid_name = { "vid1", "vidl1", "vid2", "vidl2" },
> - .vid_lite = { 0, 1, 0, 1, },
> +
> + .num_vids = 4,
> +
> + .vid_info = {
> + {
> + .name = "vid1",
> + .is_lite = false,
> + .hw_id = 0,
> + },
> + {
> + .name = "vidl1",
> + .is_lite = true,
> + .hw_id = 1,
> + },
> + {
> + .name = "vid2",
> + .is_lite = false,
> + .hw_id = 2,
> + },
> + {
> + .name = "vidl2",
> + .is_lite = true,
> + .hw_id = 3,
> + },
> + },
> +
> .vid_order = { 1, 3, 0, 2 },
> };
>
> @@ -315,11 +356,23 @@ const struct dispc_features dispc_am625_feats = {
> },
> },
>
> - .num_planes = 2,
> + .num_vids = 2,
> +
> /* note: vid is plane_id 0 and vidl1 is plane_id 1 */
> - .vid_name = { "vid", "vidl1" },
> - .vid_lite = { false, true, },
> - .vid_order = { 1, 0 },
> + .vid_info = {
> + {
> + .name = "vid",
> + .is_lite = false,
> + .hw_id = 0,
> + },
> + {
> + .name = "vidl1",
> + .is_lite = true,
> + .hw_id = 1,
> + }
> + },
> +
> + .vid_order = {1, 0},
> };
>
> const struct dispc_features dispc_am62a7_feats = {
> @@ -369,11 +422,22 @@ const struct dispc_features dispc_am62a7_feats = {
> },
> },
>
> - .num_planes = 2,
> - /* note: vid is plane_id 0 and vidl1 is plane_id 1 */
> - .vid_name = { "vid", "vidl1" },
> - .vid_lite = { false, true, },
> - .vid_order = { 1, 0 },
> + .num_vids = 2,
> +
> + .vid_info = {
> + {
> + .name = "vid",
> + .is_lite = false,
> + .hw_id = 0,
> + },
> + {
> + .name = "vidl1",
> + .is_lite = true,
> + .hw_id = 1,
> + }
> + },
> +
> + .vid_order = {1, 0},
> };
>
> static const u16 *dispc_common_regmap;
> @@ -788,7 +852,8 @@ void dispc_k3_clear_irqstatus(struct dispc_device *dispc, dispc_irq_t clearmask)
> if (clearmask & DSS_IRQ_VP_MASK(i))
> dispc_k3_vp_write_irqstatus(dispc, i, clearmask);
> }
> - for (i = 0; i < dispc->feat->num_planes; ++i) {
> +
> + for (i = 0; i < dispc->feat->num_vids; ++i) {
> if (clearmask & DSS_IRQ_PLANE_MASK(i))
> dispc_k3_vid_write_irqstatus(dispc, i, clearmask);
How did you test this?
With the changes in this patch, the index (i here) can really only be
used to reference the vid_info array. Any other use is most likely an
error, like here.
> }
> @@ -809,8 +874,8 @@ dispc_irq_t dispc_k3_read_and_clear_irqstatus(struct dispc_device *dispc)
> for (i = 0; i < dispc->feat->num_vps; ++i)
> status |= dispc_k3_vp_read_irqstatus(dispc, i);
>
> - for (i = 0; i < dispc->feat->num_planes; ++i)
> - status |= dispc_k3_vid_read_irqstatus(dispc, i);
> + for (i = 0; i < dispc->feat->num_vids; ++i)
> + status |= dispc_k3_vid_read_irqstatus(dispc, dispc->feat->vid_info[i].hw_id);
I think here and probably in almost all the cases it makes sense to use
a helper variable "hw_id".
>
> dispc_k3_clear_irqstatus(dispc, status);
>
> @@ -825,8 +890,8 @@ static dispc_irq_t dispc_k3_read_irqenable(struct dispc_device *dispc)
> for (i = 0; i < dispc->feat->num_vps; ++i)
> enable |= dispc_k3_vp_read_irqenable(dispc, i);
>
> - for (i = 0; i < dispc->feat->num_planes; ++i)
> - enable |= dispc_k3_vid_read_irqenable(dispc, i);
> + for (i = 0; i < dispc->feat->num_vids; ++i)
> + enable |= dispc_k3_vid_read_irqenable(dispc, dispc->feat->vid_info[i].hw_id);
>
> return enable;
> }
> @@ -849,10 +914,11 @@ static void dispc_k3_set_irqenable(struct dispc_device *dispc,
> main_enable |= BIT(i); /* VP IRQ */
> else
> main_disable |= BIT(i); /* VP IRQ */
> +
> }
>
> - for (i = 0; i < dispc->feat->num_planes; ++i) {
> - dispc_k3_vid_set_irqenable(dispc, i, mask);
> + for (i = 0; i < dispc->feat->num_vids; ++i) {
> + dispc_k3_vid_set_irqenable(dispc, dispc->feat->vid_info[i].hw_id, mask);
> if (mask & DSS_IRQ_PLANE_MASK(i))
> main_enable |= BIT(i + 4); /* VID IRQ */
And here.
> else
> @@ -861,7 +927,6 @@ static void dispc_k3_set_irqenable(struct dispc_device *dispc,
>
> if (main_enable)
> dispc_write(dispc, DISPC_IRQENABLE_SET, main_enable);
> -
> if (main_disable)
> dispc_write(dispc, DISPC_IRQENABLE_CLR, main_disable);
>
> @@ -2025,7 +2090,7 @@ int dispc_plane_check(struct dispc_device *dispc, u32 hw_plane,
> const struct drm_plane_state *state,
> u32 hw_videoport)
> {
> - bool lite = dispc->feat->vid_lite[hw_plane];
> + bool lite = dispc->feat->vid_info[hw_plane].is_lite;
> u32 fourcc = state->fb->format->format;
> bool need_scaling = state->src_w >> 16 != state->crtc_w ||
> state->src_h >> 16 != state->crtc_h;
> @@ -2096,7 +2161,7 @@ void dispc_plane_setup(struct dispc_device *dispc, u32 hw_plane,
> const struct drm_plane_state *state,
> u32 hw_videoport)
> {
> - bool lite = dispc->feat->vid_lite[hw_plane];
> + bool lite = dispc->feat->vid_info[hw_plane].is_lite;
> u32 fourcc = state->fb->format->format;
> u16 cpp = state->fb->format->cpp[0];
> u32 fb_width = state->fb->pitches[0] / cpp;
> @@ -2210,7 +2275,7 @@ static void dispc_k2g_plane_init(struct dispc_device *dispc)
> /* MFLAG_START = MFLAGNORMALSTARTMODE */
> REG_FLD_MOD(dispc, DISPC_GLOBAL_MFLAG_ATTRIBUTE, 0, 6, 6);
>
> - for (hw_plane = 0; hw_plane < dispc->feat->num_planes; hw_plane++) {
> + for (hw_plane = 0; hw_plane < dispc->feat->num_vids; hw_plane++) {
> u32 size = dispc_vid_get_fifo_size(dispc, hw_plane);
And here.
Maybe there's more, please check each of the cases where the index is used.
Tomi
> u32 thr_low, thr_high;
> u32 mflag_low, mflag_high;
> @@ -2226,7 +2291,7 @@ static void dispc_k2g_plane_init(struct dispc_device *dispc)
>
> dev_dbg(dispc->dev,
> "%s: bufsize %u, buf_threshold %u/%u, mflag threshold %u/%u preload %u\n",
> - dispc->feat->vid_name[hw_plane],
> + dispc->feat->vid_info[hw_plane].name,
> size,
> thr_high, thr_low,
> mflag_high, mflag_low,
> @@ -2265,7 +2330,7 @@ static void dispc_k3_plane_init(struct dispc_device *dispc)
> /* MFLAG_START = MFLAGNORMALSTARTMODE */
> REG_FLD_MOD(dispc, DISPC_GLOBAL_MFLAG_ATTRIBUTE, 0, 6, 6);
>
> - for (hw_plane = 0; hw_plane < dispc->feat->num_planes; hw_plane++) {
> + for (hw_plane = 0; hw_plane < dispc->feat->num_vids; hw_plane++) {
> u32 size = dispc_vid_get_fifo_size(dispc, hw_plane);
> u32 thr_low, thr_high;
> u32 mflag_low, mflag_high;
> @@ -2281,7 +2346,7 @@ static void dispc_k3_plane_init(struct dispc_device *dispc)
>
> dev_dbg(dispc->dev,
> "%s: bufsize %u, buf_threshold %u/%u, mflag threshold %u/%u preload %u\n",
> - dispc->feat->vid_name[hw_plane],
> + dispc->feat->vid_info[hw_plane].name,
> size,
> thr_high, thr_low,
> mflag_high, mflag_low,
> @@ -2898,8 +2963,8 @@ int dispc_init(struct tidss_device *tidss)
> if (r)
> return r;
>
> - for (i = 0; i < dispc->feat->num_planes; i++) {
> - r = dispc_iomap_resource(pdev, dispc->feat->vid_name[i],
> + for (i = 0; i < dispc->feat->num_vids; i++) {
> + r = dispc_iomap_resource(pdev, dispc->feat->vid_info[i].name,
> &dispc->base_vid[i]);
> if (r)
> return r;
> diff --git a/drivers/gpu/drm/tidss/tidss_dispc.h b/drivers/gpu/drm/tidss/tidss_dispc.h
> index 086327d51a90..72a0146e57d5 100644
> --- a/drivers/gpu/drm/tidss/tidss_dispc.h
> +++ b/drivers/gpu/drm/tidss/tidss_dispc.h
> @@ -46,6 +46,12 @@ struct dispc_features_scaling {
> u32 xinc_max;
> };
>
> +struct dispc_vid_info {
> + const char *name; /* Should match dt reg names */
> + u32 hw_id;
> + bool is_lite;
> +};
> +
> struct dispc_errata {
> bool i2000; /* DSS Does Not Support YUV Pixel Data Formats */
> };
> @@ -82,9 +88,8 @@ struct dispc_features {
> const char *vpclk_name[TIDSS_MAX_PORTS]; /* Should match dt clk names */
> const enum dispc_vp_bus_type vp_bus_type[TIDSS_MAX_PORTS];
> struct tidss_vp_feat vp_feat;
> - u32 num_planes;
> - const char *vid_name[TIDSS_MAX_PLANES]; /* Should match dt reg names */
> - bool vid_lite[TIDSS_MAX_PLANES];
> + u32 num_vids;
> + struct dispc_vid_info vid_info[TIDSS_MAX_PLANES];
> u32 vid_order[TIDSS_MAX_PLANES];
> };
>
> diff --git a/drivers/gpu/drm/tidss/tidss_kms.c b/drivers/gpu/drm/tidss/tidss_kms.c
> index f371518f8697..19432c08ec6b 100644
> --- a/drivers/gpu/drm/tidss/tidss_kms.c
> +++ b/drivers/gpu/drm/tidss/tidss_kms.c
> @@ -115,7 +115,7 @@ static int tidss_dispc_modeset_init(struct tidss_device *tidss)
>
> const struct dispc_features *feat = tidss->feat;
> u32 max_vps = feat->num_vps;
> - u32 max_planes = feat->num_planes;
> + u32 max_planes = feat->num_vids;
>
> struct pipe pipes[TIDSS_MAX_PORTS];
> u32 num_pipes = 0;
> diff --git a/drivers/gpu/drm/tidss/tidss_plane.c b/drivers/gpu/drm/tidss/tidss_plane.c
> index 116de124bddb..ff71370cad8b 100644
> --- a/drivers/gpu/drm/tidss/tidss_plane.c
> +++ b/drivers/gpu/drm/tidss/tidss_plane.c
> @@ -200,7 +200,7 @@ struct tidss_plane *tidss_plane_create(struct tidss_device *tidss,
> struct tidss_plane *tplane;
> enum drm_plane_type type;
> u32 possible_crtcs;
> - u32 num_planes = tidss->feat->num_planes;
> + u32 num_planes = tidss->feat->num_vids;
> u32 color_encodings = (BIT(DRM_COLOR_YCBCR_BT601) |
> BIT(DRM_COLOR_YCBCR_BT709));
> u32 color_ranges = (BIT(DRM_COLOR_YCBCR_FULL_RANGE) |
Powered by blists - more mailing lists