diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2016-06-18 02:55:13 +0300 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2016-06-18 02:55:13 +0300 |
commit | 9d066a252786e1a18484a6283f82614d42a9f4ac (patch) | |
tree | 72188d2f86b3d0c4100257c8d5734f2c648a8bc7 /drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | |
parent | 79ee2e8f730411a30b271d5f9cdeae189fa66174 (diff) | |
parent | b00345d1994d588fa2687e1238fcd542f0320cba (diff) | |
download | linux-9d066a252786e1a18484a6283f82614d42a9f4ac.tar.xz |
Merge branches 'pm-opp' and 'pm-cpufreq-fixes'
* pm-opp:
PM / OPP: Add 'UNKNOWN' status for shared_opp in struct opp_table
* pm-cpufreq-fixes:
cpufreq: intel_pstate: Adjust _PSS[0] freqeuency if needed
Diffstat (limited to 'drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c')
-rw-r--r-- | drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 95 |
1 files changed, 90 insertions, 5 deletions
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c index d65dcaee3832..aef3ca8a81fa 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c @@ -37,6 +37,7 @@ * @xstride: value to add to the pixel pointer between each line * @pstride: value to add to the pixel pointer between each pixel * @nplanes: number of planes (deduced from pixel_format) + * @prepared: plane update has been prepared */ struct atmel_hlcdc_plane_state { struct drm_plane_state base; @@ -58,12 +59,15 @@ 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]; int xstride[ATMEL_HLCDC_MAX_PLANES]; int pstride[ATMEL_HLCDC_MAX_PLANES]; int nplanes; + bool prepared; }; static inline struct atmel_hlcdc_plane_state * @@ -359,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 | @@ -435,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) { @@ -714,12 +755,54 @@ static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p, static int atmel_hlcdc_plane_prepare_fb(struct drm_plane *p, const struct drm_plane_state *new_state) { + /* + * FIXME: we should avoid this const -> non-const cast but it's + * currently the only solution we have to modify the ->prepared + * state and rollback the update request. + * Ideally, we should rework the code to attach all the resources + * to atmel_hlcdc_plane_state (including the DMA desc allocation), + * but this require a complete rework of the atmel_hlcdc_layer + * code. + */ + struct drm_plane_state *s = (struct drm_plane_state *)new_state; + struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p); + struct atmel_hlcdc_plane_state *state = + drm_plane_state_to_atmel_hlcdc_plane_state(s); + int ret; + + ret = atmel_hlcdc_layer_update_start(&plane->layer); + if (!ret) + state->prepared = true; + + return ret; +} + +static void atmel_hlcdc_plane_cleanup_fb(struct drm_plane *p, + const struct drm_plane_state *old_state) +{ + /* + * FIXME: we should avoid this const -> non-const cast but it's + * currently the only solution we have to modify the ->prepared + * state and rollback the update request. + * Ideally, we should rework the code to attach all the resources + * to atmel_hlcdc_plane_state (including the DMA desc allocation), + * but this require a complete rework of the atmel_hlcdc_layer + * code. + */ + struct drm_plane_state *s = (struct drm_plane_state *)old_state; struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p); + struct atmel_hlcdc_plane_state *state = + drm_plane_state_to_atmel_hlcdc_plane_state(s); - if (!new_state->fb) - return 0; + /* + * The Request has already been applied or cancelled, nothing to do + * here. + */ + if (!state->prepared) + return; - return atmel_hlcdc_layer_update_start(&plane->layer); + atmel_hlcdc_layer_update_rollback(&plane->layer); + state->prepared = false; } static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p, @@ -844,6 +927,7 @@ static void atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane, static struct drm_plane_helper_funcs atmel_hlcdc_layer_plane_helper_funcs = { .prepare_fb = atmel_hlcdc_plane_prepare_fb, + .cleanup_fb = atmel_hlcdc_plane_cleanup_fb, .atomic_check = atmel_hlcdc_plane_atomic_check, .atomic_update = atmel_hlcdc_plane_atomic_update, .atomic_disable = atmel_hlcdc_plane_atomic_disable, @@ -883,6 +967,7 @@ atmel_hlcdc_plane_atomic_duplicate_state(struct drm_plane *p) return NULL; copy->disc_updated = false; + copy->prepared = false; if (copy->base.fb) drm_framebuffer_reference(copy->base.fb); |