diff options
Diffstat (limited to 'drivers/gpu/drm/sun4i/sun8i_vi_layer.c')
-rw-r--r-- | drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 57 |
1 files changed, 40 insertions, 17 deletions
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c index f4fe97813f94..87be898f9b7a 100644 --- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c @@ -13,6 +13,7 @@ #include <drm/drm_crtc_helper.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_plane_helper.h> #include <drm/drmP.h> @@ -24,7 +25,10 @@ static void sun8i_vi_layer_enable(struct sun8i_mixer *mixer, int channel, int overlay, bool enable, unsigned int zpos, unsigned int old_zpos) { - u32 val; + u32 val, bld_base, ch_base; + + bld_base = sun8i_blender_base(mixer); + ch_base = sun8i_channel_base(mixer, channel); DRM_DEBUG_DRIVER("%sabling VI channel %d overlay %d\n", enable ? "En" : "Dis", channel, overlay); @@ -35,17 +39,17 @@ static void sun8i_vi_layer_enable(struct sun8i_mixer *mixer, int channel, val = 0; regmap_update_bits(mixer->engine.regs, - SUN8I_MIXER_CHAN_VI_LAYER_ATTR(channel, overlay), + SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base, overlay), SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN, val); if (!enable || zpos != old_zpos) { regmap_update_bits(mixer->engine.regs, - SUN8I_MIXER_BLEND_PIPE_CTL, + SUN8I_MIXER_BLEND_PIPE_CTL(bld_base), SUN8I_MIXER_BLEND_PIPE_CTL_EN(old_zpos), 0); regmap_update_bits(mixer->engine.regs, - SUN8I_MIXER_BLEND_ROUTE, + SUN8I_MIXER_BLEND_ROUTE(bld_base), SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(old_zpos), 0); } @@ -54,12 +58,13 @@ static void sun8i_vi_layer_enable(struct sun8i_mixer *mixer, int channel, val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(zpos); regmap_update_bits(mixer->engine.regs, - SUN8I_MIXER_BLEND_PIPE_CTL, val, val); + SUN8I_MIXER_BLEND_PIPE_CTL(bld_base), + val, val); val = channel << SUN8I_MIXER_BLEND_ROUTE_PIPE_SHIFT(zpos); regmap_update_bits(mixer->engine.regs, - SUN8I_MIXER_BLEND_ROUTE, + SUN8I_MIXER_BLEND_ROUTE(bld_base), SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(zpos), val); } @@ -72,6 +77,7 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel, struct drm_plane_state *state = plane->state; const struct drm_format_info *format = state->fb->format; u32 src_w, src_h, dst_w, dst_h; + u32 bld_base, ch_base; u32 outsize, insize; u32 hphase, vphase; bool subsampled; @@ -79,6 +85,9 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel, DRM_DEBUG_DRIVER("Updating VI channel %d overlay %d\n", channel, overlay); + bld_base = sun8i_blender_base(mixer); + ch_base = sun8i_channel_base(mixer, channel); + src_w = drm_rect_width(&state->src) >> 16; src_h = drm_rect_height(&state->src) >> 16; dst_w = drm_rect_width(&state->dst); @@ -115,10 +124,10 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel, (state->src.y1 >> 16) & ~(format->vsub - 1)); 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), + SUN8I_MIXER_CHAN_VI_LAYER_SIZE(ch_base, overlay), insize); regmap_write(mixer->engine.regs, - SUN8I_MIXER_CHAN_VI_OVL_SIZE(channel), + SUN8I_MIXER_CHAN_VI_OVL_SIZE(ch_base), insize); /* @@ -149,10 +158,10 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel, 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(zpos), + SUN8I_MIXER_BLEND_ATTR_COORD(bld_base, zpos), SUN8I_MIXER_COORD(state->dst.x1, state->dst.y1)); regmap_write(mixer->engine.regs, - SUN8I_MIXER_BLEND_ATTR_INSIZE(zpos), + SUN8I_MIXER_BLEND_ATTR_INSIZE(bld_base, zpos), outsize); return 0; @@ -163,7 +172,9 @@ static int sun8i_vi_layer_update_formats(struct sun8i_mixer *mixer, int channel, { struct drm_plane_state *state = plane->state; const struct de2_fmt_info *fmt_info; - u32 val; + u32 val, ch_base; + + ch_base = sun8i_channel_base(mixer, channel); fmt_info = sun8i_mixer_format_info(state->fb->format->format); if (!fmt_info) { @@ -173,7 +184,7 @@ static int sun8i_vi_layer_update_formats(struct sun8i_mixer *mixer, int channel, val = fmt_info->de2_fmt << SUN8I_MIXER_CHAN_VI_LAYER_ATTR_FBFMT_OFFSET; regmap_update_bits(mixer->engine.regs, - SUN8I_MIXER_CHAN_VI_LAYER_ATTR(channel, overlay), + SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base, overlay), SUN8I_MIXER_CHAN_VI_LAYER_ATTR_FBFMT_MASK, val); if (fmt_info->csc != SUN8I_CSC_MODE_OFF) { @@ -189,9 +200,17 @@ static int sun8i_vi_layer_update_formats(struct sun8i_mixer *mixer, int channel, val = 0; regmap_update_bits(mixer->engine.regs, - SUN8I_MIXER_CHAN_VI_LAYER_ATTR(channel, overlay), + SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base, overlay), SUN8I_MIXER_CHAN_VI_LAYER_ATTR_RGB_MODE, val); + /* It seems that YUV formats use global alpha setting. */ + if (mixer->cfg->is_de3) + regmap_update_bits(mixer->engine.regs, + SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base, + overlay), + SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA_MASK, + SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA(0xff)); + return 0; } @@ -204,8 +223,11 @@ static int sun8i_vi_layer_update_buffer(struct sun8i_mixer *mixer, int channel, struct drm_gem_cma_object *gem; u32 dx, dy, src_x, src_y; dma_addr_t paddr; + u32 ch_base; int i; + ch_base = sun8i_channel_base(mixer, channel); + /* Adjust x and y to be dividable by subsampling factor */ src_x = (state->src.x1 >> 16) & ~(format->hsub - 1); src_y = (state->src.y1 >> 16) & ~(format->vsub - 1); @@ -235,17 +257,17 @@ static int sun8i_vi_layer_update_buffer(struct sun8i_mixer *mixer, int channel, DRM_DEBUG_DRIVER("Layer %d. line width: %d bytes\n", i + 1, fb->pitches[i]); regmap_write(mixer->engine.regs, - SUN8I_MIXER_CHAN_VI_LAYER_PITCH(channel, + SUN8I_MIXER_CHAN_VI_LAYER_PITCH(ch_base, overlay, i), - fb->pitches[i]); + fb->pitches[i]); DRM_DEBUG_DRIVER("Setting %d. buffer address to %pad\n", i + 1, &paddr); regmap_write(mixer->engine.regs, - SUN8I_MIXER_CHAN_VI_LAYER_TOP_LADDR(channel, + SUN8I_MIXER_CHAN_VI_LAYER_TOP_LADDR(ch_base, overlay, i), - lower_32_bits(paddr)); + lower_32_bits(paddr)); } return 0; @@ -315,6 +337,7 @@ static void sun8i_vi_layer_atomic_update(struct drm_plane *plane, } static struct drm_plane_helper_funcs sun8i_vi_layer_helper_funcs = { + .prepare_fb = drm_gem_fb_prepare_fb, .atomic_check = sun8i_vi_layer_atomic_check, .atomic_disable = sun8i_vi_layer_atomic_disable, .atomic_update = sun8i_vi_layer_atomic_update, |