diff options
author | Dave Airlie <airlied@redhat.com> | 2018-03-20 23:58:43 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2018-03-20 23:58:43 -0400 |
commit | 4f6dd8d6858b6fc0a3babbd2510f99c2bc84f2cb (patch) | |
tree | 9577d1ce5769f004bbbf905ab03378c5f19b7ae3 | |
parent | 287d2ac36b6f2830ea4ef66c110abc0f47a9a658 (diff) | |
parent | 6e810eb508f4b937bc2a718bd4e5cd74cca55500 (diff) |
Merge branch 'for-upstream/mali-dp' of git://linux-arm.org/linux-ld into drm-next
I have accumulated some patches as we went through some internal testing
for mali-dp and I was waiting for the YUV2RGB patches to land in your
tree.
* 'for-upstream/mali-dp' of git://linux-arm.org/linux-ld:
drm: mali-dp: Add YUV->RGB conversion support for video layers
drm: mali-dp: Turn off CRTC vblank when removing module.
drm: arm: malidp: Use drm_atomic_helper_shutdown() to disable planes on removal
drm: arm: malidp: Don't destroy planes manually in error handlers
drm/mali-dp: Fix malidp_atomic_commit_hw_done() for event sending.
drm/arm/malidp: Disable pixel alpha blending for colors that do not have alpha
drm: mali-dp: Fix bug on scaling with rotation
drm/mali-dp: Don't enable scaling engine for planes that only rotate.
drm: mali-dp: Uninitialized variable in malidp_se_check_scaling()
drm/mali-dp: Align pitch size to be multiple of bus burst read size.
drm/mali-dp: Rotated planes need a larger pitch size.
-rw-r--r-- | drivers/gpu/drm/arm/malidp_crtc.c | 20 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/malidp_drv.c | 51 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/malidp_drv.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/malidp_hw.c | 26 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/malidp_hw.h | 15 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/malidp_planes.c | 141 | ||||
-rw-r--r-- | drivers/gpu/drm/arm/malidp_regs.h | 11 |
7 files changed, 189 insertions, 77 deletions
diff --git a/drivers/gpu/drm/arm/malidp_crtc.c b/drivers/gpu/drm/arm/malidp_crtc.c index 904fff80917b..fcc62bc60f6a 100644 --- a/drivers/gpu/drm/arm/malidp_crtc.c +++ b/drivers/gpu/drm/arm/malidp_crtc.c | |||
@@ -288,8 +288,14 @@ static int malidp_crtc_atomic_check_scaling(struct drm_crtc *crtc, | |||
288 | s->enhancer_enable = ((h_upscale_factor >> 16) >= 2 || | 288 | s->enhancer_enable = ((h_upscale_factor >> 16) >= 2 || |
289 | (v_upscale_factor >> 16) >= 2); | 289 | (v_upscale_factor >> 16) >= 2); |
290 | 290 | ||
291 | s->input_w = pstate->src_w >> 16; | 291 | if (pstate->rotation & MALIDP_ROTATED_MASK) { |
292 | s->input_h = pstate->src_h >> 16; | 292 | s->input_w = pstate->src_h >> 16; |
293 | s->input_h = pstate->src_w >> 16; | ||
294 | } else { | ||
295 | s->input_w = pstate->src_w >> 16; | ||
296 | s->input_h = pstate->src_h >> 16; | ||
297 | } | ||
298 | |||
293 | s->output_w = pstate->crtc_w; | 299 | s->output_w = pstate->crtc_w; |
294 | s->output_h = pstate->crtc_h; | 300 | s->output_h = pstate->crtc_h; |
295 | 301 | ||
@@ -525,14 +531,13 @@ int malidp_crtc_init(struct drm_device *drm) | |||
525 | 531 | ||
526 | if (!primary) { | 532 | if (!primary) { |
527 | DRM_ERROR("no primary plane found\n"); | 533 | DRM_ERROR("no primary plane found\n"); |
528 | ret = -EINVAL; | 534 | return -EINVAL; |
529 | goto crtc_cleanup_planes; | ||
530 | } | 535 | } |
531 | 536 | ||
532 | ret = drm_crtc_init_with_planes(drm, &malidp->crtc, primary, NULL, | 537 | ret = drm_crtc_init_with_planes(drm, &malidp->crtc, primary, NULL, |
533 | &malidp_crtc_funcs, NULL); | 538 | &malidp_crtc_funcs, NULL); |
534 | if (ret) | 539 | if (ret) |
535 | goto crtc_cleanup_planes; | 540 | return ret; |
536 | 541 | ||
537 | drm_crtc_helper_add(&malidp->crtc, &malidp_crtc_helper_funcs); | 542 | drm_crtc_helper_add(&malidp->crtc, &malidp_crtc_helper_funcs); |
538 | drm_mode_crtc_set_gamma_size(&malidp->crtc, MALIDP_GAMMA_LUT_SIZE); | 543 | drm_mode_crtc_set_gamma_size(&malidp->crtc, MALIDP_GAMMA_LUT_SIZE); |
@@ -542,9 +547,4 @@ int malidp_crtc_init(struct drm_device *drm) | |||
542 | malidp_se_set_enh_coeffs(malidp->dev); | 547 | malidp_se_set_enh_coeffs(malidp->dev); |
543 | 548 | ||
544 | return 0; | 549 | return 0; |
545 | |||
546 | crtc_cleanup_planes: | ||
547 | malidp_de_planes_destroy(drm); | ||
548 | |||
549 | return ret; | ||
550 | } | 550 | } |
diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c index 3d82712d8002..8d20faa198cf 100644 --- a/drivers/gpu/drm/arm/malidp_drv.c +++ b/drivers/gpu/drm/arm/malidp_drv.c | |||
@@ -185,25 +185,29 @@ static int malidp_set_and_wait_config_valid(struct drm_device *drm) | |||
185 | 185 | ||
186 | static void malidp_atomic_commit_hw_done(struct drm_atomic_state *state) | 186 | static void malidp_atomic_commit_hw_done(struct drm_atomic_state *state) |
187 | { | 187 | { |
188 | struct drm_pending_vblank_event *event; | ||
189 | struct drm_device *drm = state->dev; | 188 | struct drm_device *drm = state->dev; |
190 | struct malidp_drm *malidp = drm->dev_private; | 189 | struct malidp_drm *malidp = drm->dev_private; |
191 | 190 | ||
192 | if (malidp->crtc.enabled) { | 191 | malidp->event = malidp->crtc.state->event; |
193 | /* only set config_valid if the CRTC is enabled */ | 192 | malidp->crtc.state->event = NULL; |
194 | if (malidp_set_and_wait_config_valid(drm)) | ||
195 | DRM_DEBUG_DRIVER("timed out waiting for updated configuration\n"); | ||
196 | } | ||
197 | 193 | ||
198 | event = malidp->crtc.state->event; | 194 | if (malidp->crtc.state->active) { |
199 | if (event) { | 195 | /* |
200 | malidp->crtc.state->event = NULL; | 196 | * if we have an event to deliver to userspace, make sure |
197 | * the vblank is enabled as we are sending it from the IRQ | ||
198 | * handler. | ||
199 | */ | ||
200 | if (malidp->event) | ||
201 | drm_crtc_vblank_get(&malidp->crtc); | ||
201 | 202 | ||
203 | /* only set config_valid if the CRTC is enabled */ | ||
204 | if (malidp_set_and_wait_config_valid(drm) < 0) | ||
205 | DRM_DEBUG_DRIVER("timed out waiting for updated configuration\n"); | ||
206 | } else if (malidp->event) { | ||
207 | /* CRTC inactive means vblank IRQ is disabled, send event directly */ | ||
202 | spin_lock_irq(&drm->event_lock); | 208 | spin_lock_irq(&drm->event_lock); |
203 | if (drm_crtc_vblank_get(&malidp->crtc) == 0) | 209 | drm_crtc_send_vblank_event(&malidp->crtc, malidp->event); |
204 | drm_crtc_arm_vblank_event(&malidp->crtc, event); | 210 | malidp->event = NULL; |
205 | else | ||
206 | drm_crtc_send_vblank_event(&malidp->crtc, event); | ||
207 | spin_unlock_irq(&drm->event_lock); | 211 | spin_unlock_irq(&drm->event_lock); |
208 | } | 212 | } |
209 | drm_atomic_helper_commit_hw_done(state); | 213 | drm_atomic_helper_commit_hw_done(state); |
@@ -232,8 +236,6 @@ static void malidp_atomic_commit_tail(struct drm_atomic_state *state) | |||
232 | 236 | ||
233 | malidp_atomic_commit_hw_done(state); | 237 | malidp_atomic_commit_hw_done(state); |
234 | 238 | ||
235 | drm_atomic_helper_wait_for_vblanks(drm, state); | ||
236 | |||
237 | pm_runtime_put(drm->dev); | 239 | pm_runtime_put(drm->dev); |
238 | 240 | ||
239 | drm_atomic_helper_cleanup_planes(drm, state); | 241 | drm_atomic_helper_cleanup_planes(drm, state); |
@@ -276,7 +278,7 @@ static int malidp_init(struct drm_device *drm) | |||
276 | 278 | ||
277 | static void malidp_fini(struct drm_device *drm) | 279 | static void malidp_fini(struct drm_device *drm) |
278 | { | 280 | { |
279 | malidp_de_planes_destroy(drm); | 281 | drm_atomic_helper_shutdown(drm); |
280 | drm_mode_config_cleanup(drm); | 282 | drm_mode_config_cleanup(drm); |
281 | } | 283 | } |
282 | 284 | ||
@@ -312,13 +314,26 @@ static int malidp_irq_init(struct platform_device *pdev) | |||
312 | 314 | ||
313 | DEFINE_DRM_GEM_CMA_FOPS(fops); | 315 | DEFINE_DRM_GEM_CMA_FOPS(fops); |
314 | 316 | ||
317 | static int malidp_dumb_create(struct drm_file *file_priv, | ||
318 | struct drm_device *drm, | ||
319 | struct drm_mode_create_dumb *args) | ||
320 | { | ||
321 | struct malidp_drm *malidp = drm->dev_private; | ||
322 | /* allocate for the worst case scenario, i.e. rotated buffers */ | ||
323 | u8 alignment = malidp_hw_get_pitch_align(malidp->dev, 1); | ||
324 | |||
325 | args->pitch = ALIGN(DIV_ROUND_UP(args->width * args->bpp, 8), alignment); | ||
326 | |||
327 | return drm_gem_cma_dumb_create_internal(file_priv, drm, args); | ||
328 | } | ||
329 | |||
315 | static struct drm_driver malidp_driver = { | 330 | static struct drm_driver malidp_driver = { |
316 | .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC | | 331 | .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC | |
317 | DRIVER_PRIME, | 332 | DRIVER_PRIME, |
318 | .lastclose = drm_fb_helper_lastclose, | 333 | .lastclose = drm_fb_helper_lastclose, |
319 | .gem_free_object_unlocked = drm_gem_cma_free_object, | 334 | .gem_free_object_unlocked = drm_gem_cma_free_object, |
320 | .gem_vm_ops = &drm_gem_cma_vm_ops, | 335 | .gem_vm_ops = &drm_gem_cma_vm_ops, |
321 | .dumb_create = drm_gem_cma_dumb_create, | 336 | .dumb_create = malidp_dumb_create, |
322 | .prime_handle_to_fd = drm_gem_prime_handle_to_fd, | 337 | .prime_handle_to_fd = drm_gem_prime_handle_to_fd, |
323 | .prime_fd_to_handle = drm_gem_prime_fd_to_handle, | 338 | .prime_fd_to_handle = drm_gem_prime_fd_to_handle, |
324 | .gem_prime_export = drm_gem_prime_export, | 339 | .gem_prime_export = drm_gem_prime_export, |
@@ -662,8 +677,10 @@ static void malidp_unbind(struct device *dev) | |||
662 | drm_fb_cma_fbdev_fini(drm); | 677 | drm_fb_cma_fbdev_fini(drm); |
663 | drm_kms_helper_poll_fini(drm); | 678 | drm_kms_helper_poll_fini(drm); |
664 | pm_runtime_get_sync(dev); | 679 | pm_runtime_get_sync(dev); |
680 | drm_crtc_vblank_off(&malidp->crtc); | ||
665 | malidp_se_irq_fini(drm); | 681 | malidp_se_irq_fini(drm); |
666 | malidp_de_irq_fini(drm); | 682 | malidp_de_irq_fini(drm); |
683 | drm->irq_enabled = false; | ||
667 | component_unbind_all(dev, drm); | 684 | component_unbind_all(dev, drm); |
668 | of_node_put(malidp->crtc.port); | 685 | of_node_put(malidp->crtc.port); |
669 | malidp->crtc.port = NULL; | 686 | malidp->crtc.port = NULL; |
diff --git a/drivers/gpu/drm/arm/malidp_drv.h b/drivers/gpu/drm/arm/malidp_drv.h index e0d12c9fc6b8..c70989b93387 100644 --- a/drivers/gpu/drm/arm/malidp_drv.h +++ b/drivers/gpu/drm/arm/malidp_drv.h | |||
@@ -22,6 +22,7 @@ struct malidp_drm { | |||
22 | struct malidp_hw_device *dev; | 22 | struct malidp_hw_device *dev; |
23 | struct drm_crtc crtc; | 23 | struct drm_crtc crtc; |
24 | wait_queue_head_t wq; | 24 | wait_queue_head_t wq; |
25 | struct drm_pending_vblank_event *event; | ||
25 | atomic_t config_valid; | 26 | atomic_t config_valid; |
26 | u32 core_id; | 27 | u32 core_id; |
27 | }; | 28 | }; |
@@ -59,7 +60,6 @@ struct malidp_crtc_state { | |||
59 | #define to_malidp_crtc_state(x) container_of(x, struct malidp_crtc_state, base) | 60 | #define to_malidp_crtc_state(x) container_of(x, struct malidp_crtc_state, base) |
60 | 61 | ||
61 | int malidp_de_planes_init(struct drm_device *drm); | 62 | int malidp_de_planes_init(struct drm_device *drm); |
62 | void malidp_de_planes_destroy(struct drm_device *drm); | ||
63 | int malidp_crtc_init(struct drm_device *drm); | 63 | int malidp_crtc_init(struct drm_device *drm); |
64 | 64 | ||
65 | /* often used combination of rotational bits */ | 65 | /* often used combination of rotational bits */ |
diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c index 2bfb542135ac..d789b46dc817 100644 --- a/drivers/gpu/drm/arm/malidp_hw.c +++ b/drivers/gpu/drm/arm/malidp_hw.c | |||
@@ -75,16 +75,16 @@ static const struct malidp_format_id malidp550_de_formats[] = { | |||
75 | }; | 75 | }; |
76 | 76 | ||
77 | static const struct malidp_layer malidp500_layers[] = { | 77 | static const struct malidp_layer malidp500_layers[] = { |
78 | { DE_VIDEO1, MALIDP500_DE_LV_BASE, MALIDP500_DE_LV_PTR_BASE, MALIDP_DE_LV_STRIDE0 }, | 78 | { DE_VIDEO1, MALIDP500_DE_LV_BASE, MALIDP500_DE_LV_PTR_BASE, MALIDP_DE_LV_STRIDE0, MALIDP500_LV_YUV2RGB }, |
79 | { DE_GRAPHICS1, MALIDP500_DE_LG1_BASE, MALIDP500_DE_LG1_PTR_BASE, MALIDP_DE_LG_STRIDE }, | 79 | { DE_GRAPHICS1, MALIDP500_DE_LG1_BASE, MALIDP500_DE_LG1_PTR_BASE, MALIDP_DE_LG_STRIDE, 0 }, |
80 | { DE_GRAPHICS2, MALIDP500_DE_LG2_BASE, MALIDP500_DE_LG2_PTR_BASE, MALIDP_DE_LG_STRIDE }, | 80 | { DE_GRAPHICS2, MALIDP500_DE_LG2_BASE, MALIDP500_DE_LG2_PTR_BASE, MALIDP_DE_LG_STRIDE, 0 }, |
81 | }; | 81 | }; |
82 | 82 | ||
83 | static const struct malidp_layer malidp550_layers[] = { | 83 | static const struct malidp_layer malidp550_layers[] = { |
84 | { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE, MALIDP_DE_LV_STRIDE0 }, | 84 | { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE, MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB }, |
85 | { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE, MALIDP_DE_LG_STRIDE }, | 85 | { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE, MALIDP_DE_LG_STRIDE, 0 }, |
86 | { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE, MALIDP_DE_LV_STRIDE0 }, | 86 | { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE, MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB }, |
87 | { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE, MALIDP550_DE_LS_R1_STRIDE }, | 87 | { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE, MALIDP550_DE_LS_R1_STRIDE, 0 }, |
88 | }; | 88 | }; |
89 | 89 | ||
90 | #define SE_N_SCALING_COEFFS 96 | 90 | #define SE_N_SCALING_COEFFS 96 |
@@ -782,9 +782,15 @@ static irqreturn_t malidp_de_irq(int irq, void *arg) | |||
782 | /* first handle the config valid IRQ */ | 782 | /* first handle the config valid IRQ */ |
783 | dc_status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS); | 783 | dc_status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS); |
784 | if (dc_status & hw->map.dc_irq_map.vsync_irq) { | 784 | if (dc_status & hw->map.dc_irq_map.vsync_irq) { |
785 | /* we have a page flip event */ | ||
786 | atomic_set(&malidp->config_valid, 1); | ||
787 | malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, dc_status); | 785 | malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, dc_status); |
786 | /* do we have a page flip event? */ | ||
787 | if (malidp->event != NULL) { | ||
788 | spin_lock(&drm->event_lock); | ||
789 | drm_crtc_send_vblank_event(&malidp->crtc, malidp->event); | ||
790 | malidp->event = NULL; | ||
791 | spin_unlock(&drm->event_lock); | ||
792 | } | ||
793 | atomic_set(&malidp->config_valid, 1); | ||
788 | ret = IRQ_WAKE_THREAD; | 794 | ret = IRQ_WAKE_THREAD; |
789 | } | 795 | } |
790 | 796 | ||
@@ -794,7 +800,7 @@ static irqreturn_t malidp_de_irq(int irq, void *arg) | |||
794 | 800 | ||
795 | mask = malidp_hw_read(hwdev, MALIDP_REG_MASKIRQ); | 801 | mask = malidp_hw_read(hwdev, MALIDP_REG_MASKIRQ); |
796 | status &= mask; | 802 | status &= mask; |
797 | if (status & de->vsync_irq) | 803 | if ((status & de->vsync_irq) && malidp->crtc.enabled) |
798 | drm_crtc_handle_vblank(&malidp->crtc); | 804 | drm_crtc_handle_vblank(&malidp->crtc); |
799 | 805 | ||
800 | malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, status); | 806 | malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, status); |
diff --git a/drivers/gpu/drm/arm/malidp_hw.h b/drivers/gpu/drm/arm/malidp_hw.h index b0690ebb3565..b5dd6c73ec9f 100644 --- a/drivers/gpu/drm/arm/malidp_hw.h +++ b/drivers/gpu/drm/arm/malidp_hw.h | |||
@@ -58,7 +58,8 @@ struct malidp_layer { | |||
58 | u16 id; /* layer ID */ | 58 | u16 id; /* layer ID */ |
59 | u16 base; /* address offset for the register bank */ | 59 | u16 base; /* address offset for the register bank */ |
60 | u16 ptr; /* address offset for the pointer register */ | 60 | u16 ptr; /* address offset for the pointer register */ |
61 | u16 stride_offset; /* Offset to the first stride register. */ | 61 | u16 stride_offset; /* offset to the first stride register. */ |
62 | s16 yuv2rgb_offset; /* offset to the YUV->RGB matrix entries */ | ||
62 | }; | 63 | }; |
63 | 64 | ||
64 | enum malidp_scaling_coeff_set { | 65 | enum malidp_scaling_coeff_set { |
@@ -285,10 +286,16 @@ void malidp_se_irq_fini(struct drm_device *drm); | |||
285 | u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map, | 286 | u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map, |
286 | u8 layer_id, u32 format); | 287 | u8 layer_id, u32 format); |
287 | 288 | ||
288 | static inline bool malidp_hw_pitch_valid(struct malidp_hw_device *hwdev, | 289 | static inline u8 malidp_hw_get_pitch_align(struct malidp_hw_device *hwdev, bool rotated) |
289 | unsigned int pitch) | ||
290 | { | 290 | { |
291 | return !(pitch & (hwdev->hw->map.bus_align_bytes - 1)); | 291 | /* |
292 | * only hardware that cannot do 8 bytes bus alignments have further | ||
293 | * constraints on rotated planes | ||
294 | */ | ||
295 | if (hwdev->hw->map.bus_align_bytes == 8) | ||
296 | return 8; | ||
297 | else | ||
298 | return hwdev->hw->map.bus_align_bytes << (rotated ? 2 : 0); | ||
292 | } | 299 | } |
293 | 300 | ||
294 | /* U16.16 */ | 301 | /* U16.16 */ |
diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index ee32361c87ac..7a44897c50fe 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c | |||
@@ -35,6 +35,9 @@ | |||
35 | #define LAYER_COMP_MASK (0x3 << 12) | 35 | #define LAYER_COMP_MASK (0x3 << 12) |
36 | #define LAYER_COMP_PIXEL (0x3 << 12) | 36 | #define LAYER_COMP_PIXEL (0x3 << 12) |
37 | #define LAYER_COMP_PLANE (0x2 << 12) | 37 | #define LAYER_COMP_PLANE (0x2 << 12) |
38 | #define LAYER_ALPHA_OFFSET (16) | ||
39 | #define LAYER_ALPHA_MASK (0xff) | ||
40 | #define LAYER_ALPHA(x) (((x) & LAYER_ALPHA_MASK) << LAYER_ALPHA_OFFSET) | ||
38 | #define MALIDP_LAYER_COMPOSE 0x008 | 41 | #define MALIDP_LAYER_COMPOSE 0x008 |
39 | #define MALIDP_LAYER_SIZE 0x00c | 42 | #define MALIDP_LAYER_SIZE 0x00c |
40 | #define LAYER_H_VAL(x) (((x) & 0x1fff) << 0) | 43 | #define LAYER_H_VAL(x) (((x) & 0x1fff) << 0) |
@@ -56,12 +59,8 @@ static void malidp_de_plane_destroy(struct drm_plane *plane) | |||
56 | { | 59 | { |
57 | struct malidp_plane *mp = to_malidp_plane(plane); | 60 | struct malidp_plane *mp = to_malidp_plane(plane); |
58 | 61 | ||
59 | if (mp->base.fb) | ||
60 | drm_framebuffer_put(mp->base.fb); | ||
61 | |||
62 | drm_plane_helper_disable(plane); | ||
63 | drm_plane_cleanup(plane); | 62 | drm_plane_cleanup(plane); |
64 | devm_kfree(plane->dev->dev, mp); | 63 | kfree(mp); |
65 | } | 64 | } |
66 | 65 | ||
67 | /* | 66 | /* |
@@ -147,13 +146,21 @@ static int malidp_se_check_scaling(struct malidp_plane *mp, | |||
147 | if (!crtc_state) | 146 | if (!crtc_state) |
148 | return -EINVAL; | 147 | return -EINVAL; |
149 | 148 | ||
149 | mc = to_malidp_crtc_state(crtc_state); | ||
150 | |||
150 | ret = drm_atomic_helper_check_plane_state(state, crtc_state, | 151 | ret = drm_atomic_helper_check_plane_state(state, crtc_state, |
151 | 0, INT_MAX, true, true); | 152 | 0, INT_MAX, true, true); |
152 | if (ret) | 153 | if (ret) |
153 | return ret; | 154 | return ret; |
154 | 155 | ||
155 | src_w = state->src_w >> 16; | 156 | if (state->rotation & MALIDP_ROTATED_MASK) { |
156 | src_h = state->src_h >> 16; | 157 | src_w = state->src_h >> 16; |
158 | src_h = state->src_w >> 16; | ||
159 | } else { | ||
160 | src_w = state->src_w >> 16; | ||
161 | src_h = state->src_h >> 16; | ||
162 | } | ||
163 | |||
157 | if ((state->crtc_w == src_w) && (state->crtc_h == src_h)) { | 164 | if ((state->crtc_w == src_w) && (state->crtc_h == src_h)) { |
158 | /* Scaling not necessary for this plane. */ | 165 | /* Scaling not necessary for this plane. */ |
159 | mc->scaled_planes_mask &= ~(mp->layer->id); | 166 | mc->scaled_planes_mask &= ~(mp->layer->id); |
@@ -163,8 +170,6 @@ static int malidp_se_check_scaling(struct malidp_plane *mp, | |||
163 | if (mp->layer->id & (DE_SMART | DE_GRAPHICS2)) | 170 | if (mp->layer->id & (DE_SMART | DE_GRAPHICS2)) |
164 | return -EINVAL; | 171 | return -EINVAL; |
165 | 172 | ||
166 | mc = to_malidp_crtc_state(crtc_state); | ||
167 | |||
168 | mc->scaled_planes_mask |= mp->layer->id; | 173 | mc->scaled_planes_mask |= mp->layer->id; |
169 | /* Defer scaling requirements calculation to the crtc check. */ | 174 | /* Defer scaling requirements calculation to the crtc check. */ |
170 | return 0; | 175 | return 0; |
@@ -175,6 +180,7 @@ static int malidp_de_plane_check(struct drm_plane *plane, | |||
175 | { | 180 | { |
176 | struct malidp_plane *mp = to_malidp_plane(plane); | 181 | struct malidp_plane *mp = to_malidp_plane(plane); |
177 | struct malidp_plane_state *ms = to_malidp_plane_state(state); | 182 | struct malidp_plane_state *ms = to_malidp_plane_state(state); |
183 | bool rotated = state->rotation & MALIDP_ROTATED_MASK; | ||
178 | struct drm_framebuffer *fb; | 184 | struct drm_framebuffer *fb; |
179 | int i, ret; | 185 | int i, ret; |
180 | 186 | ||
@@ -191,7 +197,8 @@ static int malidp_de_plane_check(struct drm_plane *plane, | |||
191 | 197 | ||
192 | ms->n_planes = fb->format->num_planes; | 198 | ms->n_planes = fb->format->num_planes; |
193 | for (i = 0; i < ms->n_planes; i++) { | 199 | for (i = 0; i < ms->n_planes; i++) { |
194 | if (!malidp_hw_pitch_valid(mp->hwdev, fb->pitches[i])) { | 200 | u8 alignment = malidp_hw_get_pitch_align(mp->hwdev, rotated); |
201 | if (fb->pitches[i] & (alignment - 1)) { | ||
195 | DRM_DEBUG_KMS("Invalid pitch %u for plane %d\n", | 202 | DRM_DEBUG_KMS("Invalid pitch %u for plane %d\n", |
196 | fb->pitches[i], i); | 203 | fb->pitches[i], i); |
197 | return -EINVAL; | 204 | return -EINVAL; |
@@ -259,6 +266,60 @@ static void malidp_de_set_plane_pitches(struct malidp_plane *mp, | |||
259 | mp->layer->stride_offset + i * 4); | 266 | mp->layer->stride_offset + i * 4); |
260 | } | 267 | } |
261 | 268 | ||
269 | static const s16 | ||
270 | malidp_yuv2rgb_coeffs[][DRM_COLOR_RANGE_MAX][MALIDP_COLORADJ_NUM_COEFFS] = { | ||
271 | [DRM_COLOR_YCBCR_BT601][DRM_COLOR_YCBCR_LIMITED_RANGE] = { | ||
272 | 1192, 0, 1634, | ||
273 | 1192, -401, -832, | ||
274 | 1192, 2066, 0, | ||
275 | 64, 512, 512 | ||
276 | }, | ||
277 | [DRM_COLOR_YCBCR_BT601][DRM_COLOR_YCBCR_FULL_RANGE] = { | ||
278 | 1024, 0, 1436, | ||
279 | 1024, -352, -731, | ||
280 | 1024, 1815, 0, | ||
281 | 0, 512, 512 | ||
282 | }, | ||
283 | [DRM_COLOR_YCBCR_BT709][DRM_COLOR_YCBCR_LIMITED_RANGE] = { | ||
284 | 1192, 0, 1836, | ||
285 | 1192, -218, -546, | ||
286 | 1192, 2163, 0, | ||
287 | 64, 512, 512 | ||
288 | }, | ||
289 | [DRM_COLOR_YCBCR_BT709][DRM_COLOR_YCBCR_FULL_RANGE] = { | ||
290 | 1024, 0, 1613, | ||
291 | 1024, -192, -479, | ||
292 | 1024, 1900, 0, | ||
293 | 0, 512, 512 | ||
294 | }, | ||
295 | [DRM_COLOR_YCBCR_BT2020][DRM_COLOR_YCBCR_LIMITED_RANGE] = { | ||
296 | 1024, 0, 1476, | ||
297 | 1024, -165, -572, | ||
298 | 1024, 1884, 0, | ||
299 | 0, 512, 512 | ||
300 | }, | ||
301 | [DRM_COLOR_YCBCR_BT2020][DRM_COLOR_YCBCR_FULL_RANGE] = { | ||
302 | 1024, 0, 1510, | ||
303 | 1024, -168, -585, | ||
304 | 1024, 1927, 0, | ||
305 | 0, 512, 512 | ||
306 | } | ||
307 | }; | ||
308 | |||
309 | static void malidp_de_set_color_encoding(struct malidp_plane *plane, | ||
310 | enum drm_color_encoding enc, | ||
311 | enum drm_color_range range) | ||
312 | { | ||
313 | unsigned int i; | ||
314 | |||
315 | for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) { | ||
316 | /* coefficients are signed, two's complement values */ | ||
317 | malidp_hw_write(plane->hwdev, malidp_yuv2rgb_coeffs[enc][range][i], | ||
318 | plane->layer->base + plane->layer->yuv2rgb_offset + | ||
319 | i * 4); | ||
320 | } | ||
321 | } | ||
322 | |||
262 | static void malidp_de_plane_update(struct drm_plane *plane, | 323 | static void malidp_de_plane_update(struct drm_plane *plane, |
263 | struct drm_plane_state *old_state) | 324 | struct drm_plane_state *old_state) |
264 | { | 325 | { |
@@ -266,6 +327,7 @@ static void malidp_de_plane_update(struct drm_plane *plane, | |||
266 | struct malidp_plane_state *ms = to_malidp_plane_state(plane->state); | 327 | struct malidp_plane_state *ms = to_malidp_plane_state(plane->state); |
267 | u32 src_w, src_h, dest_w, dest_h, val; | 328 | u32 src_w, src_h, dest_w, dest_h, val; |
268 | int i; | 329 | int i; |
330 | bool format_has_alpha = plane->state->fb->format->has_alpha; | ||
269 | 331 | ||
270 | mp = to_malidp_plane(plane); | 332 | mp = to_malidp_plane(plane); |
271 | 333 | ||
@@ -289,6 +351,11 @@ static void malidp_de_plane_update(struct drm_plane *plane, | |||
289 | malidp_de_set_plane_pitches(mp, ms->n_planes, | 351 | malidp_de_set_plane_pitches(mp, ms->n_planes, |
290 | plane->state->fb->pitches); | 352 | plane->state->fb->pitches); |
291 | 353 | ||
354 | if ((plane->state->color_encoding != old_state->color_encoding) || | ||
355 | (plane->state->color_range != old_state->color_range)) | ||
356 | malidp_de_set_color_encoding(mp, plane->state->color_encoding, | ||
357 | plane->state->color_range); | ||
358 | |||
292 | malidp_hw_write(mp->hwdev, LAYER_H_VAL(src_w) | LAYER_V_VAL(src_h), | 359 | malidp_hw_write(mp->hwdev, LAYER_H_VAL(src_w) | LAYER_V_VAL(src_h), |
293 | mp->layer->base + MALIDP_LAYER_SIZE); | 360 | mp->layer->base + MALIDP_LAYER_SIZE); |
294 | 361 | ||
@@ -317,12 +384,25 @@ static void malidp_de_plane_update(struct drm_plane *plane, | |||
317 | if (plane->state->rotation & DRM_MODE_REFLECT_Y) | 384 | if (plane->state->rotation & DRM_MODE_REFLECT_Y) |
318 | val |= LAYER_V_FLIP; | 385 | val |= LAYER_V_FLIP; |
319 | 386 | ||
320 | /* | ||
321 | * always enable pixel alpha blending until we have a way to change | ||
322 | * blend modes | ||
323 | */ | ||
324 | val &= ~LAYER_COMP_MASK; | 387 | val &= ~LAYER_COMP_MASK; |
325 | val |= LAYER_COMP_PIXEL; | 388 | if (format_has_alpha) { |
389 | |||
390 | /* | ||
391 | * always enable pixel alpha blending until we have a way | ||
392 | * to change blend modes | ||
393 | */ | ||
394 | val |= LAYER_COMP_PIXEL; | ||
395 | } else { | ||
396 | |||
397 | /* | ||
398 | * do not enable pixel alpha blending as the color channel | ||
399 | * does not have any alpha information | ||
400 | */ | ||
401 | val |= LAYER_COMP_PLANE; | ||
402 | |||
403 | /* Set layer alpha coefficient to 0xff ie fully opaque */ | ||
404 | val |= LAYER_ALPHA(0xff); | ||
405 | } | ||
326 | 406 | ||
327 | val &= ~LAYER_FLOWCFG(LAYER_FLOWCFG_MASK); | 407 | val &= ~LAYER_FLOWCFG(LAYER_FLOWCFG_MASK); |
328 | if (plane->state->crtc) { | 408 | if (plane->state->crtc) { |
@@ -417,6 +497,26 @@ int malidp_de_planes_init(struct drm_device *drm) | |||
417 | drm_plane_create_rotation_property(&plane->base, DRM_MODE_ROTATE_0, flags); | 497 | drm_plane_create_rotation_property(&plane->base, DRM_MODE_ROTATE_0, flags); |
418 | malidp_hw_write(malidp->dev, MALIDP_ALPHA_LUT, | 498 | malidp_hw_write(malidp->dev, MALIDP_ALPHA_LUT, |
419 | plane->layer->base + MALIDP_LAYER_COMPOSE); | 499 | plane->layer->base + MALIDP_LAYER_COMPOSE); |
500 | |||
501 | /* Attach the YUV->RGB property only to video layers */ | ||
502 | if (id & (DE_VIDEO1 | DE_VIDEO2)) { | ||
503 | /* default encoding for YUV->RGB is BT601 NARROW */ | ||
504 | enum drm_color_encoding enc = DRM_COLOR_YCBCR_BT601; | ||
505 | enum drm_color_range range = DRM_COLOR_YCBCR_LIMITED_RANGE; | ||
506 | |||
507 | ret = drm_plane_create_color_properties(&plane->base, | ||
508 | BIT(DRM_COLOR_YCBCR_BT601) | \ | ||
509 | BIT(DRM_COLOR_YCBCR_BT709) | \ | ||
510 | BIT(DRM_COLOR_YCBCR_BT2020), | ||
511 | BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | \ | ||
512 | BIT(DRM_COLOR_YCBCR_FULL_RANGE), | ||
513 | enc, range); | ||
514 | if (!ret) | ||
515 | /* program the HW registers */ | ||
516 | malidp_de_set_color_encoding(plane, enc, range); | ||
517 | else | ||
518 | DRM_WARN("Failed to create video layer %d color properties\n", id); | ||
519 | } | ||
420 | } | 520 | } |
421 | 521 | ||
422 | kfree(formats); | 522 | kfree(formats); |
@@ -424,18 +524,7 @@ int malidp_de_planes_init(struct drm_device *drm) | |||
424 | return 0; | 524 | return 0; |
425 | 525 | ||
426 | cleanup: | 526 | cleanup: |
427 | malidp_de_planes_destroy(drm); | ||
428 | kfree(formats); | 527 | kfree(formats); |
429 | 528 | ||
430 | return ret; | 529 | return ret; |
431 | } | 530 | } |
432 | |||
433 | void malidp_de_planes_destroy(struct drm_device *drm) | ||
434 | { | ||
435 | struct drm_plane *p, *pt; | ||
436 | |||
437 | list_for_each_entry_safe(p, pt, &drm->mode_config.plane_list, head) { | ||
438 | drm_plane_cleanup(p); | ||
439 | kfree(p); | ||
440 | } | ||
441 | } | ||
diff --git a/drivers/gpu/drm/arm/malidp_regs.h b/drivers/gpu/drm/arm/malidp_regs.h index 2039f857f77d..149024fb4432 100644 --- a/drivers/gpu/drm/arm/malidp_regs.h +++ b/drivers/gpu/drm/arm/malidp_regs.h | |||
@@ -170,10 +170,7 @@ | |||
170 | #define MALIDP500_CONFIG_3D 0x00038 | 170 | #define MALIDP500_CONFIG_3D 0x00038 |
171 | #define MALIDP500_BGND_COLOR 0x0003c | 171 | #define MALIDP500_BGND_COLOR 0x0003c |
172 | #define MALIDP500_OUTPUT_DEPTH 0x00044 | 172 | #define MALIDP500_OUTPUT_DEPTH 0x00044 |
173 | #define MALIDP500_YUV_RGB_COEF 0x00048 | 173 | #define MALIDP500_COEFFS_BASE 0x00078 |
174 | #define MALIDP500_COLOR_ADJ_COEF 0x00078 | ||
175 | #define MALIDP500_COEF_TABLE_ADDR 0x000a8 | ||
176 | #define MALIDP500_COEF_TABLE_DATA 0x000ac | ||
177 | 174 | ||
178 | /* | 175 | /* |
179 | * The YUV2RGB coefficients on the DP500 are not in the video layer's register | 176 | * The YUV2RGB coefficients on the DP500 are not in the video layer's register |
@@ -181,11 +178,6 @@ | |||
181 | * the negative offset. | 178 | * the negative offset. |
182 | */ | 179 | */ |
183 | #define MALIDP500_LV_YUV2RGB ((s16)(-0xB8)) | 180 | #define MALIDP500_LV_YUV2RGB ((s16)(-0xB8)) |
184 | /* | ||
185 | * To match DP550/650, the start of the coeffs registers is | ||
186 | * at COLORADJ_COEFF0 instead of at YUV_RGB_COEF1. | ||
187 | */ | ||
188 | #define MALIDP500_COEFFS_BASE 0x00078 | ||
189 | #define MALIDP500_DE_LV_BASE 0x00100 | 181 | #define MALIDP500_DE_LV_BASE 0x00100 |
190 | #define MALIDP500_DE_LV_PTR_BASE 0x00124 | 182 | #define MALIDP500_DE_LV_PTR_BASE 0x00124 |
191 | #define MALIDP500_DE_LG1_BASE 0x00200 | 183 | #define MALIDP500_DE_LG1_BASE 0x00200 |
@@ -213,6 +205,7 @@ | |||
213 | #define MALIDP550_DE_BGND_COLOR 0x00044 | 205 | #define MALIDP550_DE_BGND_COLOR 0x00044 |
214 | #define MALIDP550_DE_OUTPUT_DEPTH 0x0004c | 206 | #define MALIDP550_DE_OUTPUT_DEPTH 0x0004c |
215 | #define MALIDP550_COEFFS_BASE 0x00050 | 207 | #define MALIDP550_COEFFS_BASE 0x00050 |
208 | #define MALIDP550_LV_YUV2RGB 0x00084 | ||
216 | #define MALIDP550_DE_LV1_BASE 0x00100 | 209 | #define MALIDP550_DE_LV1_BASE 0x00100 |
217 | #define MALIDP550_DE_LV1_PTR_BASE 0x00124 | 210 | #define MALIDP550_DE_LV1_PTR_BASE 0x00124 |
218 | #define MALIDP550_DE_LV2_BASE 0x00200 | 211 | #define MALIDP550_DE_LV2_BASE 0x00200 |