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>
This commit is contained in:
parent
0b9d0416fc
commit
dd86dc2f9a
|
@ -5,12 +5,10 @@
|
|||
* for STMicroelectronics.
|
||||
* License terms: GNU General Public License (GPL), version 2
|
||||
*/
|
||||
#include <drm/drmP.h>
|
||||
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_fb_cma_helper.h>
|
||||
#include <drm/drm_gem_cma_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
|
||||
#include "sti_compositor.h"
|
||||
#include "sti_cursor.h"
|
||||
|
@ -110,34 +108,31 @@ static void sti_cursor_init(struct sti_cursor *cursor)
|
|||
(b * 5);
|
||||
}
|
||||
|
||||
static void sti_cursor_atomic_update(struct drm_plane *drm_plane,
|
||||
struct drm_plane_state *oldstate)
|
||||
static int sti_cursor_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_cursor *cursor = to_sti_cursor(plane);
|
||||
struct drm_crtc *crtc = state->crtc;
|
||||
struct sti_mixer *mixer = to_sti_mixer(crtc);
|
||||
struct drm_framebuffer *fb = state->fb;
|
||||
struct drm_display_mode *mode = &crtc->mode;
|
||||
int dst_x = state->crtc_x;
|
||||
int dst_y = state->crtc_y;
|
||||
int dst_w = clamp_val(state->crtc_w, 0, mode->crtc_hdisplay - dst_x);
|
||||
int dst_h = clamp_val(state->crtc_h, 0, mode->crtc_vdisplay - dst_y);
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_display_mode *mode;
|
||||
int dst_x, dst_y, dst_w, dst_h;
|
||||
int src_w, src_h;
|
||||
|
||||
/* no need for further checks if the plane is being disabled */
|
||||
if (!crtc || !fb)
|
||||
return 0;
|
||||
|
||||
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 */
|
||||
int src_w = state->src_w >> 16;
|
||||
int src_h = state->src_h >> 16;
|
||||
struct drm_gem_cma_object *cma_obj;
|
||||
u32 y, x;
|
||||
u32 val;
|
||||
|
||||
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("(%dx%d)@(%d,%d)\n", dst_w, dst_h, dst_x, dst_y);
|
||||
|
||||
dev_dbg(cursor->dev, "%s %s\n", __func__,
|
||||
sti_plane_to_str(plane));
|
||||
src_w = state->src_w >> 16;
|
||||
src_h = state->src_h >> 16;
|
||||
|
||||
if (src_w < STI_CURS_MIN_SIZE ||
|
||||
src_h < STI_CURS_MIN_SIZE ||
|
||||
|
@ -145,7 +140,7 @@ static void sti_cursor_atomic_update(struct drm_plane *drm_plane,
|
|||
src_h > STI_CURS_MAX_SIZE) {
|
||||
DRM_ERROR("Invalid cursor size (%dx%d)\n",
|
||||
src_w, src_h);
|
||||
return;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* If the cursor size has changed, re-allocated the pixmap */
|
||||
|
@ -169,16 +164,46 @@ static void sti_cursor_atomic_update(struct drm_plane *drm_plane,
|
|||
GFP_KERNEL | GFP_DMA);
|
||||
if (!cursor->pixmap.base) {
|
||||
DRM_ERROR("Failed to allocate memory for pixmap\n");
|
||||
return;
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
|
||||
if (!cma_obj) {
|
||||
if (!drm_fb_cma_get_gem_obj(fb, 0)) {
|
||||
DRM_ERROR("Can't get CMA GEM object for fb\n");
|
||||
return;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s)\n",
|
||||
crtc->base.id, sti_mixer_to_str(to_sti_mixer(crtc)),
|
||||
drm_plane->base.id, sti_plane_to_str(plane));
|
||||
DRM_DEBUG_KMS("(%dx%d)@(%d,%d)\n", dst_w, dst_h, dst_x, dst_y);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sti_cursor_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_cursor *cursor = to_sti_cursor(plane);
|
||||
struct drm_crtc *crtc = state->crtc;
|
||||
struct drm_framebuffer *fb = state->fb;
|
||||
struct drm_display_mode *mode;
|
||||
int dst_x, dst_y;
|
||||
struct drm_gem_cma_object *cma_obj;
|
||||
u32 y, x;
|
||||
u32 val;
|
||||
|
||||
if (!crtc || !fb)
|
||||
return;
|
||||
|
||||
mode = &crtc->mode;
|
||||
dst_x = state->crtc_x;
|
||||
dst_y = state->crtc_y;
|
||||
|
||||
cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
|
||||
|
||||
/* Convert ARGB8888 to CLUT8 */
|
||||
sti_cursor_argb8888_to_clut8(cursor, (u32 *)cma_obj->vaddr);
|
||||
|
||||
|
@ -212,7 +237,6 @@ static void sti_cursor_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",
|
||||
|
@ -221,13 +245,15 @@ static void sti_cursor_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_cursor_helpers_funcs = {
|
||||
.atomic_check = sti_cursor_atomic_check,
|
||||
.atomic_update = sti_cursor_atomic_update,
|
||||
.atomic_disable = sti_cursor_atomic_disable,
|
||||
};
|
||||
|
|
|
@ -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,6 +384,104 @@ static int sti_gdp_get_dst(struct device *dev, int dst, int src)
|
|||
return src;
|
||||
}
|
||||
|
||||
static int sti_gdp_atomic_check(struct drm_plane *drm_plane,
|
||||
struct drm_plane_state *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)
|
||||
{
|
||||
|
@ -393,10 +489,7 @@ static void sti_gdp_atomic_update(struct drm_plane *drm_plane,
|
|||
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 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;
|
||||
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -4,14 +4,11 @@
|
|||
* License terms: GNU General Public License (GPL), version 2
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/component.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/reset.h>
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_fb_cma_helper.h>
|
||||
#include <drm/drm_gem_cma_helper.h>
|
||||
|
||||
|
@ -670,7 +667,7 @@ static void sti_hqvdp_start_xp70(struct sti_hqvdp *hqvdp)
|
|||
DRM_DEBUG_DRIVER("\n");
|
||||
|
||||
if (hqvdp->xp70_initialized) {
|
||||
DRM_INFO("HQVDP XP70 already initialized\n");
|
||||
DRM_DEBUG_DRIVER("HQVDP XP70 already initialized\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -775,6 +772,94 @@ out:
|
|||
release_firmware(firmware);
|
||||
}
|
||||
|
||||
static int sti_hqvdp_atomic_check(struct drm_plane *drm_plane,
|
||||
struct drm_plane_state *state)
|
||||
{
|
||||
struct sti_plane *plane = to_sti_plane(drm_plane);
|
||||
struct sti_hqvdp *hqvdp = to_sti_hqvdp(plane);
|
||||
struct drm_crtc *crtc = state->crtc;
|
||||
struct drm_framebuffer *fb = state->fb;
|
||||
bool first_prepare = plane->status == STI_PLANE_DISABLED ? true : false;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_display_mode *mode;
|
||||
int dst_x, dst_y, dst_w, dst_h;
|
||||
int src_x, src_y, src_w, src_h;
|
||||
|
||||
/* no need for further checks if the plane is being disabled */
|
||||
if (!crtc || !fb)
|
||||
return 0;
|
||||
|
||||
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 = state->src_w >> 16;
|
||||
src_h = state->src_h >> 16;
|
||||
|
||||
if (!sti_hqvdp_check_hw_scaling(hqvdp, mode,
|
||||
src_w, src_h,
|
||||
dst_w, dst_h)) {
|
||||
DRM_ERROR("Scaling beyond HW capabilities\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!drm_fb_cma_get_gem_obj(fb, 0)) {
|
||||
DRM_ERROR("Can't get CMA GEM object for fb\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Input / output size
|
||||
* Align to upper even value
|
||||
*/
|
||||
dst_w = ALIGN(dst_w, 2);
|
||||
dst_h = ALIGN(dst_h, 2);
|
||||
|
||||
if ((src_w > MAX_WIDTH) || (src_w < MIN_WIDTH) ||
|
||||
(src_h > MAX_HEIGHT) || (src_h < MIN_HEIGHT) ||
|
||||
(dst_w > MAX_WIDTH) || (dst_w < MIN_WIDTH) ||
|
||||
(dst_h > MAX_HEIGHT) || (dst_h < MIN_HEIGHT)) {
|
||||
DRM_ERROR("Invalid in/out size %dx%d -> %dx%d\n",
|
||||
src_w, src_h,
|
||||
dst_w, dst_h);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (first_prepare) {
|
||||
/* Start HQVDP XP70 coprocessor */
|
||||
sti_hqvdp_start_xp70(hqvdp);
|
||||
|
||||
/* Prevent VTG shutdown */
|
||||
if (clk_prepare_enable(hqvdp->clk_pix_main)) {
|
||||
DRM_ERROR("Failed to prepare/enable pix main clk\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Register VTG Vsync callback to handle bottom fields */
|
||||
if (sti_vtg_register_client(hqvdp->vtg,
|
||||
&hqvdp->vtg_nb,
|
||||
crtc)) {
|
||||
DRM_ERROR("Cannot register VTG notifier\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("CRTC:%d (%s) drm plane:%d (%s)\n",
|
||||
crtc->base.id, sti_mixer_to_str(to_sti_mixer(crtc)),
|
||||
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_hqvdp_atomic_update(struct drm_plane *drm_plane,
|
||||
struct drm_plane_state *oldstate)
|
||||
{
|
||||
|
@ -782,31 +867,28 @@ static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane,
|
|||
struct sti_plane *plane = to_sti_plane(drm_plane);
|
||||
struct sti_hqvdp *hqvdp = to_sti_hqvdp(plane);
|
||||
struct drm_crtc *crtc = state->crtc;
|
||||
struct sti_mixer *mixer = to_sti_mixer(crtc);
|
||||
struct drm_framebuffer *fb = state->fb;
|
||||
struct drm_display_mode *mode = &crtc->mode;
|
||||
int dst_x = state->crtc_x;
|
||||
int dst_y = state->crtc_y;
|
||||
int dst_w = clamp_val(state->crtc_w, 0, mode->crtc_hdisplay - dst_x);
|
||||
int dst_h = clamp_val(state->crtc_h, 0, mode->crtc_vdisplay - dst_y);
|
||||
/* src_x are in 16.16 format */
|
||||
int src_x = state->src_x >> 16;
|
||||
int src_y = state->src_y >> 16;
|
||||
int src_w = state->src_w >> 16;
|
||||
int src_h = state->src_h >> 16;
|
||||
bool first_prepare = plane->status == STI_PLANE_DISABLED ? true : false;
|
||||
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_hqvdp_cmd *cmd;
|
||||
int scale_h, scale_v;
|
||||
int cmd_offset;
|
||||
|
||||
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);
|
||||
if (!crtc || !fb)
|
||||
return;
|
||||
|
||||
mode = &crtc->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 = state->src_w >> 16;
|
||||
src_h = state->src_h >> 16;
|
||||
|
||||
cmd_offset = sti_hqvdp_get_free_cmd(hqvdp);
|
||||
if (cmd_offset == -1) {
|
||||
|
@ -815,13 +897,6 @@ static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane,
|
|||
}
|
||||
cmd = hqvdp->hqvdp_cmd + cmd_offset;
|
||||
|
||||
if (!sti_hqvdp_check_hw_scaling(hqvdp, mode,
|
||||
src_w, src_h,
|
||||
dst_w, dst_h)) {
|
||||
DRM_ERROR("Scaling beyond HW capabilities\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Static parameters, defaulting to progressive mode */
|
||||
cmd->top.config = TOP_CONFIG_PROGRESSIVE;
|
||||
cmd->top.mem_format = TOP_MEM_FORMAT_DFLT;
|
||||
|
@ -836,10 +911,6 @@ static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane,
|
|||
cmd->iqi.pxf_conf = IQI_PXF_CONF_DFLT;
|
||||
|
||||
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,
|
||||
|
@ -860,16 +931,6 @@ static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane,
|
|||
dst_w = ALIGN(dst_w, 2);
|
||||
dst_h = ALIGN(dst_h, 2);
|
||||
|
||||
if ((src_w > MAX_WIDTH) || (src_w < MIN_WIDTH) ||
|
||||
(src_h > MAX_HEIGHT) || (src_h < MIN_HEIGHT) ||
|
||||
(dst_w > MAX_WIDTH) || (dst_w < MIN_WIDTH) ||
|
||||
(dst_h > MAX_HEIGHT) || (dst_h < MIN_HEIGHT)) {
|
||||
DRM_ERROR("Invalid in/out size %dx%d -> %dx%d\n",
|
||||
src_w, src_h,
|
||||
dst_w, dst_h);
|
||||
return;
|
||||
}
|
||||
|
||||
cmd->top.input_viewport_size = src_h << 16 | src_w;
|
||||
cmd->top.input_frame_size = src_h << 16 | src_w;
|
||||
cmd->hvsrc.output_picture_size = dst_h << 16 | dst_w;
|
||||
|
@ -900,25 +961,6 @@ static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane,
|
|||
scale_v = SCALE_FACTOR * dst_h / src_h;
|
||||
sti_hqvdp_update_hvsrc(HVSRC_VERT, scale_v, &cmd->hvsrc);
|
||||
|
||||
if (first_prepare) {
|
||||
/* Start HQVDP XP70 coprocessor */
|
||||
sti_hqvdp_start_xp70(hqvdp);
|
||||
|
||||
/* Prevent VTG shutdown */
|
||||
if (clk_prepare_enable(hqvdp->clk_pix_main)) {
|
||||
DRM_ERROR("Failed to prepare/enable pix main clk\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Register VTG Vsync callback to handle bottom fields */
|
||||
if (sti_vtg_register_client(hqvdp->vtg,
|
||||
&hqvdp->vtg_nb,
|
||||
crtc)) {
|
||||
DRM_ERROR("Cannot register VTG notifier\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
writel(hqvdp->hqvdp_cmd_paddr + cmd_offset,
|
||||
hqvdp->regs + HQVDP_MBX_NEXT_CMD);
|
||||
|
||||
|
@ -938,7 +980,6 @@ static void sti_hqvdp_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",
|
||||
|
@ -947,13 +988,15 @@ static void sti_hqvdp_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_hqvdp_helpers_funcs = {
|
||||
.atomic_check = sti_hqvdp_atomic_check,
|
||||
.atomic_update = sti_hqvdp_atomic_update,
|
||||
.atomic_disable = sti_hqvdp_atomic_disable,
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue