aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBoris Brezillon <boris.brezillon@free-electrons.com>2015-02-06 10:25:06 -0500
committerBoris Brezillon <boris.brezillon@free-electrons.com>2015-02-22 15:00:06 -0500
commit5957017db0f62e00c42d5b8d61ac850636be1230 (patch)
treef7c9475a0b7b2779a927225185e82ec914419c0b
parent2389fc1305fc1e2cf8b310a75463fefd3058bf48 (diff)
drm: atmel-hlcdc: add discard area support
The HLCDC IP provides a way to discard a specific area on the primary plane (in case at least one of the overlay is activated and alpha blending is disabled). Doing this will reduce the amount of data to transfer from the main memory to the Display Controller, and thus alleviate the load on the memory bus (since this link is quite limited on such hardware, this kind of optimization is really important). Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c2
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h2
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c108
3 files changed, 111 insertions, 1 deletions
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
index b0c06272a1cb..a120246474e4 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
@@ -212,7 +212,7 @@ static int atmel_hlcdc_crtc_atomic_check(struct drm_crtc *c,
212 if (atmel_hlcdc_dc_mode_valid(crtc->dc, &s->adjusted_mode) != MODE_OK) 212 if (atmel_hlcdc_dc_mode_valid(crtc->dc, &s->adjusted_mode) != MODE_OK)
213 return -EINVAL; 213 return -EINVAL;
214 214
215 return 0; 215 return atmel_hlcdc_plane_prepare_disc_area(s);
216} 216}
217 217
218static void atmel_hlcdc_crtc_atomic_begin(struct drm_crtc *c) 218static void atmel_hlcdc_crtc_atomic_begin(struct drm_crtc *c)
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
index 015c3f13b7f8..1ea9c2ccd8a7 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
@@ -148,6 +148,8 @@ int atmel_hlcdc_dc_mode_valid(struct atmel_hlcdc_dc *dc,
148struct atmel_hlcdc_planes * 148struct atmel_hlcdc_planes *
149atmel_hlcdc_create_planes(struct drm_device *dev); 149atmel_hlcdc_create_planes(struct drm_device *dev);
150 150
151int atmel_hlcdc_plane_prepare_disc_area(struct drm_crtc_state *c_state);
152
151void atmel_hlcdc_crtc_irq(struct drm_crtc *c); 153void atmel_hlcdc_crtc_irq(struct drm_crtc *c);
152 154
153void atmel_hlcdc_crtc_cancel_page_flip(struct drm_crtc *crtc, 155void atmel_hlcdc_crtc_cancel_page_flip(struct drm_crtc *crtc,
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
index 6c6fcaef356d..dbf97d999d40 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
@@ -51,6 +51,13 @@ struct atmel_hlcdc_plane_state {
51 51
52 u8 alpha; 52 u8 alpha;
53 53
54 bool disc_updated;
55
56 int disc_x;
57 int disc_y;
58 int disc_w;
59 int disc_h;
60
54 /* These fields are private and should not be touched */ 61 /* These fields are private and should not be touched */
55 int bpp[ATMEL_HLCDC_MAX_PLANES]; 62 int bpp[ATMEL_HLCDC_MAX_PLANES];
56 unsigned int offsets[ATMEL_HLCDC_MAX_PLANES]; 63 unsigned int offsets[ATMEL_HLCDC_MAX_PLANES];
@@ -428,6 +435,104 @@ static void atmel_hlcdc_plane_update_buffers(struct atmel_hlcdc_plane *plane,
428 } 435 }
429} 436}
430 437
438int
439atmel_hlcdc_plane_prepare_disc_area(struct drm_crtc_state *c_state)
440{
441 int disc_x = 0, disc_y = 0, disc_w = 0, disc_h = 0;
442 const struct atmel_hlcdc_layer_cfg_layout *layout;
443 struct atmel_hlcdc_plane_state *primary_state;
444 struct drm_plane_state *primary_s;
445 struct atmel_hlcdc_plane *primary;
446 struct drm_plane *ovl;
447
448 primary = drm_plane_to_atmel_hlcdc_plane(c_state->crtc->primary);
449 layout = &primary->layer.desc->layout;
450 if (!layout->disc_pos || !layout->disc_size)
451 return 0;
452
453 primary_s = drm_atomic_get_plane_state(c_state->state,
454 &primary->base);
455 if (IS_ERR(primary_s))
456 return PTR_ERR(primary_s);
457
458 primary_state = drm_plane_state_to_atmel_hlcdc_plane_state(primary_s);
459
460 drm_atomic_crtc_state_for_each_plane(ovl, c_state) {
461 struct atmel_hlcdc_plane_state *ovl_state;
462 struct drm_plane_state *ovl_s;
463
464 if (ovl == c_state->crtc->primary)
465 continue;
466
467 ovl_s = drm_atomic_get_plane_state(c_state->state, ovl);
468 if (IS_ERR(ovl_s))
469 return PTR_ERR(ovl_s);
470
471 ovl_state = drm_plane_state_to_atmel_hlcdc_plane_state(ovl_s);
472
473 if (!ovl_s->fb ||
474 atmel_hlcdc_format_embeds_alpha(ovl_s->fb->pixel_format) ||
475 ovl_state->alpha != 255)
476 continue;
477
478 /* TODO: implement a smarter hidden area detection */
479 if (ovl_state->crtc_h * ovl_state->crtc_w < disc_h * disc_w)
480 continue;
481
482 disc_x = ovl_state->crtc_x;
483 disc_y = ovl_state->crtc_y;
484 disc_h = ovl_state->crtc_h;
485 disc_w = ovl_state->crtc_w;
486 }
487
488 if (disc_x == primary_state->disc_x &&
489 disc_y == primary_state->disc_y &&
490 disc_w == primary_state->disc_w &&
491 disc_h == primary_state->disc_h)
492 return 0;
493
494
495 primary_state->disc_x = disc_x;
496 primary_state->disc_y = disc_y;
497 primary_state->disc_w = disc_w;
498 primary_state->disc_h = disc_h;
499 primary_state->disc_updated = true;
500
501 return 0;
502}
503
504static void
505atmel_hlcdc_plane_update_disc_area(struct atmel_hlcdc_plane *plane,
506 struct atmel_hlcdc_plane_state *state)
507{
508 const struct atmel_hlcdc_layer_cfg_layout *layout =
509 &plane->layer.desc->layout;
510 int disc_surface = 0;
511
512 if (!state->disc_updated)
513 return;
514
515 disc_surface = state->disc_h * state->disc_w;
516
517 atmel_hlcdc_layer_update_cfg(&plane->layer, layout->general_config,
518 ATMEL_HLCDC_LAYER_DISCEN,
519 disc_surface ? ATMEL_HLCDC_LAYER_DISCEN : 0);
520
521 if (!disc_surface)
522 return;
523
524 atmel_hlcdc_layer_update_cfg(&plane->layer,
525 layout->disc_pos,
526 0xffffffff,
527 state->disc_x | (state->disc_y << 16));
528
529 atmel_hlcdc_layer_update_cfg(&plane->layer,
530 layout->disc_size,
531 0xffffffff,
532 (state->disc_w - 1) |
533 ((state->disc_h - 1) << 16));
534}
535
431static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p, 536static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p,
432 struct drm_plane_state *s) 537 struct drm_plane_state *s)
433{ 538{
@@ -628,6 +733,7 @@ static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p,
628 atmel_hlcdc_plane_update_general_settings(plane, state); 733 atmel_hlcdc_plane_update_general_settings(plane, state);
629 atmel_hlcdc_plane_update_format(plane, state); 734 atmel_hlcdc_plane_update_format(plane, state);
630 atmel_hlcdc_plane_update_buffers(plane, state); 735 atmel_hlcdc_plane_update_buffers(plane, state);
736 atmel_hlcdc_plane_update_disc_area(plane, state);
631 737
632 atmel_hlcdc_layer_update_commit(&plane->layer); 738 atmel_hlcdc_layer_update_commit(&plane->layer);
633} 739}
@@ -773,6 +879,8 @@ atmel_hlcdc_plane_atomic_duplicate_state(struct drm_plane *p)
773 if (!copy) 879 if (!copy)
774 return NULL; 880 return NULL;
775 881
882 copy->disc_updated = false;
883
776 if (copy->base.fb) 884 if (copy->base.fb)
777 drm_framebuffer_reference(copy->base.fb); 885 drm_framebuffer_reference(copy->base.fb);
778 886