From bce9936a0d7f6570aaa64a41e6ff902716aabfa6 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 29 Apr 2015 01:11:57 +0300 Subject: [PATCH 01/10] drm: rcar-du: Document the rcar_du_crtc structure Document the structure fields using kerneldoc. Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_crtc.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h index 5d9aa9b33769..4b95d9d08c49 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h @@ -22,6 +22,20 @@ struct rcar_du_group; +/** + * struct rcar_du_crtc - the CRTC, representing a DU superposition processor + * @crtc: base DRM CRTC + * @clock: the CRTC functional clock + * @extclock: external pixel dot clock (optional) + * @mmio_offset: offset of the CRTC registers in the DU MMIO block + * @index: CRTC software and hardware index + * @started: whether the CRTC has been started and is running + * @event: event to post when the pending page flip completes + * @flip_wait: wait queue used to signal page flip completion + * @outputs: bitmask of the outputs (enum rcar_du_output) driven by this CRTC + * @enabled: whether the CRTC is enabled, used to control system resume + * @group: CRTC group this CRTC belongs to + */ struct rcar_du_crtc { struct drm_crtc crtc; From 0855c6827f822b51b2b4fc86d1085f47463cb5c9 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 29 Apr 2015 00:12:40 +0300 Subject: [PATCH 02/10] drm: rcar-du: Document the rcar_du_plane_state structure Document the structure fields using kerneldoc. Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_plane.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/rcar-du/rcar_du_plane.h index abff0ebeb195..2beb67acdb38 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h @@ -46,11 +46,20 @@ struct rcar_du_planes { struct drm_property *zpos; }; +/** + * struct rcar_du_plane_state - Driver-specific plane state + * @state: base DRM plane state + * @format: information about the pixel format used by the plane + * @hwindex: 0-based hardware plane index, -1 means unused + * @alpha: value of the plane alpha property + * @colorkey: value of the plane colorkey property + * @zpos: value of the plane zpos property + */ struct rcar_du_plane_state { struct drm_plane_state state; const struct rcar_du_format_info *format; - int hwindex; /* 0-based, -1 means unused */ + int hwindex; unsigned int alpha; unsigned int colorkey; From 9f6aee952b18d9910912d7cedae9bd26bd901ac3 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 28 Apr 2015 23:59:29 +0300 Subject: [PATCH 03/10] drm: rcar-du: Move properties from rcar_du_planes to rcar_du_device The plane property objects are instantiated once per CRTC group, while they should be instantiated once globally for the device. Fix this and move them to the rcar_du_device structure. Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_drv.h | 6 ++++ drivers/gpu/drm/rcar-du/rcar_du_kms.c | 29 ++++++++++++++++ drivers/gpu/drm/rcar-du/rcar_du_plane.c | 46 +++++++------------------ drivers/gpu/drm/rcar-du/rcar_du_plane.h | 4 --- 4 files changed, 47 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h index c7c538dd2e68..9f34fc86436a 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h @@ -83,6 +83,12 @@ struct rcar_du_device { struct rcar_du_group groups[RCAR_DU_MAX_GROUPS]; + struct { + struct drm_property *alpha; + struct drm_property *colorkey; + struct drm_property *zpos; + } props; + unsigned int dpad0_source; struct rcar_du_lvdsenc *lvds[RCAR_DU_MAX_LVDS]; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index 93117f159a3b..5fd6f8c07ec2 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -648,6 +648,31 @@ static int rcar_du_encoders_init(struct rcar_du_device *rcdu) return num_encoders; } +static int rcar_du_properties_init(struct rcar_du_device *rcdu) +{ + rcdu->props.alpha = + drm_property_create_range(rcdu->ddev, 0, "alpha", 0, 255); + if (rcdu->props.alpha == NULL) + return -ENOMEM; + + /* The color key is expressed as an RGB888 triplet stored in a 32-bit + * integer in XRGB8888 format. Bit 24 is used as a flag to disable (0) + * or enable source color keying (1). + */ + rcdu->props.colorkey = + drm_property_create_range(rcdu->ddev, 0, "colorkey", + 0, 0x01ffffff); + if (rcdu->props.colorkey == NULL) + return -ENOMEM; + + rcdu->props.zpos = + drm_property_create_range(rcdu->ddev, 0, "zpos", 1, 7); + if (rcdu->props.zpos == NULL) + return -ENOMEM; + + return 0; +} + int rcar_du_modeset_init(struct rcar_du_device *rcdu) { static const unsigned int mmio_offsets[] = { @@ -672,6 +697,10 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu) rcdu->num_crtcs = rcdu->info->num_crtcs; + ret = rcar_du_properties_init(rcdu); + if (ret < 0) + return ret; + /* Initialize the groups. */ num_groups = DIV_ROUND_UP(rcdu->num_crtcs, 2); diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c index 210e5c3fd982..b5565417f673 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c @@ -328,14 +328,13 @@ static int rcar_du_plane_atomic_set_property(struct drm_plane *plane, uint64_t val) { struct rcar_du_plane_state *rstate = to_rcar_du_plane_state(state); - struct rcar_du_plane *rplane = to_rcar_plane(plane); - struct rcar_du_group *rgrp = rplane->group; + struct rcar_du_device *rcdu = to_rcar_plane(plane)->group->dev; - if (property == rgrp->planes.alpha) + if (property == rcdu->props.alpha) rstate->alpha = val; - else if (property == rgrp->planes.colorkey) + else if (property == rcdu->props.colorkey) rstate->colorkey = val; - else if (property == rgrp->planes.zpos) + else if (property == rcdu->props.zpos) rstate->zpos = val; else return -EINVAL; @@ -349,14 +348,13 @@ static int rcar_du_plane_atomic_get_property(struct drm_plane *plane, { const struct rcar_du_plane_state *rstate = container_of(state, const struct rcar_du_plane_state, state); - struct rcar_du_plane *rplane = to_rcar_plane(plane); - struct rcar_du_group *rgrp = rplane->group; + struct rcar_du_device *rcdu = to_rcar_plane(plane)->group->dev; - if (property == rgrp->planes.alpha) + if (property == rcdu->props.alpha) *val = rstate->alpha; - else if (property == rgrp->planes.colorkey) + else if (property == rcdu->props.colorkey) *val = rstate->colorkey; - else if (property == rgrp->planes.zpos) + else if (property == rcdu->props.zpos) *val = rstate->zpos; else return -EINVAL; @@ -399,27 +397,7 @@ int rcar_du_planes_init(struct rcar_du_group *rgrp) unsigned int i; int ret; - planes->alpha = - drm_property_create_range(rcdu->ddev, 0, "alpha", 0, 255); - if (planes->alpha == NULL) - return -ENOMEM; - - /* The color key is expressed as an RGB888 triplet stored in a 32-bit - * integer in XRGB8888 format. Bit 24 is used as a flag to disable (0) - * or enable source color keying (1). - */ - planes->colorkey = - drm_property_create_range(rcdu->ddev, 0, "colorkey", - 0, 0x01ffffff); - if (planes->colorkey == NULL) - return -ENOMEM; - - planes->zpos = - drm_property_create_range(rcdu->ddev, 0, "zpos", 1, 7); - if (planes->zpos == NULL) - return -ENOMEM; - - /* Create one primary plane per in this group CRTC and seven overlay + /* Create one primary plane per CRTC in this group and seven overlay * planes. */ num_crtcs = min(rcdu->num_crtcs - 2 * rgrp->index, 2U); @@ -448,12 +426,12 @@ int rcar_du_planes_init(struct rcar_du_group *rgrp) continue; drm_object_attach_property(&plane->plane.base, - planes->alpha, 255); + rcdu->props.alpha, 255); drm_object_attach_property(&plane->plane.base, - planes->colorkey, + rcdu->props.colorkey, RCAR_DU_COLORKEY_NONE); drm_object_attach_property(&plane->plane.base, - planes->zpos, 1); + rcdu->props.zpos, 1); } return 0; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/rcar-du/rcar_du_plane.h index 2beb67acdb38..6b17b1f4f414 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h @@ -40,10 +40,6 @@ static inline struct rcar_du_plane *to_rcar_plane(struct drm_plane *plane) struct rcar_du_planes { struct rcar_du_plane planes[RCAR_DU_NUM_KMS_PLANES]; - - struct drm_property *alpha; - struct drm_property *colorkey; - struct drm_property *zpos; }; /** From 99caede11d84af4c0a16fd07f7d7ce9de94f6109 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 29 Apr 2015 00:05:56 +0300 Subject: [PATCH 04/10] drm: rcar-du: Embed rcar_du_planes structure into rcar_du_group The rcar_du_planes structure contains a single field and is only instantiated in the rcar_du_group structure. Embed it directly and remove the rcar_du_planes structure. Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 10 +++++----- drivers/gpu/drm/rcar-du/rcar_du_group.h | 2 +- drivers/gpu/drm/rcar-du/rcar_du_kms.c | 6 +++--- drivers/gpu/drm/rcar-du/rcar_du_plane.c | 3 +-- drivers/gpu/drm/rcar-du/rcar_du_plane.h | 4 ---- 5 files changed, 10 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 7d0b8ef9bea2..b5f66b78cbb2 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -213,8 +213,8 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc) u32 dptsr = 0; u32 dspr = 0; - for (i = 0; i < ARRAY_SIZE(rcrtc->group->planes.planes); ++i) { - struct rcar_du_plane *plane = &rcrtc->group->planes.planes[i]; + for (i = 0; i < ARRAY_SIZE(rcrtc->group->planes); ++i) { + struct rcar_du_plane *plane = &rcrtc->group->planes[i]; unsigned int j; if (plane->plane.state->crtc != &rcrtc->crtc) @@ -427,8 +427,8 @@ void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc) rcar_du_crtc_start(rcrtc); /* Commit the planes state. */ - for (i = 0; i < ARRAY_SIZE(rcrtc->group->planes.planes); ++i) { - struct rcar_du_plane *plane = &rcrtc->group->planes.planes[i]; + for (i = 0; i < ARRAY_SIZE(rcrtc->group->planes); ++i) { + struct rcar_du_plane *plane = &rcrtc->group->planes[i]; if (plane->plane.state->crtc != &rcrtc->crtc) continue; @@ -592,7 +592,7 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index) rcrtc->enabled = false; ret = drm_crtc_init_with_planes(rcdu->ddev, crtc, - &rgrp->planes.planes[index % 2].plane, + &rgrp->planes[index % 2].plane, NULL, &crtc_funcs); if (ret < 0) return ret; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.h b/drivers/gpu/drm/rcar-du/rcar_du_group.h index ed36433fbe84..ea02bb02f3e1 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_group.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.h @@ -40,7 +40,7 @@ struct rcar_du_group { struct mutex lock; - struct rcar_du_planes planes; + struct rcar_du_plane planes[RCAR_DU_NUM_KMS_PLANES]; }; u32 rcar_du_group_read(struct rcar_du_group *rgrp, u32 reg); diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index 5fd6f8c07ec2..4012afacab5f 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -291,7 +291,7 @@ static int rcar_du_atomic_check(struct drm_device *dev, * plane(s) as freed. */ if (!plane_state->format) { - index = plane - plane->group->planes.planes; + index = plane - plane->group->planes; group_freed_planes[plane->group->index] |= 1 << index; plane_state->hwindex = -1; continue; @@ -304,7 +304,7 @@ static int rcar_du_atomic_check(struct drm_device *dev, groups |= 1 << plane->group->index; needs_realloc = true; - index = plane - plane->group->planes.planes; + index = plane - plane->group->planes; group_freed_planes[plane->group->index] |= 1 << index; plane_state->hwindex = -1; } @@ -327,7 +327,7 @@ static int rcar_du_atomic_check(struct drm_device *dev, unsigned int used_planes = 0; for (i = 0; i < RCAR_DU_NUM_KMS_PLANES; ++i) { - struct rcar_du_plane *plane = &group->planes.planes[i]; + struct rcar_du_plane *plane = &group->planes[i]; struct rcar_du_plane_state *plane_state; struct drm_plane_state *s; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c index b5565417f673..99fefcaf6597 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c @@ -389,7 +389,6 @@ static const uint32_t formats[] = { int rcar_du_planes_init(struct rcar_du_group *rgrp) { - struct rcar_du_planes *planes = &rgrp->planes; struct rcar_du_device *rcdu = rgrp->dev; unsigned int num_planes; unsigned int num_crtcs; @@ -409,7 +408,7 @@ int rcar_du_planes_init(struct rcar_du_group *rgrp) enum drm_plane_type type = i < num_crtcs ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY; - struct rcar_du_plane *plane = &planes->planes[i]; + struct rcar_du_plane *plane = &rgrp->planes[i]; plane->group = rgrp; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/rcar-du/rcar_du_plane.h index 6b17b1f4f414..d1fb9b16a060 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h @@ -38,10 +38,6 @@ static inline struct rcar_du_plane *to_rcar_plane(struct drm_plane *plane) return container_of(plane, struct rcar_du_plane, plane); } -struct rcar_du_planes { - struct rcar_du_plane planes[RCAR_DU_NUM_KMS_PLANES]; -}; - /** * struct rcar_du_plane_state - Driver-specific plane state * @state: base DRM plane state From ec69a40645c829fcec613b437f72451205ff601f Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 29 Apr 2015 00:48:17 +0300 Subject: [PATCH 05/10] drm: rcar-du: Rename to_rcar_du_plane_state to to_rcar_plane_state All other cast functions are named without using "du", make the plane state cast consistent with them. Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 6 +++--- drivers/gpu/drm/rcar-du/rcar_du_kms.c | 8 ++++---- drivers/gpu/drm/rcar-du/rcar_du_plane.c | 16 ++++++++-------- drivers/gpu/drm/rcar-du/rcar_du_plane.h | 2 +- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index b5f66b78cbb2..15f8d145a133 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -195,13 +195,13 @@ void rcar_du_crtc_route_output(struct drm_crtc *crtc, static unsigned int plane_zpos(struct rcar_du_plane *plane) { - return to_rcar_du_plane_state(plane->plane.state)->zpos; + return to_rcar_plane_state(plane->plane.state)->zpos; } static const struct rcar_du_format_info * plane_format(struct rcar_du_plane *plane) { - return to_rcar_du_plane_state(plane->plane.state)->format; + return to_rcar_plane_state(plane->plane.state)->format; } static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc) @@ -234,7 +234,7 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc) for (i = 0; i < num_planes; ++i) { struct rcar_du_plane *plane = planes[i]; struct drm_plane_state *state = plane->plane.state; - unsigned int index = to_rcar_du_plane_state(state)->hwindex; + unsigned int index = to_rcar_plane_state(state)->hwindex; prio -= 4; dspr |= (index + 1) << prio; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index 4012afacab5f..14d457047c40 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -221,7 +221,7 @@ static bool rcar_du_plane_needs_realloc(struct rcar_du_plane *plane, { const struct rcar_du_format_info *cur_format; - cur_format = to_rcar_du_plane_state(plane->plane.state)->format; + cur_format = to_rcar_plane_state(plane->plane.state)->format; /* Lowering the number of planes doesn't strictly require reallocation * as the extra hardware plane will be freed when committing, but doing @@ -284,7 +284,7 @@ static int rcar_du_atomic_check(struct drm_device *dev, continue; plane = to_rcar_plane(state->planes[i]); - plane_state = to_rcar_du_plane_state(state->plane_states[i]); + plane_state = to_rcar_plane_state(state->plane_states[i]); /* If the plane is being disabled we don't need to go through * the full reallocation procedure. Just mark the hardware @@ -345,7 +345,7 @@ static int rcar_du_atomic_check(struct drm_device *dev, if (group_freed_planes[index] & (1 << i)) continue; - plane_state = to_rcar_du_plane_state(plane->plane.state); + plane_state = to_rcar_plane_state(plane->plane.state); used_planes |= rcar_du_plane_hwmask(plane_state); } @@ -363,7 +363,7 @@ static int rcar_du_atomic_check(struct drm_device *dev, continue; plane = to_rcar_plane(state->planes[i]); - plane_state = to_rcar_du_plane_state(state->plane_states[i]); + plane_state = to_rcar_plane_state(state->plane_states[i]); /* Skip planes that are being disabled or don't need to be * reallocated. diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c index 99fefcaf6597..d3ed528fa56d 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c @@ -45,7 +45,7 @@ static void rcar_du_plane_write(struct rcar_du_group *rgrp, static void rcar_du_plane_setup_fb(struct rcar_du_plane *plane) { struct rcar_du_plane_state *state = - to_rcar_du_plane_state(plane->plane.state); + to_rcar_plane_state(plane->plane.state); struct drm_framebuffer *fb = plane->plane.state->fb; struct rcar_du_group *rgrp = plane->group; unsigned int src_x = state->state.src_x >> 16; @@ -109,7 +109,7 @@ static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane, unsigned int index) { struct rcar_du_plane_state *state = - to_rcar_du_plane_state(plane->plane.state); + to_rcar_plane_state(plane->plane.state); struct rcar_du_group *rgrp = plane->group; u32 colorkey; u32 pnmr; @@ -172,7 +172,7 @@ static void __rcar_du_plane_setup(struct rcar_du_plane *plane, unsigned int index) { struct rcar_du_plane_state *state = - to_rcar_du_plane_state(plane->plane.state); + to_rcar_plane_state(plane->plane.state); struct rcar_du_group *rgrp = plane->group; u32 ddcr2 = PnDDCR2_CODE; u32 ddcr4; @@ -222,7 +222,7 @@ static void __rcar_du_plane_setup(struct rcar_du_plane *plane, void rcar_du_plane_setup(struct rcar_du_plane *plane) { struct rcar_du_plane_state *state = - to_rcar_du_plane_state(plane->plane.state); + to_rcar_plane_state(plane->plane.state); __rcar_du_plane_setup(plane, state->hwindex); if (state->format->planes == 2) @@ -234,7 +234,7 @@ void rcar_du_plane_setup(struct rcar_du_plane *plane) static int rcar_du_plane_atomic_check(struct drm_plane *plane, struct drm_plane_state *state) { - struct rcar_du_plane_state *rstate = to_rcar_du_plane_state(state); + struct rcar_du_plane_state *rstate = to_rcar_plane_state(state); struct rcar_du_plane *rplane = to_rcar_plane(plane); struct rcar_du_device *rcdu = rplane->group->dev; @@ -302,7 +302,7 @@ rcar_du_plane_atomic_duplicate_state(struct drm_plane *plane) struct rcar_du_plane_state *state; struct rcar_du_plane_state *copy; - state = to_rcar_du_plane_state(plane->state); + state = to_rcar_plane_state(plane->state); copy = kmemdup(state, sizeof(*state), GFP_KERNEL); if (copy == NULL) return NULL; @@ -319,7 +319,7 @@ static void rcar_du_plane_atomic_destroy_state(struct drm_plane *plane, if (state->fb) drm_framebuffer_unreference(state->fb); - kfree(to_rcar_du_plane_state(state)); + kfree(to_rcar_plane_state(state)); } static int rcar_du_plane_atomic_set_property(struct drm_plane *plane, @@ -327,7 +327,7 @@ static int rcar_du_plane_atomic_set_property(struct drm_plane *plane, struct drm_property *property, uint64_t val) { - struct rcar_du_plane_state *rstate = to_rcar_du_plane_state(state); + struct rcar_du_plane_state *rstate = to_rcar_plane_state(state); struct rcar_du_device *rcdu = to_rcar_plane(plane)->group->dev; if (property == rcdu->props.alpha) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/rcar-du/rcar_du_plane.h index d1fb9b16a060..9732bff1911b 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h @@ -59,7 +59,7 @@ struct rcar_du_plane_state { }; static inline struct rcar_du_plane_state * -to_rcar_du_plane_state(struct drm_plane_state *state) +to_rcar_plane_state(struct drm_plane_state *state) { return container_of(state, struct rcar_du_plane_state, state); } From 08058611958bc161b1de991b494373b8bce56e6b Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 25 Feb 2015 22:31:52 +0200 Subject: [PATCH 06/10] drm: rcar-du: Add plane allocation debugging Plane allocation is a complex process, add debugging statements to help finding out what could might wrong. Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_kms.c | 38 ++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index 14d457047c40..ade135008e98 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -286,11 +286,16 @@ static int rcar_du_atomic_check(struct drm_device *dev, plane = to_rcar_plane(state->planes[i]); plane_state = to_rcar_plane_state(state->plane_states[i]); + dev_dbg(rcdu->dev, "%s: checking plane (%u,%u)\n", __func__, + plane->group->index, plane - plane->group->planes); + /* If the plane is being disabled we don't need to go through * the full reallocation procedure. Just mark the hardware * plane(s) as freed. */ if (!plane_state->format) { + dev_dbg(rcdu->dev, "%s: plane is being disabled\n", + __func__); index = plane - plane->group->planes; group_freed_planes[plane->group->index] |= 1 << index; plane_state->hwindex = -1; @@ -301,6 +306,8 @@ static int rcar_du_atomic_check(struct drm_device *dev, * mark the hardware plane(s) as free. */ if (rcar_du_plane_needs_realloc(plane, plane_state)) { + dev_dbg(rcdu->dev, "%s: plane needs reallocation\n", + __func__); groups |= 1 << plane->group->index; needs_realloc = true; @@ -326,6 +333,9 @@ static int rcar_du_atomic_check(struct drm_device *dev, struct rcar_du_group *group = &rcdu->groups[index]; unsigned int used_planes = 0; + dev_dbg(rcdu->dev, "%s: finding free planes for group %u\n", + __func__, index); + for (i = 0; i < RCAR_DU_NUM_KMS_PLANES; ++i) { struct rcar_du_plane *plane = &group->planes[i]; struct rcar_du_plane_state *plane_state; @@ -342,15 +352,31 @@ static int rcar_du_atomic_check(struct drm_device *dev, * above. Use the local freed planes list to check for * that condition instead. */ - if (group_freed_planes[index] & (1 << i)) + if (group_freed_planes[index] & (1 << i)) { + dev_dbg(rcdu->dev, + "%s: plane (%u,%u) has been freed, skipping\n", + __func__, plane->group->index, + plane - plane->group->planes); continue; + } plane_state = to_rcar_plane_state(plane->plane.state); used_planes |= rcar_du_plane_hwmask(plane_state); + + dev_dbg(rcdu->dev, + "%s: plane (%u,%u) uses %u hwplanes (index %d)\n", + __func__, plane->group->index, + plane - plane->group->planes, + plane_state->format ? + plane_state->format->planes : 0, + plane_state->hwindex); } group_free_planes[index] = 0xff & ~used_planes; groups &= ~(1 << index); + + dev_dbg(rcdu->dev, "%s: group %u free planes mask 0x%02x\n", + __func__, index, group_free_planes[index]); } /* Reallocate hardware planes for each plane that needs it. */ @@ -365,6 +391,9 @@ static int rcar_du_atomic_check(struct drm_device *dev, plane = to_rcar_plane(state->planes[i]); plane_state = to_rcar_plane_state(state->plane_states[i]); + dev_dbg(rcdu->dev, "%s: allocating plane (%u,%u)\n", __func__, + plane->group->index, plane - plane->group->planes); + /* Skip planes that are being disabled or don't need to be * reallocated. */ @@ -380,10 +409,17 @@ static int rcar_du_atomic_check(struct drm_device *dev, return idx; } + dev_dbg(rcdu->dev, "%s: allocated %u hwplanes (index %u)\n", + __func__, plane_state->format->planes, idx); + plane_state->hwindex = idx; group_free_planes[plane->group->index] &= ~rcar_du_plane_hwmask(plane_state); + + dev_dbg(rcdu->dev, "%s: group %u free planes mask 0x%02x\n", + __func__, plane->group->index, + group_free_planes[plane->group->index]); } return 0; From 2a57e9b5af2b96c45d8c73d34416e5dfa5dd38d9 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 28 Apr 2015 18:01:45 +0300 Subject: [PATCH 07/10] drm: rcar-du: Keep plane to CRTC associations when disabling a plane Changing the plane to CRTC associations requires restarting the CRTC group, creating visible flicker. Mitigate the issue by changing plane association only when a plane becomes enabled, not when it get disabled. Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 48 ++++++++++++++----------- drivers/gpu/drm/rcar-du/rcar_du_group.c | 6 ++++ drivers/gpu/drm/rcar-du/rcar_du_group.h | 4 ++- 3 files changed, 37 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 15f8d145a133..620a2c51185c 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -208,9 +208,10 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc) { struct rcar_du_plane *planes[RCAR_DU_NUM_HW_PLANES]; unsigned int num_planes = 0; + unsigned int dptsr_planes; + unsigned int hwplanes = 0; unsigned int prio = 0; unsigned int i; - u32 dptsr = 0; u32 dspr = 0; for (i = 0; i < ARRAY_SIZE(rcrtc->group->planes); ++i) { @@ -238,37 +239,44 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc) prio -= 4; dspr |= (index + 1) << prio; - dptsr |= DPTSR_PnDK(index) | DPTSR_PnTS(index); + hwplanes |= 1 << index; if (plane_format(plane)->planes == 2) { index = (index + 1) % 8; prio -= 4; dspr |= (index + 1) << prio; - dptsr |= DPTSR_PnDK(index) | DPTSR_PnTS(index); + hwplanes |= 1 << index; } } - /* Select display timing and dot clock generator 2 for planes associated - * with superposition controller 2. + /* Update the planes to display timing and dot clock generator + * associations. + * + * Updating the DPTSR register requires restarting the CRTC group, + * resulting in visible flicker. To mitigate the issue only update the + * association if needed by enabled planes. Planes being disabled will + * keep their current association. + * + * To mitigate the issue further we could pre-associate planes with + * CRTCs, either with a fixed 4/4 split, or through a module parameter. */ - if (rcrtc->index % 2) { - /* The DPTSR register is updated when the display controller is - * stopped. We thus need to restart the DU. Once again, sorry - * for the flicker. One way to mitigate the issue would be to - * pre-associate planes with CRTCs (either with a fixed 4/4 - * split, or through a module parameter). Flicker would then - * occur only if we need to break the pre-association. - */ - mutex_lock(&rcrtc->group->lock); - if (rcar_du_group_read(rcrtc->group, DPTSR) != dptsr) { - rcar_du_group_write(rcrtc->group, DPTSR, dptsr); - if (rcrtc->group->used_crtcs) - rcar_du_group_restart(rcrtc->group); - } - mutex_unlock(&rcrtc->group->lock); + mutex_lock(&rcrtc->group->lock); + + dptsr_planes = rcrtc->index % 2 ? rcrtc->group->dptsr_planes | hwplanes + : rcrtc->group->dptsr_planes & ~hwplanes; + + if (dptsr_planes != rcrtc->group->dptsr_planes) { + rcar_du_group_write(rcrtc->group, DPTSR, + (dptsr_planes << 16) | dptsr_planes); + rcrtc->group->dptsr_planes = dptsr_planes; + + if (rcrtc->group->used_crtcs) + rcar_du_group_restart(rcrtc->group); } + mutex_unlock(&rcrtc->group->lock); + rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR, dspr); } diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c index 1bdc0ee0c248..7fd39a7d91c8 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c @@ -85,6 +85,12 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp) * superposition 0 to DU0 pins. DU1 pins will be configured dynamically. */ rcar_du_group_write(rgrp, DORCR, DORCR_PG1D_DS1 | DORCR_DPRS); + + /* Apply planes to CRTCs association. */ + mutex_lock(&rgrp->lock); + rcar_du_group_write(rgrp, DPTSR, (rgrp->dptsr_planes << 16) | + rgrp->dptsr_planes); + mutex_unlock(&rgrp->lock); } /* diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.h b/drivers/gpu/drm/rcar-du/rcar_du_group.h index ea02bb02f3e1..4f6c37c8d336 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_group.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.h @@ -27,7 +27,8 @@ struct rcar_du_device; * @index: group index * @use_count: number of users of the group (rcar_du_group_(get|put)) * @used_crtcs: number of CRTCs currently in use - * @lock: protects the DPTSR register + * @lock: protects the dptsr_planes field and the DPTSR register + * @dptsr_planes: bitmask of planes driven by dot-clock and timing generator 1 * @planes: planes handled by the group */ struct rcar_du_group { @@ -39,6 +40,7 @@ struct rcar_du_group { unsigned int used_crtcs; struct mutex lock; + unsigned int dptsr_planes; struct rcar_du_plane planes[RCAR_DU_NUM_KMS_PLANES]; }; From c8af99b60421c184cab1c3a849debce1463ec792 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 29 Apr 2015 00:51:01 +0300 Subject: [PATCH 08/10] drm: rcar-du: Consider plane to CRTC associations in the plane allocator Hardware planes are driven by the timing generator of the CRTC they are associated to. Changing the association requires restarting the CRTC group that the plane belongs to, resulting in flicker on the other CRTC. To avoid flicker as much as possible, try to allocate planes first from the free planes already associated with the target CRTC. If allocation fails then fall back to allocation from all free planes. Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_kms.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index ade135008e98..2c6cf691d163 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -383,6 +383,8 @@ static int rcar_du_atomic_check(struct drm_device *dev, for (i = 0; i < dev->mode_config.num_total_plane; ++i) { struct rcar_du_plane_state *plane_state; struct rcar_du_plane *plane; + unsigned int crtc_planes; + unsigned int free; int idx; if (!state->planes[i]) @@ -401,8 +403,21 @@ static int rcar_du_atomic_check(struct drm_device *dev, !rcar_du_plane_needs_realloc(plane, plane_state)) continue; + /* Try to allocate the plane from the free planes currently + * associated with the target CRTC to avoid restarting the CRTC + * group and thus minimize flicker. If it fails fall back to + * allocating from all free planes. + */ + crtc_planes = to_rcar_crtc(plane_state->state.crtc)->index % 2 + ? plane->group->dptsr_planes + : ~plane->group->dptsr_planes; + free = group_free_planes[plane->group->index]; + idx = rcar_du_plane_hwalloc(plane_state->format->planes, - group_free_planes[plane->group->index]); + free & crtc_planes); + if (idx < 0) + idx = rcar_du_plane_hwalloc(plane_state->format->planes, + free); if (idx < 0) { dev_dbg(rcdu->dev, "%s: no available hardware plane\n", __func__); @@ -749,6 +764,11 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu) rgrp->mmio_offset = mmio_offsets[i]; rgrp->index = i; + /* Pre-associate all hardware planes with the first CRTC in the + * group. + */ + rgrp->dptsr_planes = 0; + ret = rcar_du_planes_init(rgrp); if (ret < 0) return ret; From fe6fbe9a024e149e4230a338700d24db8806183a Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 28 Apr 2015 17:36:33 +0300 Subject: [PATCH 09/10] drm: rcar-du: Store the number of CRTCs per group in the group structure The number of CRTCs in a group is only used to implement plane initialization for now, but is also needed to implement pre-association of planes to CRTCs. Store it in the group structure instead of computing it on demand. Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_group.h | 2 ++ drivers/gpu/drm/rcar-du/rcar_du_kms.c | 1 + drivers/gpu/drm/rcar-du/rcar_du_plane.c | 6 ++---- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.h b/drivers/gpu/drm/rcar-du/rcar_du_group.h index 4f6c37c8d336..7b414b31c3be 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_group.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.h @@ -25,6 +25,7 @@ struct rcar_du_device; * @dev: the DU device * @mmio_offset: registers offset in the device memory map * @index: group index + * @num_crtcs: number of CRTCs in this group (1 or 2) * @use_count: number of users of the group (rcar_du_group_(get|put)) * @used_crtcs: number of CRTCs currently in use * @lock: protects the dptsr_planes field and the DPTSR register @@ -36,6 +37,7 @@ struct rcar_du_group { unsigned int mmio_offset; unsigned int index; + unsigned int num_crtcs; unsigned int use_count; unsigned int used_crtcs; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index 2c6cf691d163..fec5f4d794da 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -763,6 +763,7 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu) rgrp->dev = rcdu; rgrp->mmio_offset = mmio_offsets[i]; rgrp->index = i; + rgrp->num_crtcs = min(rcdu->num_crtcs - 2 * i, 2U); /* Pre-associate all hardware planes with the first CRTC in the * group. diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c index d3ed528fa56d..3e30d84b798f 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c @@ -391,7 +391,6 @@ int rcar_du_planes_init(struct rcar_du_group *rgrp) { struct rcar_du_device *rcdu = rgrp->dev; unsigned int num_planes; - unsigned int num_crtcs; unsigned int crtcs; unsigned int i; int ret; @@ -399,13 +398,12 @@ int rcar_du_planes_init(struct rcar_du_group *rgrp) /* Create one primary plane per CRTC in this group and seven overlay * planes. */ - num_crtcs = min(rcdu->num_crtcs - 2 * rgrp->index, 2U); - num_planes = num_crtcs + 7; + num_planes = rgrp->num_crtcs + 7; crtcs = ((1 << rcdu->num_crtcs) - 1) & (3 << (2 * rgrp->index)); for (i = 0; i < num_planes; ++i) { - enum drm_plane_type type = i < num_crtcs + enum drm_plane_type type = i < rgrp->num_crtcs ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY; struct rcar_du_plane *plane = &rgrp->planes[i]; From 2610abfb3a72f6e5444a710b695c9460138f9326 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 28 Apr 2015 22:00:28 +0300 Subject: [PATCH 10/10] drm: rcar-du: Split planes pre-association 4/4 between CRTCs If we have more than one CRTCs in a group pre-associate planes 0-3 with CRTC 0 and planes 4-7 with CRTC 1 to minimize flicker occurring when the association is changed. The pre-association could be controlled by a module parameter if needed. Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 3 --- drivers/gpu/drm/rcar-du/rcar_du_kms.c | 7 ++++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 620a2c51185c..e6a32c4e4040 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -257,9 +257,6 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc) * resulting in visible flicker. To mitigate the issue only update the * association if needed by enabled planes. Planes being disabled will * keep their current association. - * - * To mitigate the issue further we could pre-associate planes with - * CRTCs, either with a fixed 4/4 split, or through a module parameter. */ mutex_lock(&rcrtc->group->lock); diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index fec5f4d794da..20859aae882e 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -765,10 +765,11 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu) rgrp->index = i; rgrp->num_crtcs = min(rcdu->num_crtcs - 2 * i, 2U); - /* Pre-associate all hardware planes with the first CRTC in the - * group. + /* If we have more than one CRTCs in this group pre-associate + * planes 0-3 with CRTC 0 and planes 4-7 with CRTC 1 to minimize + * flicker occurring when the association is changed. */ - rgrp->dptsr_planes = 0; + rgrp->dptsr_planes = rgrp->num_crtcs > 1 ? 0xf0 : 0; ret = rcar_du_planes_init(rgrp); if (ret < 0)