From ebab87ab7a130c2930b85695e01fc2944fab85c5 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Tue, 15 Mar 2016 18:01:08 +0100 Subject: [PATCH] drm: atmel-hlcdc: route DMA accesses through AHB interfaces In relation with the actuall bandwidth consumed on a DMA Source interface, choose the less used one for a created plane. Signed-off-by: Boris Brezillon Tested-by: Nicolas Ferre --- .../gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 6 ++- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h | 1 + .../gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 43 ++++++++++++++++++- 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c index bd35a8ac1a49..8df0aaf98725 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c @@ -319,7 +319,11 @@ static int atmel_hlcdc_crtc_atomic_check(struct drm_crtc *c, if (ret) return ret; - return atmel_hlcdc_plane_prepare_disc_area(s); + ret = atmel_hlcdc_plane_prepare_disc_area(s); + if (ret) + return ret; + + return atmel_hlcdc_plane_prepare_ahb_routing(s); } static 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 93d0281196e5..7a47f8c094d0 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h @@ -163,6 +163,7 @@ struct atmel_hlcdc_planes * atmel_hlcdc_create_planes(struct drm_device *dev); int atmel_hlcdc_plane_prepare_disc_area(struct drm_crtc_state *c_state); +int atmel_hlcdc_plane_prepare_ahb_routing(struct drm_crtc_state *c_state); void atmel_hlcdc_crtc_irq(struct drm_crtc *c); diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c index 2158d7a61c5e..aef3ca8a81fa 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c @@ -59,6 +59,8 @@ struct atmel_hlcdc_plane_state { int disc_w; int disc_h; + int ahb_id; + /* These fields are private and should not be touched */ int bpp[ATMEL_HLCDC_MAX_PLANES]; unsigned int offsets[ATMEL_HLCDC_MAX_PLANES]; @@ -361,8 +363,10 @@ atmel_hlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane, atmel_hlcdc_layer_update_cfg(&plane->layer, ATMEL_HLCDC_LAYER_DMA_CFG_ID, - ATMEL_HLCDC_LAYER_DMA_BLEN_MASK, - ATMEL_HLCDC_LAYER_DMA_BLEN_INCR16); + ATMEL_HLCDC_LAYER_DMA_BLEN_MASK | + ATMEL_HLCDC_LAYER_DMA_SIF, + ATMEL_HLCDC_LAYER_DMA_BLEN_INCR16 | + state->ahb_id); atmel_hlcdc_layer_update_cfg(&plane->layer, layout->general_config, ATMEL_HLCDC_LAYER_ITER2BL | @@ -437,6 +441,41 @@ static void atmel_hlcdc_plane_update_buffers(struct atmel_hlcdc_plane *plane, } } +int atmel_hlcdc_plane_prepare_ahb_routing(struct drm_crtc_state *c_state) +{ + unsigned int ahb_load[2] = { }; + struct drm_plane *plane; + + drm_atomic_crtc_state_for_each_plane(plane, c_state) { + struct atmel_hlcdc_plane_state *plane_state; + struct drm_plane_state *plane_s; + unsigned int pixels, load = 0; + int i; + + plane_s = drm_atomic_get_plane_state(c_state->state, plane); + if (IS_ERR(plane_s)) + return PTR_ERR(plane_s); + + plane_state = + drm_plane_state_to_atmel_hlcdc_plane_state(plane_s); + + pixels = (plane_state->src_w * plane_state->src_h) - + (plane_state->disc_w * plane_state->disc_h); + + for (i = 0; i < plane_state->nplanes; i++) + load += pixels * plane_state->bpp[i]; + + if (ahb_load[0] <= ahb_load[1]) + plane_state->ahb_id = 0; + else + plane_state->ahb_id = 1; + + ahb_load[plane_state->ahb_id] += load; + } + + return 0; +} + int atmel_hlcdc_plane_prepare_disc_area(struct drm_crtc_state *c_state) { -- 2.39.2