diff options
Diffstat (limited to 'drivers/gpu/drm/sun4i/sun8i_vi_layer.c')
| -rw-r--r-- | drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 61 | 
1 files changed, 44 insertions, 17 deletions
| diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c index 5877f8ef5895..f4fe97813f94 100644 --- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c @@ -21,7 +21,8 @@  #include "sun8i_vi_scaler.h"  static void sun8i_vi_layer_enable(struct sun8i_mixer *mixer, int channel, -				  int overlay, bool enable) +				  int overlay, bool enable, unsigned int zpos, +				  unsigned int old_zpos)  {  	u32 val; @@ -37,18 +38,36 @@ static void sun8i_vi_layer_enable(struct sun8i_mixer *mixer, int channel,  			   SUN8I_MIXER_CHAN_VI_LAYER_ATTR(channel, overlay),  			   SUN8I_MIXER_CHAN_VI_LAYER_ATTR_EN, val); -	if (enable) -		val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(channel); -	else -		val = 0; +	if (!enable || zpos != old_zpos) { +		regmap_update_bits(mixer->engine.regs, +				   SUN8I_MIXER_BLEND_PIPE_CTL, +				   SUN8I_MIXER_BLEND_PIPE_CTL_EN(old_zpos), +				   0); -	regmap_update_bits(mixer->engine.regs, -			   SUN8I_MIXER_BLEND_PIPE_CTL, -			   SUN8I_MIXER_BLEND_PIPE_CTL_EN(channel), val); +		regmap_update_bits(mixer->engine.regs, +				   SUN8I_MIXER_BLEND_ROUTE, +				   SUN8I_MIXER_BLEND_ROUTE_PIPE_MSK(old_zpos), +				   0); +	} + +	if (enable) { +		val = SUN8I_MIXER_BLEND_PIPE_CTL_EN(zpos); + +		regmap_update_bits(mixer->engine.regs, +				   SUN8I_MIXER_BLEND_PIPE_CTL, 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_PIPE_MSK(zpos), +				   val); +	}  }  static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel, -				       int overlay, struct drm_plane *plane) +				       int overlay, struct drm_plane *plane, +				       unsigned int zpos)  {  	struct drm_plane_state *state = plane->state;  	const struct drm_format_info *format = state->fb->format; @@ -130,10 +149,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(channel), +		     SUN8I_MIXER_BLEND_ATTR_COORD(zpos),  		     SUN8I_MIXER_COORD(state->dst.x1, state->dst.y1));  	regmap_write(mixer->engine.regs, -		     SUN8I_MIXER_BLEND_ATTR_INSIZE(channel), +		     SUN8I_MIXER_BLEND_ATTR_INSIZE(zpos),  		     outsize);  	return 0; @@ -264,30 +283,35 @@ static void sun8i_vi_layer_atomic_disable(struct drm_plane *plane,  					  struct drm_plane_state *old_state)  {  	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; -	sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay, false); +	sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay, false, 0, +			      old_zpos);  }  static void sun8i_vi_layer_atomic_update(struct drm_plane *plane,  					 struct drm_plane_state *old_state)  {  	struct sun8i_vi_layer *layer = plane_to_sun8i_vi_layer(plane); +	unsigned int zpos = plane->state->normalized_zpos; +	unsigned int old_zpos = old_state->normalized_zpos;  	struct sun8i_mixer *mixer = layer->mixer;  	if (!plane->state->visible) {  		sun8i_vi_layer_enable(mixer, layer->channel, -				      layer->overlay, false); +				      layer->overlay, false, 0, old_zpos);  		return;  	}  	sun8i_vi_layer_update_coord(mixer, layer->channel, -				    layer->overlay, plane); +				    layer->overlay, plane, zpos);  	sun8i_vi_layer_update_formats(mixer, layer->channel,  				      layer->overlay, plane);  	sun8i_vi_layer_update_buffer(mixer, layer->channel,  				     layer->overlay, plane); -	sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay, true); +	sun8i_vi_layer_enable(mixer, layer->channel, layer->overlay, +			      true, zpos, old_zpos);  }  static struct drm_plane_helper_funcs sun8i_vi_layer_helper_funcs = { @@ -351,6 +375,7 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm,  					       int index)  {  	struct sun8i_vi_layer *layer; +	unsigned int plane_cnt;  	int ret;  	layer = devm_kzalloc(drm->dev, sizeof(*layer), GFP_KERNEL); @@ -368,8 +393,10 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm,  		return ERR_PTR(ret);  	} -	/* fixed zpos for now */ -	ret = drm_plane_create_zpos_immutable_property(&layer->plane, index); +	plane_cnt = mixer->cfg->ui_num + mixer->cfg->vi_num; + +	ret = drm_plane_create_zpos_property(&layer->plane, index, +					     0, plane_cnt - 1);  	if (ret) {  		dev_err(drm->dev, "Couldn't add zpos property\n");  		return ERR_PTR(ret); |