diff options
author | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2015-09-08 01:01:14 -0300 |
---|---|---|
committer | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2015-09-08 01:01:14 -0300 |
commit | e5fd91f1ef340da553f7a79da9540c3db711c937 (patch) | |
tree | b11842027dc6641da63f4bcc524f8678263304a3 /drivers/gpu/drm/rcar-du | |
parent | 2a9b0348e685a63d97486f6749622b61e9e3292f (diff) |
Linux-libre 4.2-gnu
Diffstat (limited to 'drivers/gpu/drm/rcar-du')
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 74 | ||||
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_du_crtc.h | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_du_drv.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_du_drv.h | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_du_group.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_du_group.h | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_du_kms.c | 136 | ||||
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_du_plane.c | 84 | ||||
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_du_plane.h | 21 |
9 files changed, 237 insertions, 116 deletions
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 7d0b8ef9b..65d6ba662 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -195,26 +195,27 @@ 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) { 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.planes); ++i) { - struct rcar_du_plane *plane = &rcrtc->group->planes.planes[i]; + for (i = 0; i < rcrtc->group->num_planes; ++i) { + struct rcar_du_plane *plane = &rcrtc->group->planes[i]; unsigned int j; if (plane->plane.state->crtc != &rcrtc->crtc) @@ -234,41 +235,45 @@ 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; - 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. */ - 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); } @@ -393,6 +398,19 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc) if (!rcrtc->started) return; + /* Disable all planes and wait for the change to take effect. This is + * required as the DSnPR registers are updated on vblank, and no vblank + * will occur once the CRTC is stopped. Disabling planes when starting + * the CRTC thus wouldn't be enough as it would start scanning out + * immediately from old frame buffers until the next vblank. + * + * This increases the CRTC stop delay, especially when multiple CRTCs + * are stopped in one operation as we now wait for one vblank per CRTC. + * Whether this can be improved needs to be researched. + */ + rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR, 0); + drm_crtc_wait_one_vblank(crtc); + /* Disable vertical blanking interrupt reporting. We first need to wait * for page flip completion before stopping the CRTC as userspace * expects page flips to eventually complete. @@ -427,8 +445,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 < rcrtc->group->num_planes; ++i) { + struct rcar_du_plane *plane = &rcrtc->group->planes[i]; if (plane->plane.state->crtc != &rcrtc->crtc) continue; @@ -592,7 +610,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_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h index 5d9aa9b33..4b95d9d08 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; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c index da1216a73..780ca1151 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c @@ -190,7 +190,7 @@ static int rcar_du_load(struct drm_device *dev, unsigned long flags) /* DRM/KMS objects */ ret = rcar_du_modeset_init(rcdu); if (ret < 0) { - dev_err(&pdev->dev, "failed to initialize DRM/KMS\n"); + dev_err(&pdev->dev, "failed to initialize DRM/KMS (%d)\n", ret); goto done; } diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h index c7c538dd2..9f34fc864 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_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c index 1bdc0ee0c..7fd39a7d9 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 ed36433fb..d7318e1a6 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_group.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.h @@ -25,9 +25,12 @@ 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 register + * @lock: protects the dptsr_planes field and the DPTSR register + * @dptsr_planes: bitmask of planes driven by dot-clock and timing generator 1 + * @num_planes: number of planes in the group * @planes: planes handled by the group */ struct rcar_du_group { @@ -35,12 +38,15 @@ struct rcar_du_group { unsigned int mmio_offset; unsigned int index; + unsigned int num_crtcs; unsigned int use_count; unsigned int used_crtcs; struct mutex lock; + unsigned int dptsr_planes; - struct rcar_du_planes planes; + unsigned int num_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 93117f159..56518eb12 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,14 +284,19 @@ 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]); + + 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) { - index = plane - plane->group->planes.planes; + 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; continue; @@ -301,10 +306,12 @@ 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; - index = plane - plane->group->planes.planes; + index = plane - plane->group->planes; group_freed_planes[plane->group->index] |= 1 << index; plane_state->hwindex = -1; } @@ -326,8 +333,11 @@ static int rcar_du_atomic_check(struct drm_device *dev, struct rcar_du_group *group = &rcdu->groups[index]; unsigned int used_planes = 0; - for (i = 0; i < RCAR_DU_NUM_KMS_PLANES; ++i) { - struct rcar_du_plane *plane = &group->planes.planes[i]; + dev_dbg(rcdu->dev, "%s: finding free planes for group %u\n", + __func__, index); + + for (i = 0; i < group->num_planes; ++i) { + struct rcar_du_plane *plane = &group->planes[i]; struct rcar_du_plane_state *plane_state; struct drm_plane_state *s; @@ -342,28 +352,49 @@ 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_du_plane_state(plane->plane.state); + 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. */ 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]) 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]); + + 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. @@ -372,18 +403,38 @@ 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__); 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; @@ -444,8 +495,10 @@ static int rcar_du_atomic_commit(struct drm_device *dev, /* Allocate the commit object. */ commit = kzalloc(sizeof(*commit), GFP_KERNEL); - if (commit == NULL) - return -ENOMEM; + if (commit == NULL) { + ret = -ENOMEM; + goto error; + } INIT_WORK(&commit->work, rcar_du_atomic_work); commit->dev = dev; @@ -468,7 +521,7 @@ static int rcar_du_atomic_commit(struct drm_device *dev, if (ret) { kfree(commit); - return ret; + goto error; } /* Swap the state, this is the point of no return. */ @@ -480,6 +533,10 @@ static int rcar_du_atomic_commit(struct drm_device *dev, rcar_du_atomic_complete(commit); return 0; + +error: + drm_atomic_helper_cleanup_planes(dev, state); + return ret; } /* ----------------------------------------------------------------------------- @@ -522,7 +579,7 @@ static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu, if (!entity) { dev_dbg(rcdu->dev, "unconnected endpoint %s, skipping\n", ep->local_node->full_name); - return 0; + return -ENODEV; } entity_ep_node = of_parse_phandle(ep->local_node, "remote-endpoint", 0); @@ -545,7 +602,7 @@ static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu, encoder->full_name); of_node_put(entity_ep_node); of_node_put(encoder); - return 0; + return -ENODEV; } break; @@ -574,7 +631,7 @@ static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu, encoder->full_name); of_node_put(encoder); of_node_put(connector); - return 0; + return -EINVAL; } } else { /* @@ -588,7 +645,12 @@ static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu, of_node_put(encoder); of_node_put(connector); - return ret < 0 ? ret : 1; + if (ret && ret != -EPROBE_DEFER) + dev_warn(rcdu->dev, + "failed to initialize encoder %s (%d), skipping\n", + encoder->full_name, ret); + + return ret; } static int rcar_du_encoders_init(struct rcar_du_device *rcdu) @@ -637,17 +699,40 @@ static int rcar_du_encoders_init(struct rcar_du_device *rcdu) return ret; } - dev_info(rcdu->dev, - "encoder initialization failed, skipping\n"); continue; } - num_encoders += ret; + num_encoders++; } 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 +757,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); @@ -683,6 +772,13 @@ 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); + + /* 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 = rgrp->num_crtcs > 1 ? 0xf0 : 0; ret = rcar_du_planes_init(rgrp); if (ret < 0) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c index 210e5c3fd..c66986414 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,13 +302,15 @@ 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); + if (WARN_ON(!plane->state)) + return NULL; + + state = to_rcar_plane_state(plane->state); copy = kmemdup(state, sizeof(*state), GFP_KERNEL); if (copy == NULL) return NULL; - if (copy->state.fb) - drm_framebuffer_reference(copy->state.fb); + __drm_atomic_helper_plane_duplicate_state(plane, ©->state); return ©->state; } @@ -316,10 +318,8 @@ rcar_du_plane_atomic_duplicate_state(struct drm_plane *plane) static void rcar_du_plane_atomic_destroy_state(struct drm_plane *plane, struct drm_plane_state *state) { - if (state->fb) - drm_framebuffer_unreference(state->fb); - - kfree(to_rcar_du_plane_state(state)); + __drm_atomic_helper_plane_destroy_state(plane, state); + kfree(to_rcar_plane_state(state)); } static int rcar_du_plane_atomic_set_property(struct drm_plane *plane, @@ -327,15 +327,14 @@ 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 *rplane = to_rcar_plane(plane); - struct rcar_du_group *rgrp = rplane->group; + struct rcar_du_plane_state *rstate = to_rcar_plane_state(state); + 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; @@ -391,47 +389,23 @@ 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; unsigned int crtcs; 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); - num_planes = num_crtcs + 7; + rgrp->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 + for (i = 0; i < rgrp->num_planes; ++i) { + enum drm_plane_type type = i < rgrp->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; @@ -448,12 +422,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 abff0ebeb..9732bff19 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h @@ -38,19 +38,20 @@ 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 drm_property *alpha; - struct drm_property *colorkey; - 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; @@ -58,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); } |