diff options
author | Jernej Skrabec <jernej.skrabec@siol.net> | 2017-12-01 09:05:44 +0300 |
---|---|---|
committer | Maxime Ripard <maxime.ripard@free-electrons.com> | 2017-12-05 15:22:44 +0300 |
commit | b862a648de3b9ddaad772e11f0db4046d469e88e (patch) | |
tree | ad5d87d6ecb926e0166b1da7d8986ca41bbdcd5f /drivers/gpu/drm/sun4i/sun8i_vi_layer.c | |
parent | 5b1f8367f3ea1a74414a4dce3ccb2e76fdd84385 (diff) | |
download | linux-b862a648de3b9ddaad772e11f0db4046d469e88e.tar.xz |
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
Diffstat (limited to 'drivers/gpu/drm/sun4i/sun8i_vi_layer.c')
-rw-r--r-- | drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 62 |
1 files changed, 47 insertions, 15 deletions
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c index 99ef2a191510..d44f06cc13c5 100644 --- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c @@ -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); } |