diff options
author | Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> | 2015-02-22 19:36:31 -0500 |
---|---|---|
committer | Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> | 2015-03-03 09:16:23 -0500 |
commit | 4407cc02c9251b0ce6bad3718211353a7dba93ef (patch) | |
tree | 63bf492797632e4d679aae3fd75bf9d66c4f3197 | |
parent | d5746642f480c134e8e76a3104b987c08f790283 (diff) |
drm: rcar-du: Switch plane set_property to atomic helpers
Allow setting up plane properties atomically using the plane
set_property atomic helper. The properties are now stored in the plane
state (requiring subclassing it) and applied when updating the planes.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_du_crtc.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_du_plane.c | 125 | ||||
-rw-r--r-- | drivers/gpu/drm/rcar-du/rcar_du_plane.h | 17 |
4 files changed, 95 insertions, 57 deletions
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 2a1119b52c2a..faa46ed23a62 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c | |||
@@ -193,7 +193,12 @@ void rcar_du_crtc_route_output(struct drm_crtc *crtc, | |||
193 | rcdu->dpad0_source = rcrtc->index; | 193 | rcdu->dpad0_source = rcrtc->index; |
194 | } | 194 | } |
195 | 195 | ||
196 | void rcar_du_crtc_update_planes(struct drm_crtc *crtc) | 196 | static unsigned int plane_zpos(struct rcar_du_plane *plane) |
197 | { | ||
198 | return to_rcar_du_plane_state(plane->plane.state)->zpos; | ||
199 | } | ||
200 | |||
201 | static void rcar_du_crtc_update_planes(struct drm_crtc *crtc) | ||
197 | { | 202 | { |
198 | struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); | 203 | struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); |
199 | struct rcar_du_plane *planes[RCAR_DU_NUM_HW_PLANES]; | 204 | struct rcar_du_plane *planes[RCAR_DU_NUM_HW_PLANES]; |
@@ -212,7 +217,7 @@ void rcar_du_crtc_update_planes(struct drm_crtc *crtc) | |||
212 | 217 | ||
213 | /* Insert the plane in the sorted planes array. */ | 218 | /* Insert the plane in the sorted planes array. */ |
214 | for (j = num_planes++; j > 0; --j) { | 219 | for (j = num_planes++; j > 0; --j) { |
215 | if (planes[j-1]->zpos <= plane->zpos) | 220 | if (plane_zpos(planes[j-1]) <= plane_zpos(plane)) |
216 | break; | 221 | break; |
217 | planes[j] = planes[j-1]; | 222 | planes[j] = planes[j-1]; |
218 | } | 223 | } |
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h index f50fbafd609f..0a3dcca58fd7 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h | |||
@@ -62,6 +62,5 @@ void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc); | |||
62 | 62 | ||
63 | void rcar_du_crtc_route_output(struct drm_crtc *crtc, | 63 | void rcar_du_crtc_route_output(struct drm_crtc *crtc, |
64 | enum rcar_du_output output); | 64 | enum rcar_du_output output); |
65 | void rcar_du_crtc_update_planes(struct drm_crtc *crtc); | ||
66 | 65 | ||
67 | #endif /* __RCAR_DU_CRTC_H__ */ | 66 | #endif /* __RCAR_DU_CRTC_H__ */ |
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c index 9176ac451438..7e0e2731ea27 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c | |||
@@ -201,6 +201,8 @@ static void rcar_du_plane_compute_base(struct rcar_du_plane *plane, | |||
201 | static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane, | 201 | static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane, |
202 | unsigned int index) | 202 | unsigned int index) |
203 | { | 203 | { |
204 | struct rcar_du_plane_state *state = | ||
205 | to_rcar_du_plane_state(plane->plane.state); | ||
204 | struct rcar_du_group *rgrp = plane->group; | 206 | struct rcar_du_group *rgrp = plane->group; |
205 | u32 colorkey; | 207 | u32 colorkey; |
206 | u32 pnmr; | 208 | u32 pnmr; |
@@ -218,7 +220,7 @@ static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane, | |||
218 | rcar_du_plane_write(rgrp, index, PnALPHAR, PnALPHAR_ABIT_0); | 220 | rcar_du_plane_write(rgrp, index, PnALPHAR, PnALPHAR_ABIT_0); |
219 | else | 221 | else |
220 | rcar_du_plane_write(rgrp, index, PnALPHAR, | 222 | rcar_du_plane_write(rgrp, index, PnALPHAR, |
221 | PnALPHAR_ABIT_X | plane->alpha); | 223 | PnALPHAR_ABIT_X | state->alpha); |
222 | 224 | ||
223 | pnmr = PnMR_BM_MD | plane->format->pnmr; | 225 | pnmr = PnMR_BM_MD | plane->format->pnmr; |
224 | 226 | ||
@@ -226,7 +228,7 @@ static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane, | |||
226 | * PnMR_SPIM_TP_OFF bit set in their pnmr field, disabling color keying | 228 | * PnMR_SPIM_TP_OFF bit set in their pnmr field, disabling color keying |
227 | * automatically. | 229 | * automatically. |
228 | */ | 230 | */ |
229 | if ((plane->colorkey & RCAR_DU_COLORKEY_MASK) == RCAR_DU_COLORKEY_NONE) | 231 | if ((state->colorkey & RCAR_DU_COLORKEY_MASK) == RCAR_DU_COLORKEY_NONE) |
230 | pnmr |= PnMR_SPIM_TP_OFF; | 232 | pnmr |= PnMR_SPIM_TP_OFF; |
231 | 233 | ||
232 | /* For packed YUV formats we need to select the U/V order. */ | 234 | /* For packed YUV formats we need to select the U/V order. */ |
@@ -237,24 +239,24 @@ static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane, | |||
237 | 239 | ||
238 | switch (plane->format->fourcc) { | 240 | switch (plane->format->fourcc) { |
239 | case DRM_FORMAT_RGB565: | 241 | case DRM_FORMAT_RGB565: |
240 | colorkey = ((plane->colorkey & 0xf80000) >> 8) | 242 | colorkey = ((state->colorkey & 0xf80000) >> 8) |
241 | | ((plane->colorkey & 0x00fc00) >> 5) | 243 | | ((state->colorkey & 0x00fc00) >> 5) |
242 | | ((plane->colorkey & 0x0000f8) >> 3); | 244 | | ((state->colorkey & 0x0000f8) >> 3); |
243 | rcar_du_plane_write(rgrp, index, PnTC2R, colorkey); | 245 | rcar_du_plane_write(rgrp, index, PnTC2R, colorkey); |
244 | break; | 246 | break; |
245 | 247 | ||
246 | case DRM_FORMAT_ARGB1555: | 248 | case DRM_FORMAT_ARGB1555: |
247 | case DRM_FORMAT_XRGB1555: | 249 | case DRM_FORMAT_XRGB1555: |
248 | colorkey = ((plane->colorkey & 0xf80000) >> 9) | 250 | colorkey = ((state->colorkey & 0xf80000) >> 9) |
249 | | ((plane->colorkey & 0x00f800) >> 6) | 251 | | ((state->colorkey & 0x00f800) >> 6) |
250 | | ((plane->colorkey & 0x0000f8) >> 3); | 252 | | ((state->colorkey & 0x0000f8) >> 3); |
251 | rcar_du_plane_write(rgrp, index, PnTC2R, colorkey); | 253 | rcar_du_plane_write(rgrp, index, PnTC2R, colorkey); |
252 | break; | 254 | break; |
253 | 255 | ||
254 | case DRM_FORMAT_XRGB8888: | 256 | case DRM_FORMAT_XRGB8888: |
255 | case DRM_FORMAT_ARGB8888: | 257 | case DRM_FORMAT_ARGB8888: |
256 | rcar_du_plane_write(rgrp, index, PnTC3R, | 258 | rcar_du_plane_write(rgrp, index, PnTC3R, |
257 | PnTC3R_CODE | (plane->colorkey & 0xffffff)); | 259 | PnTC3R_CODE | (state->colorkey & 0xffffff)); |
258 | break; | 260 | break; |
259 | } | 261 | } |
260 | } | 262 | } |
@@ -414,65 +416,87 @@ static const struct drm_plane_helper_funcs rcar_du_plane_helper_funcs = { | |||
414 | .atomic_update = rcar_du_plane_atomic_update, | 416 | .atomic_update = rcar_du_plane_atomic_update, |
415 | }; | 417 | }; |
416 | 418 | ||
417 | /* Both the .set_property and the .update_plane operations are called with the | 419 | static void rcar_du_plane_reset(struct drm_plane *plane) |
418 | * mode_config lock held. There is this no need to explicitly protect access to | ||
419 | * the alpha and colorkey fields and the mode register. | ||
420 | */ | ||
421 | static void rcar_du_plane_set_alpha(struct rcar_du_plane *plane, u32 alpha) | ||
422 | { | 420 | { |
423 | if (plane->alpha == alpha) | 421 | struct rcar_du_plane_state *state; |
424 | return; | 422 | |
423 | if (plane->state && plane->state->fb) | ||
424 | drm_framebuffer_unreference(plane->state->fb); | ||
425 | 425 | ||
426 | plane->alpha = alpha; | 426 | kfree(plane->state); |
427 | if (!plane->enabled || plane->format->fourcc != DRM_FORMAT_XRGB1555) | 427 | plane->state = NULL; |
428 | |||
429 | state = kzalloc(sizeof(*state), GFP_KERNEL); | ||
430 | if (state == NULL) | ||
428 | return; | 431 | return; |
429 | 432 | ||
430 | rcar_du_plane_setup_mode(plane, plane->hwindex); | 433 | state->alpha = 255; |
434 | state->colorkey = RCAR_DU_COLORKEY_NONE; | ||
435 | state->zpos = plane->type == DRM_PLANE_TYPE_PRIMARY ? 0 : 1; | ||
436 | |||
437 | plane->state = &state->state; | ||
438 | plane->state->plane = plane; | ||
431 | } | 439 | } |
432 | 440 | ||
433 | static void rcar_du_plane_set_colorkey(struct rcar_du_plane *plane, | 441 | static struct drm_plane_state * |
434 | u32 colorkey) | 442 | rcar_du_plane_atomic_duplicate_state(struct drm_plane *plane) |
435 | { | 443 | { |
436 | if (plane->colorkey == colorkey) | 444 | struct rcar_du_plane_state *state; |
437 | return; | 445 | struct rcar_du_plane_state *copy; |
438 | 446 | ||
439 | plane->colorkey = colorkey; | 447 | state = to_rcar_du_plane_state(plane->state); |
440 | if (!plane->enabled) | 448 | copy = kmemdup(state, sizeof(*state), GFP_KERNEL); |
441 | return; | 449 | if (copy == NULL) |
450 | return NULL; | ||
451 | |||
452 | if (copy->state.fb) | ||
453 | drm_framebuffer_reference(copy->state.fb); | ||
442 | 454 | ||
443 | rcar_du_plane_setup_mode(plane, plane->hwindex); | 455 | return ©->state; |
444 | } | 456 | } |
445 | 457 | ||
446 | static void rcar_du_plane_set_zpos(struct rcar_du_plane *plane, | 458 | static void rcar_du_plane_atomic_destroy_state(struct drm_plane *plane, |
447 | unsigned int zpos) | 459 | struct drm_plane_state *state) |
448 | { | 460 | { |
449 | mutex_lock(&plane->group->planes.lock); | 461 | kfree(to_rcar_du_plane_state(state)); |
450 | if (plane->zpos == zpos) | 462 | } |
451 | goto done; | ||
452 | 463 | ||
453 | plane->zpos = zpos; | 464 | static int rcar_du_plane_atomic_set_property(struct drm_plane *plane, |
454 | if (!plane->enabled) | 465 | struct drm_plane_state *state, |
455 | goto done; | 466 | struct drm_property *property, |
467 | uint64_t val) | ||
468 | { | ||
469 | struct rcar_du_plane_state *rstate = to_rcar_du_plane_state(state); | ||
470 | struct rcar_du_plane *rplane = to_rcar_plane(plane); | ||
471 | struct rcar_du_group *rgrp = rplane->group; | ||
456 | 472 | ||
457 | rcar_du_crtc_update_planes(plane->crtc); | 473 | if (property == rgrp->planes.alpha) |
474 | rstate->alpha = val; | ||
475 | else if (property == rgrp->planes.colorkey) | ||
476 | rstate->colorkey = val; | ||
477 | else if (property == rgrp->planes.zpos) | ||
478 | rstate->zpos = val; | ||
479 | else | ||
480 | return -EINVAL; | ||
458 | 481 | ||
459 | done: | 482 | return 0; |
460 | mutex_unlock(&plane->group->planes.lock); | ||
461 | } | 483 | } |
462 | 484 | ||
463 | static int rcar_du_plane_set_property(struct drm_plane *plane, | 485 | static int rcar_du_plane_atomic_get_property(struct drm_plane *plane, |
464 | struct drm_property *property, | 486 | const struct drm_plane_state *state, struct drm_property *property, |
465 | uint64_t value) | 487 | uint64_t *val) |
466 | { | 488 | { |
489 | const struct rcar_du_plane_state *rstate = | ||
490 | container_of(state, const struct rcar_du_plane_state, state); | ||
467 | struct rcar_du_plane *rplane = to_rcar_plane(plane); | 491 | struct rcar_du_plane *rplane = to_rcar_plane(plane); |
468 | struct rcar_du_group *rgrp = rplane->group; | 492 | struct rcar_du_group *rgrp = rplane->group; |
469 | 493 | ||
470 | if (property == rgrp->planes.alpha) | 494 | if (property == rgrp->planes.alpha) |
471 | rcar_du_plane_set_alpha(rplane, value); | 495 | *val = rstate->alpha; |
472 | else if (property == rgrp->planes.colorkey) | 496 | else if (property == rgrp->planes.colorkey) |
473 | rcar_du_plane_set_colorkey(rplane, value); | 497 | *val = rstate->colorkey; |
474 | else if (property == rgrp->planes.zpos) | 498 | else if (property == rgrp->planes.zpos) |
475 | rcar_du_plane_set_zpos(rplane, value); | 499 | *val = rstate->zpos; |
476 | else | 500 | else |
477 | return -EINVAL; | 501 | return -EINVAL; |
478 | 502 | ||
@@ -482,11 +506,13 @@ static int rcar_du_plane_set_property(struct drm_plane *plane, | |||
482 | static const struct drm_plane_funcs rcar_du_plane_funcs = { | 506 | static const struct drm_plane_funcs rcar_du_plane_funcs = { |
483 | .update_plane = drm_atomic_helper_update_plane, | 507 | .update_plane = drm_atomic_helper_update_plane, |
484 | .disable_plane = drm_atomic_helper_disable_plane, | 508 | .disable_plane = drm_atomic_helper_disable_plane, |
485 | .reset = drm_atomic_helper_plane_reset, | 509 | .reset = rcar_du_plane_reset, |
486 | .set_property = rcar_du_plane_set_property, | 510 | .set_property = drm_atomic_helper_plane_set_property, |
487 | .destroy = drm_plane_cleanup, | 511 | .destroy = drm_plane_cleanup, |
488 | .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, | 512 | .atomic_duplicate_state = rcar_du_plane_atomic_duplicate_state, |
489 | .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, | 513 | .atomic_destroy_state = rcar_du_plane_atomic_destroy_state, |
514 | .atomic_set_property = rcar_du_plane_atomic_set_property, | ||
515 | .atomic_get_property = rcar_du_plane_atomic_get_property, | ||
490 | }; | 516 | }; |
491 | 517 | ||
492 | static const uint32_t formats[] = { | 518 | static const uint32_t formats[] = { |
@@ -551,9 +577,6 @@ int rcar_du_planes_init(struct rcar_du_group *rgrp) | |||
551 | 577 | ||
552 | plane->group = rgrp; | 578 | plane->group = rgrp; |
553 | plane->hwindex = -1; | 579 | plane->hwindex = -1; |
554 | plane->alpha = 255; | ||
555 | plane->colorkey = RCAR_DU_COLORKEY_NONE; | ||
556 | plane->zpos = type == DRM_PLANE_TYPE_PRIMARY ? 0 : 1; | ||
557 | 580 | ||
558 | ret = drm_universal_plane_init(rcdu->ddev, &plane->plane, crtcs, | 581 | ret = drm_universal_plane_init(rcdu->ddev, &plane->plane, crtcs, |
559 | &rcar_du_plane_funcs, formats, | 582 | &rcar_du_plane_funcs, formats, |
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/rcar-du/rcar_du_plane.h index 9b77a638863f..d291e85896ef 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h | |||
@@ -39,9 +39,6 @@ struct rcar_du_plane { | |||
39 | bool enabled; | 39 | bool enabled; |
40 | 40 | ||
41 | int hwindex; /* 0-based, -1 means unused */ | 41 | int hwindex; /* 0-based, -1 means unused */ |
42 | unsigned int alpha; | ||
43 | unsigned int colorkey; | ||
44 | unsigned int zpos; | ||
45 | 42 | ||
46 | const struct rcar_du_format_info *format; | 43 | const struct rcar_du_format_info *format; |
47 | 44 | ||
@@ -59,6 +56,20 @@ struct rcar_du_planes { | |||
59 | struct drm_property *zpos; | 56 | struct drm_property *zpos; |
60 | }; | 57 | }; |
61 | 58 | ||
59 | struct rcar_du_plane_state { | ||
60 | struct drm_plane_state state; | ||
61 | |||
62 | unsigned int alpha; | ||
63 | unsigned int colorkey; | ||
64 | unsigned int zpos; | ||
65 | }; | ||
66 | |||
67 | static inline struct rcar_du_plane_state * | ||
68 | to_rcar_du_plane_state(struct drm_plane_state *state) | ||
69 | { | ||
70 | return container_of(state, struct rcar_du_plane_state, state); | ||
71 | } | ||
72 | |||
62 | int rcar_du_planes_init(struct rcar_du_group *rgrp); | 73 | int rcar_du_planes_init(struct rcar_du_group *rgrp); |
63 | 74 | ||
64 | void rcar_du_plane_setup(struct rcar_du_plane *plane); | 75 | void rcar_du_plane_setup(struct rcar_du_plane *plane); |