diff options
Diffstat (limited to 'drivers/gpu/drm/sun4i/sun8i_vi_layer.c')
| -rw-r--r-- | drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 78 | 
1 files changed, 60 insertions, 18 deletions
| diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c index 8cc294a9969d..46420780db59 100644 --- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c @@ -7,8 +7,8 @@  #include <drm/drm_atomic_helper.h>  #include <drm/drm_crtc.h>  #include <drm/drm_fb_cma_helper.h> +#include <drm/drm_gem_atomic_helper.h>  #include <drm/drm_gem_cma_helper.h> -#include <drm/drm_gem_framebuffer_helper.h>  #include <drm/drm_plane_helper.h>  #include <drm/drm_probe_helper.h> @@ -66,6 +66,36 @@ static void sun8i_vi_layer_enable(struct sun8i_mixer *mixer, int channel,  	}  } +static void sun8i_vi_layer_update_alpha(struct sun8i_mixer *mixer, int channel, +					int overlay, struct drm_plane *plane) +{ +	u32 mask, val, ch_base; + +	ch_base = sun8i_channel_base(mixer, channel); + +	if (mixer->cfg->is_de3) { +		mask = SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA_MASK | +		       SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA_MODE_MASK; +		val = SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA +			(plane->state->alpha >> 8); + +		val |= (plane->state->alpha == DRM_BLEND_ALPHA_OPAQUE) ? +			SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA_MODE_PIXEL : +			SUN50I_MIXER_CHAN_VI_LAYER_ATTR_ALPHA_MODE_COMBINED; + +		regmap_update_bits(mixer->engine.regs, +				   SUN8I_MIXER_CHAN_VI_LAYER_ATTR(ch_base, +								  overlay), +				   mask, val); +	} else if (mixer->cfg->vi_num == 1) { +		regmap_update_bits(mixer->engine.regs, +				   SUN8I_MIXER_FCC_GLOBAL_ALPHA_REG, +				   SUN8I_MIXER_FCC_GLOBAL_ALPHA_MASK, +				   SUN8I_MIXER_FCC_GLOBAL_ALPHA +					(plane->state->alpha >> 8)); +	} +} +  static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel,  				       int overlay, struct drm_plane *plane,  				       unsigned int zpos) @@ -268,14 +298,6 @@ static int sun8i_vi_layer_update_formats(struct sun8i_mixer *mixer, int channel,  			   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;  } @@ -339,17 +361,20 @@ 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 drm_atomic_state *state)  { +	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, +										 plane);  	struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane); -	struct drm_crtc *crtc = state->crtc; +	struct drm_crtc *crtc = new_plane_state->crtc;  	struct drm_crtc_state *crtc_state;  	int min_scale, max_scale;  	if (!crtc)  		return 0; -	crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc); +	crtc_state = drm_atomic_get_existing_crtc_state(state, +							crtc);  	if (WARN_ON(!crtc_state))  		return -EINVAL; @@ -361,14 +386,17 @@ static int sun8i_vi_layer_atomic_check(struct drm_plane *plane,  		max_scale = SUN8I_VI_SCALER_SCALE_MAX;  	} -	return drm_atomic_helper_check_plane_state(state, crtc_state, +	return drm_atomic_helper_check_plane_state(new_plane_state, +						   crtc_state,  						   min_scale, max_scale,  						   true, true);  }  static void sun8i_vi_layer_atomic_disable(struct drm_plane *plane, -					  struct drm_plane_state *old_state) +					  struct drm_atomic_state *state)  { +	struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, +									   plane);  	struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane);  	unsigned int old_zpos = old_state->normalized_zpos;  	struct sun8i_mixer *mixer = layer->mixer; @@ -378,14 +406,18 @@ static void sun8i_vi_layer_atomic_disable(struct drm_plane *plane,  }  static void sun8i_vi_layer_atomic_update(struct drm_plane *plane, -					 struct drm_plane_state *old_state) +					 struct drm_atomic_state *state)  { +	struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, +									   plane); +	struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, +									   plane);  	struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane); -	unsigned int zpos = plane->state->normalized_zpos; +	unsigned int zpos = new_state->normalized_zpos;  	unsigned int old_zpos = old_state->normalized_zpos;  	struct sun8i_mixer *mixer = layer->mixer; -	if (!plane->state->visible) { +	if (!new_state->visible) {  		sun8i_vi_layer_enable(mixer, layer->channel,  				      layer->overlay, false, 0, old_zpos);  		return; @@ -393,6 +425,8 @@ static void sun8i_vi_layer_atomic_update(struct drm_plane *plane,  	sun8i_vi_layer_update_coord(mixer, layer->channel,  				    layer->overlay, plane, zpos); +	sun8i_vi_layer_update_alpha(mixer, layer->channel, +				    layer->overlay, plane);  	sun8i_vi_layer_update_formats(mixer, layer->channel,  				      layer->overlay, plane);  	sun8i_vi_layer_update_buffer(mixer, layer->channel, @@ -402,7 +436,7 @@ static void sun8i_vi_layer_atomic_update(struct drm_plane *plane,  }  static const struct drm_plane_helper_funcs sun8i_vi_layer_helper_funcs = { -	.prepare_fb	= drm_gem_fb_prepare_fb, +	.prepare_fb	= drm_gem_plane_helper_prepare_fb,  	.atomic_check	= sun8i_vi_layer_atomic_check,  	.atomic_disable	= sun8i_vi_layer_atomic_disable,  	.atomic_update	= sun8i_vi_layer_atomic_update, @@ -534,6 +568,14 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm,  	plane_cnt = mixer->cfg->ui_num + mixer->cfg->vi_num; +	if (mixer->cfg->vi_num == 1 || mixer->cfg->is_de3) { +		ret = drm_plane_create_alpha_property(&layer->plane); +		if (ret) { +			dev_err(drm->dev, "Couldn't add alpha property\n"); +			return ERR_PTR(ret); +		} +	} +  	ret = drm_plane_create_zpos_property(&layer->plane, index,  					     0, plane_cnt - 1);  	if (ret) { | 
