diff options
author | Vincent Abriou <vincent.abriou@st.com> | 2016-02-10 12:48:20 +0300 |
---|---|---|
committer | Vincent Abriou <vincent.abriou@st.com> | 2016-02-26 12:03:59 +0300 |
commit | dd86dc2f9ae1102f46115be1f1422265c15540f1 (patch) | |
tree | a023ad056bb141f5187d26c7464712dc4c74cf1b /drivers/gpu/drm/sti/sti_gdp.c | |
parent | 0b9d0416fc28e27cb279021d17bb59e7eba43edb (diff) | |
download | linux-dd86dc2f9ae1102f46115be1f1422265c15540f1.tar.xz |
drm/sti: implement atomic_check for the planes
Atomic update should never fail. Thus all checks must be done in
the atomic_check function for each plane (gdp, hqvdp and cursor).
Signed-off-by: Vincent Abriou <vincent.abriou@st.com>
Reviewed-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
Diffstat (limited to 'drivers/gpu/drm/sti/sti_gdp.c')
-rw-r--r-- | drivers/gpu/drm/sti/sti_gdp.c | 173 |
1 files changed, 103 insertions, 70 deletions
diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c index 6c1a695a07e1..a6fba9cfb0a6 100644 --- a/drivers/gpu/drm/sti/sti_gdp.c +++ b/drivers/gpu/drm/sti/sti_gdp.c @@ -6,9 +6,7 @@ * License terms: GNU General Public License (GPL), version 2 */ -#include <linux/clk.h> -#include <linux/dma-mapping.h> - +#include <drm/drm_atomic.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h> @@ -386,20 +384,115 @@ static int sti_gdp_get_dst(struct device *dev, int dst, int src) return src; } -static void sti_gdp_atomic_update(struct drm_plane *drm_plane, - struct drm_plane_state *oldstate) +static int sti_gdp_atomic_check(struct drm_plane *drm_plane, + struct drm_plane_state *state) { - struct drm_plane_state *state = drm_plane->state; struct sti_plane *plane = to_sti_plane(drm_plane); struct sti_gdp *gdp = to_sti_gdp(plane); struct drm_crtc *crtc = state->crtc; struct sti_compositor *compo = dev_get_drvdata(gdp->dev); struct drm_framebuffer *fb = state->fb; bool first_prepare = plane->status == STI_PLANE_DISABLED ? true : false; + struct drm_crtc_state *crtc_state; struct sti_mixer *mixer; struct drm_display_mode *mode; int dst_x, dst_y, dst_w, dst_h; int src_x, src_y, src_w, src_h; + int format; + + /* no need for further checks if the plane is being disabled */ + if (!crtc || !fb) + return 0; + + mixer = to_sti_mixer(crtc); + crtc_state = drm_atomic_get_crtc_state(state->state, crtc); + mode = &crtc_state->mode; + dst_x = state->crtc_x; + dst_y = state->crtc_y; + dst_w = clamp_val(state->crtc_w, 0, mode->crtc_hdisplay - dst_x); + dst_h = clamp_val(state->crtc_h, 0, mode->crtc_vdisplay - dst_y); + /* src_x are in 16.16 format */ + src_x = state->src_x >> 16; + src_y = state->src_y >> 16; + src_w = clamp_val(state->src_w >> 16, 0, GAM_GDP_SIZE_MAX); + src_h = clamp_val(state->src_h >> 16, 0, GAM_GDP_SIZE_MAX); + + format = sti_gdp_fourcc2format(fb->pixel_format); + if (format == -1) { + DRM_ERROR("Format not supported by GDP %.4s\n", + (char *)&fb->pixel_format); + return -EINVAL; + } + + if (!drm_fb_cma_get_gem_obj(fb, 0)) { + DRM_ERROR("Can't get CMA GEM object for fb\n"); + return -EINVAL; + } + + if (first_prepare) { + /* Register gdp callback */ + gdp->vtg = mixer->id == STI_MIXER_MAIN ? + compo->vtg_main : compo->vtg_aux; + if (sti_vtg_register_client(gdp->vtg, + &gdp->vtg_field_nb, crtc)) { + DRM_ERROR("Cannot register VTG notifier\n"); + return -EINVAL; + } + + /* Set and enable gdp clock */ + if (gdp->clk_pix) { + struct clk *clkp; + int rate = mode->clock * 1000; + int res; + + /* + * According to the mixer used, the gdp pixel clock + * should have a different parent clock. + */ + if (mixer->id == STI_MIXER_MAIN) + clkp = gdp->clk_main_parent; + else + clkp = gdp->clk_aux_parent; + + if (clkp) + clk_set_parent(gdp->clk_pix, clkp); + + res = clk_set_rate(gdp->clk_pix, rate); + if (res < 0) { + DRM_ERROR("Cannot set rate (%dHz) for gdp\n", + rate); + return -EINVAL; + } + + if (clk_prepare_enable(gdp->clk_pix)) { + DRM_ERROR("Failed to prepare/enable gdp\n"); + return -EINVAL; + } + } + } + + DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s)\n", + crtc->base.id, sti_mixer_to_str(mixer), + drm_plane->base.id, sti_plane_to_str(plane)); + DRM_DEBUG_KMS("%s dst=(%dx%d)@(%d,%d) - src=(%dx%d)@(%d,%d)\n", + sti_plane_to_str(plane), + dst_w, dst_h, dst_x, dst_y, + src_w, src_h, src_x, src_y); + + return 0; +} + +static void sti_gdp_atomic_update(struct drm_plane *drm_plane, + struct drm_plane_state *oldstate) +{ + struct drm_plane_state *state = drm_plane->state; + struct sti_plane *plane = to_sti_plane(drm_plane); + struct sti_gdp *gdp = to_sti_gdp(plane); + struct drm_crtc *crtc = state->crtc; + struct drm_framebuffer *fb = state->fb; + struct drm_display_mode *mode; + int dst_x, dst_y, dst_w, dst_h; + int src_x, src_y, src_w, src_h; struct drm_gem_cma_object *cma_obj; struct sti_gdp_node_list *list; struct sti_gdp_node_list *curr_list; @@ -409,13 +502,10 @@ static void sti_gdp_atomic_update(struct drm_plane *drm_plane, int format; unsigned int depth, bpp; u32 ydo, xdo, yds, xds; - int res; - /* Manage the case where crtc is null (disabled) */ - if (!crtc) + if (!crtc || !fb) return; - mixer = to_sti_mixer(crtc); mode = &crtc->mode; dst_x = state->crtc_x; dst_y = state->crtc_y; @@ -427,14 +517,6 @@ static void sti_gdp_atomic_update(struct drm_plane *drm_plane, src_w = clamp_val(state->src_w >> 16, 0, GAM_GDP_SIZE_MAX); src_h = clamp_val(state->src_h >> 16, 0, GAM_GDP_SIZE_MAX); - DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s)\n", - crtc->base.id, sti_mixer_to_str(mixer), - drm_plane->base.id, sti_plane_to_str(plane)); - DRM_DEBUG_KMS("%s dst=(%dx%d)@(%d,%d) - src=(%dx%d)@(%d,%d)\n", - sti_plane_to_str(plane), - dst_w, dst_h, dst_x, dst_y, - src_w, src_h, src_x, src_y); - list = sti_gdp_get_free_nodes(gdp); top_field = list->top_field; btm_field = list->btm_field; @@ -446,20 +528,11 @@ static void sti_gdp_atomic_update(struct drm_plane *drm_plane, top_field->gam_gdp_agc = GAM_GDP_AGC_FULL_RANGE; top_field->gam_gdp_ctl = WAIT_NEXT_VSYNC; format = sti_gdp_fourcc2format(fb->pixel_format); - if (format == -1) { - DRM_ERROR("Format not supported by GDP %.4s\n", - (char *)&fb->pixel_format); - return; - } top_field->gam_gdp_ctl |= format; top_field->gam_gdp_ctl |= sti_gdp_get_alpharange(format); top_field->gam_gdp_ppt &= ~GAM_GDP_PPT_IGNORE; cma_obj = drm_fb_cma_get_gem_obj(fb, 0); - if (!cma_obj) { - DRM_ERROR("Can't get CMA GEM object for fb\n"); - return; - } DRM_DEBUG_DRIVER("drm FB:%d format:%.4s phys@:0x%lx\n", fb->base.id, (char *)&fb->pixel_format, @@ -496,47 +569,6 @@ static void sti_gdp_atomic_update(struct drm_plane *drm_plane, btm_field->gam_gdp_pml = top_field->gam_gdp_pml + fb->pitches[0]; - if (first_prepare) { - /* Register gdp callback */ - gdp->vtg = mixer->id == STI_MIXER_MAIN ? - compo->vtg_main : compo->vtg_aux; - - if (sti_vtg_register_client(gdp->vtg == STI_MIXER_MAIN ? - compo->vtg_main : compo->vtg_aux, - &gdp->vtg_field_nb, crtc)) { - DRM_ERROR("Cannot register VTG notifier\n"); - return; - } - - /* Set and enable gdp clock */ - if (gdp->clk_pix) { - struct clk *clkp; - int rate = mode->clock * 1000; - - /* According to the mixer used, the gdp pixel clock - * should have a different parent clock. */ - if (mixer->id == STI_MIXER_MAIN) - clkp = gdp->clk_main_parent; - else - clkp = gdp->clk_aux_parent; - - if (clkp) - clk_set_parent(gdp->clk_pix, clkp); - - res = clk_set_rate(gdp->clk_pix, rate); - if (res < 0) { - DRM_ERROR("Cannot set rate (%dHz) for gdp\n", - rate); - return; - } - - if (clk_prepare_enable(gdp->clk_pix)) { - DRM_ERROR("Failed to prepare/enable gdp\n"); - return; - } - } - } - /* Update the NVN field of the 'right' field of the current GDP node * (being used by the HW) with the address of the updated ('free') top * field GDP node. @@ -592,7 +624,6 @@ static void sti_gdp_atomic_disable(struct drm_plane *drm_plane, struct drm_plane_state *oldstate) { struct sti_plane *plane = to_sti_plane(drm_plane); - struct sti_mixer *mixer = to_sti_mixer(drm_plane->crtc); if (!drm_plane->crtc) { DRM_DEBUG_DRIVER("drm plane:%d not enabled\n", @@ -601,13 +632,15 @@ static void sti_gdp_atomic_disable(struct drm_plane *drm_plane, } DRM_DEBUG_DRIVER("CRTC:%d (%s) drm plane:%d (%s)\n", - drm_plane->crtc->base.id, sti_mixer_to_str(mixer), + drm_plane->crtc->base.id, + sti_mixer_to_str(to_sti_mixer(drm_plane->crtc)), drm_plane->base.id, sti_plane_to_str(plane)); plane->status = STI_PLANE_DISABLING; } static const struct drm_plane_helper_funcs sti_gdp_helpers_funcs = { + .atomic_check = sti_gdp_atomic_check, .atomic_update = sti_gdp_atomic_update, .atomic_disable = sti_gdp_atomic_disable, }; |