drm/sun4i: Add support for HW scaling to DE2
Scaling is currently supported only for RGB framebuffers Coefficients and algorithm which coefficients to select are taken from BSP driver. Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> Link: https://patchwork.freedesktop.org/patch/msgid/20171201060550.10392-22-jernej.skrabec@siol.net
This commit is contained in:
committed by
Maxime Ripard
parent
5b1f8367f3
commit
b862a648de
@@ -18,6 +18,7 @@
|
||||
|
||||
#include "sun8i_vi_layer.h"
|
||||
#include "sun8i_mixer.h"
|
||||
#include "sun8i_vi_scaler.h"
|
||||
|
||||
static void sun8i_vi_layer_enable(struct sun8i_mixer *mixer, int channel,
|
||||
int overlay, bool enable)
|
||||
@@ -50,36 +51,61 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,
|
||||
int overlay, struct drm_plane *plane)
|
||||
{
|
||||
struct drm_plane_state *state = plane->state;
|
||||
u32 width, height, size;
|
||||
u32 src_w, src_h, dst_w, dst_h;
|
||||
u32 outsize, insize;
|
||||
u32 hphase, vphase;
|
||||
|
||||
DRM_DEBUG_DRIVER("Updating VI channel %d overlay %d\n",
|
||||
channel, overlay);
|
||||
/*
|
||||
* Same source and destination width and height are guaranteed
|
||||
* by atomic check function.
|
||||
*/
|
||||
width = drm_rect_width(&state->dst);
|
||||
height = drm_rect_height(&state->dst);
|
||||
size = SUN8I_MIXER_SIZE(width, height);
|
||||
|
||||
src_w = drm_rect_width(&state->src) >> 16;
|
||||
src_h = drm_rect_height(&state->src) >> 16;
|
||||
dst_w = drm_rect_width(&state->dst);
|
||||
dst_h = drm_rect_height(&state->dst);
|
||||
|
||||
hphase = state->src.x1 & 0xffff;
|
||||
vphase = state->src.y1 & 0xffff;
|
||||
|
||||
insize = SUN8I_MIXER_SIZE(src_w, src_h);
|
||||
outsize = SUN8I_MIXER_SIZE(dst_w, dst_h);
|
||||
|
||||
/* Set height and width */
|
||||
DRM_DEBUG_DRIVER("Layer size W: %u H: %u\n", width, height);
|
||||
DRM_DEBUG_DRIVER("Layer source offset X: %d Y: %d\n",
|
||||
state->src.x1 >> 16, state->src.y1 >> 16);
|
||||
DRM_DEBUG_DRIVER("Layer source size W: %d H: %d\n", src_w, src_h);
|
||||
regmap_write(mixer->engine.regs,
|
||||
SUN8I_MIXER_CHAN_VI_LAYER_SIZE(channel, overlay),
|
||||
size);
|
||||
insize);
|
||||
regmap_write(mixer->engine.regs,
|
||||
SUN8I_MIXER_CHAN_VI_OVL_SIZE(channel),
|
||||
size);
|
||||
insize);
|
||||
|
||||
if (insize != outsize || hphase || vphase) {
|
||||
u32 hscale, vscale;
|
||||
|
||||
DRM_DEBUG_DRIVER("HW scaling is enabled\n");
|
||||
|
||||
hscale = state->src_w / state->crtc_w;
|
||||
vscale = state->src_h / state->crtc_h;
|
||||
|
||||
sun8i_vi_scaler_setup(mixer, channel, src_w, src_h, dst_w,
|
||||
dst_h, hscale, vscale, hphase, vphase);
|
||||
sun8i_vi_scaler_enable(mixer, channel, true);
|
||||
} else {
|
||||
DRM_DEBUG_DRIVER("HW scaling is not needed\n");
|
||||
sun8i_vi_scaler_enable(mixer, channel, false);
|
||||
}
|
||||
|
||||
/* Set base coordinates */
|
||||
DRM_DEBUG_DRIVER("Layer coordinates X: %d Y: %d\n",
|
||||
DRM_DEBUG_DRIVER("Layer destination coordinates X: %d Y: %d\n",
|
||||
state->dst.x1, state->dst.y1);
|
||||
DRM_DEBUG_DRIVER("Layer destination size W: %d H: %d\n", dst_w, dst_h);
|
||||
regmap_write(mixer->engine.regs,
|
||||
SUN8I_MIXER_BLEND_ATTR_COORD(channel),
|
||||
SUN8I_MIXER_COORD(state->dst.x1, state->dst.y1));
|
||||
regmap_write(mixer->engine.regs,
|
||||
SUN8I_MIXER_BLEND_ATTR_INSIZE(channel),
|
||||
size);
|
||||
outsize);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -147,8 +173,10 @@ static int sun8i_vi_layer_update_buffer(struct sun8i_mixer *mixer, int channel,
|
||||
static int sun8i_vi_layer_atomic_check(struct drm_plane *plane,
|
||||
struct drm_plane_state *state)
|
||||
{
|
||||
struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane);
|
||||
struct drm_crtc *crtc = state->crtc;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
int min_scale, max_scale;
|
||||
struct drm_rect clip;
|
||||
|
||||
if (!crtc)
|
||||
@@ -163,9 +191,13 @@ static int sun8i_vi_layer_atomic_check(struct drm_plane *plane,
|
||||
clip.x2 = crtc_state->adjusted_mode.hdisplay;
|
||||
clip.y2 = crtc_state->adjusted_mode.vdisplay;
|
||||
|
||||
if (layer->mixer->cfg->scaler_mask & BIT(layer->channel)) {
|
||||
min_scale = SUN8I_VI_SCALER_SCALE_MIN;
|
||||
max_scale = SUN8I_VI_SCALER_SCALE_MAX;
|
||||
}
|
||||
|
||||
return drm_atomic_helper_check_plane_state(state, crtc_state, &clip,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
min_scale, max_scale,
|
||||
true, true);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user