mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	drm/komeda: Add the initial scaler support for CORE
This patch add the initial and necessary logic for CORE to support scaler: - Complete the struct komeda_scaler and komeda_scaler_state for adding the scaler specific features and capablities. - Implement komeda_scaler_validate to check the scaler with the data flow configurations. - Enable scaling support for plane input path (layer input data flow). v2: Fix a typo, and rename "needs_scaling" to "en_scaling" Signed-off-by: James Qian Wang (Arm Technology China) <james.qian.wang@arm.com> Signed-off-by: Liviu Dudau <liviu.dudau@arm.com>
This commit is contained in:
		
							parent
							
								
									7fded557c4
								
							
						
					
					
						commit
						502932a03f
					
				
					 4 changed files with 157 additions and 1 deletions
				
			
		| 
						 | 
					@ -126,6 +126,20 @@ komeda_pipeline_get_component(struct komeda_pipeline *pipe, int id)
 | 
				
			||||||
	return c;
 | 
						return c;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct komeda_component *
 | 
				
			||||||
 | 
					komeda_pipeline_get_first_component(struct komeda_pipeline *pipe,
 | 
				
			||||||
 | 
									    u32 comp_mask)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct komeda_component *c = NULL;
 | 
				
			||||||
 | 
						int id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						id = find_first_bit((unsigned long *)&comp_mask, 32);
 | 
				
			||||||
 | 
						if (id < 32)
 | 
				
			||||||
 | 
							c = komeda_pipeline_get_component(pipe, id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return c;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** komeda_component_add - Add a component to &komeda_pipeline */
 | 
					/** komeda_component_add - Add a component to &komeda_pipeline */
 | 
				
			||||||
struct komeda_component *
 | 
					struct komeda_component *
 | 
				
			||||||
komeda_component_add(struct komeda_pipeline *pipe,
 | 
					komeda_component_add(struct komeda_pipeline *pipe,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -244,11 +244,17 @@ struct komeda_layer_state {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct komeda_scaler {
 | 
					struct komeda_scaler {
 | 
				
			||||||
	struct komeda_component base;
 | 
						struct komeda_component base;
 | 
				
			||||||
	/* scaler features and caps */
 | 
						struct malidp_range hsize, vsize;
 | 
				
			||||||
 | 
						u32 max_upscaling;
 | 
				
			||||||
 | 
						u32 max_downscaling;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct komeda_scaler_state {
 | 
					struct komeda_scaler_state {
 | 
				
			||||||
	struct komeda_component_state base;
 | 
						struct komeda_component_state base;
 | 
				
			||||||
 | 
						u16 hsize_in, vsize_in;
 | 
				
			||||||
 | 
						u16 hsize_out, vsize_out;
 | 
				
			||||||
 | 
						u8 en_scaling : 1,
 | 
				
			||||||
 | 
						   en_alpha : 1; /* enable alpha processing */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct komeda_compiz {
 | 
					struct komeda_compiz {
 | 
				
			||||||
| 
						 | 
					@ -307,6 +313,7 @@ struct komeda_data_flow_cfg {
 | 
				
			||||||
	u32 rot;
 | 
						u32 rot;
 | 
				
			||||||
	int blending_zorder;
 | 
						int blending_zorder;
 | 
				
			||||||
	u8 pixel_blend_mode, layer_alpha;
 | 
						u8 pixel_blend_mode, layer_alpha;
 | 
				
			||||||
 | 
						u8 en_scaling : 1;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** struct komeda_pipeline_funcs */
 | 
					/** struct komeda_pipeline_funcs */
 | 
				
			||||||
| 
						 | 
					@ -407,6 +414,9 @@ void komeda_pipeline_destroy(struct komeda_dev *mdev,
 | 
				
			||||||
int komeda_assemble_pipelines(struct komeda_dev *mdev);
 | 
					int komeda_assemble_pipelines(struct komeda_dev *mdev);
 | 
				
			||||||
struct komeda_component *
 | 
					struct komeda_component *
 | 
				
			||||||
komeda_pipeline_get_component(struct komeda_pipeline *pipe, int id);
 | 
					komeda_pipeline_get_component(struct komeda_pipeline *pipe, int id);
 | 
				
			||||||
 | 
					struct komeda_component *
 | 
				
			||||||
 | 
					komeda_pipeline_get_first_component(struct komeda_pipeline *pipe,
 | 
				
			||||||
 | 
									    u32 comp_mask);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void komeda_pipeline_dump_register(struct komeda_pipeline *pipe,
 | 
					void komeda_pipeline_dump_register(struct komeda_pipeline *pipe,
 | 
				
			||||||
				   struct seq_file *sf);
 | 
									   struct seq_file *sf);
 | 
				
			||||||
| 
						 | 
					@ -423,6 +433,14 @@ komeda_component_add(struct komeda_pipeline *pipe,
 | 
				
			||||||
void komeda_component_destroy(struct komeda_dev *mdev,
 | 
					void komeda_component_destroy(struct komeda_dev *mdev,
 | 
				
			||||||
			      struct komeda_component *c);
 | 
								      struct komeda_component *c);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline struct komeda_component *
 | 
				
			||||||
 | 
					komeda_component_pickup_output(struct komeda_component *c, u32 avail_comps)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						u32 avail_inputs = c->supported_outputs & (avail_comps);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return komeda_pipeline_get_first_component(c->pipeline, avail_inputs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct komeda_plane_state;
 | 
					struct komeda_plane_state;
 | 
				
			||||||
struct komeda_crtc_state;
 | 
					struct komeda_crtc_state;
 | 
				
			||||||
struct komeda_crtc;
 | 
					struct komeda_crtc;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -249,6 +249,26 @@ komeda_component_validate_private(struct komeda_component *c,
 | 
				
			||||||
	return err;
 | 
						return err;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Get current available scaler from the component->supported_outputs */
 | 
				
			||||||
 | 
					static struct komeda_scaler *
 | 
				
			||||||
 | 
					komeda_component_get_avail_scaler(struct komeda_component *c,
 | 
				
			||||||
 | 
									  struct drm_atomic_state *state)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct komeda_pipeline_state *pipe_st;
 | 
				
			||||||
 | 
						u32 avail_scalers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pipe_st = komeda_pipeline_get_state(c->pipeline, state);
 | 
				
			||||||
 | 
						if (!pipe_st)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						avail_scalers = (pipe_st->active_comps & KOMEDA_PIPELINE_SCALERS) ^
 | 
				
			||||||
 | 
								KOMEDA_PIPELINE_SCALERS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c = komeda_component_pickup_output(c, avail_scalers);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return to_scaler(c);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
komeda_layer_check_cfg(struct komeda_layer *layer,
 | 
					komeda_layer_check_cfg(struct komeda_layer *layer,
 | 
				
			||||||
		       struct komeda_plane_state *kplane_st,
 | 
							       struct komeda_plane_state *kplane_st,
 | 
				
			||||||
| 
						 | 
					@ -355,6 +375,98 @@ komeda_wb_layer_validate(struct komeda_layer *wb_layer,
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool scaling_ratio_valid(u32 size_in, u32 size_out,
 | 
				
			||||||
 | 
									u32 max_upscaling, u32 max_downscaling)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (size_out > size_in * max_upscaling)
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						else if (size_in > size_out * max_downscaling)
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					komeda_scaler_check_cfg(struct komeda_scaler *scaler,
 | 
				
			||||||
 | 
								struct komeda_data_flow_cfg *dflow)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						u32 hsize_in, vsize_in, hsize_out, vsize_out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hsize_in = dflow->in_w;
 | 
				
			||||||
 | 
						vsize_in = dflow->in_h;
 | 
				
			||||||
 | 
						hsize_out = dflow->out_w;
 | 
				
			||||||
 | 
						vsize_out = dflow->out_h;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!in_range(&scaler->hsize, hsize_in) ||
 | 
				
			||||||
 | 
						    !in_range(&scaler->hsize, hsize_out)) {
 | 
				
			||||||
 | 
							DRM_DEBUG_ATOMIC("Invalid horizontal sizes");
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!in_range(&scaler->vsize, vsize_in) ||
 | 
				
			||||||
 | 
						    !in_range(&scaler->vsize, vsize_out)) {
 | 
				
			||||||
 | 
							DRM_DEBUG_ATOMIC("Invalid vertical sizes");
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!scaling_ratio_valid(hsize_in, hsize_out, scaler->max_upscaling,
 | 
				
			||||||
 | 
									 scaler->max_downscaling)) {
 | 
				
			||||||
 | 
							DRM_DEBUG_ATOMIC("Invalid horizontal scaling ratio");
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!scaling_ratio_valid(vsize_in, vsize_out, scaler->max_upscaling,
 | 
				
			||||||
 | 
									 scaler->max_downscaling)) {
 | 
				
			||||||
 | 
							DRM_DEBUG_ATOMIC("Invalid vertical scaling ratio");
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					komeda_scaler_validate(void *user,
 | 
				
			||||||
 | 
							       struct komeda_crtc_state *kcrtc_st,
 | 
				
			||||||
 | 
							       struct komeda_data_flow_cfg *dflow)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct drm_atomic_state *drm_st = kcrtc_st->base.state;
 | 
				
			||||||
 | 
						struct komeda_component_state *c_st;
 | 
				
			||||||
 | 
						struct komeda_scaler_state *st;
 | 
				
			||||||
 | 
						struct komeda_scaler *scaler;
 | 
				
			||||||
 | 
						int err = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!dflow->en_scaling)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						scaler = komeda_component_get_avail_scaler(dflow->input.component,
 | 
				
			||||||
 | 
											   drm_st);
 | 
				
			||||||
 | 
						if (!scaler) {
 | 
				
			||||||
 | 
							DRM_DEBUG_ATOMIC("No scaler available");
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = komeda_scaler_check_cfg(scaler, dflow);
 | 
				
			||||||
 | 
						if (err)
 | 
				
			||||||
 | 
							return err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c_st = komeda_component_get_state_and_set_user(&scaler->base,
 | 
				
			||||||
 | 
								drm_st, user, kcrtc_st->base.crtc);
 | 
				
			||||||
 | 
						if (IS_ERR(c_st))
 | 
				
			||||||
 | 
							return PTR_ERR(c_st);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						st = to_scaler_st(c_st);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						st->hsize_in = dflow->in_w;
 | 
				
			||||||
 | 
						st->vsize_in = dflow->in_h;
 | 
				
			||||||
 | 
						st->hsize_out = dflow->out_w;
 | 
				
			||||||
 | 
						st->vsize_out = dflow->out_h;
 | 
				
			||||||
 | 
						st->en_scaling = dflow->en_scaling;
 | 
				
			||||||
 | 
						/* Enable alpha processing if the next stage needs the pixel alpha */
 | 
				
			||||||
 | 
						st->en_alpha = dflow->pixel_blend_mode != DRM_MODE_BLEND_PIXEL_NONE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						komeda_component_add_input(&st->base, &dflow->input, 0);
 | 
				
			||||||
 | 
						komeda_component_set_output(&dflow->input, &scaler->base, 0);
 | 
				
			||||||
 | 
						return err;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void pipeline_composition_size(struct komeda_crtc_state *kcrtc_st,
 | 
					void pipeline_composition_size(struct komeda_crtc_state *kcrtc_st,
 | 
				
			||||||
			       u16 *hsize, u16 *vsize)
 | 
								       u16 *hsize, u16 *vsize)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -520,6 +632,10 @@ int komeda_build_layer_data_flow(struct komeda_layer *layer,
 | 
				
			||||||
	if (err)
 | 
						if (err)
 | 
				
			||||||
		return err;
 | 
							return err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = komeda_scaler_validate(plane, kcrtc_st, dflow);
 | 
				
			||||||
 | 
						if (err)
 | 
				
			||||||
 | 
							return err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = komeda_compiz_set_input(pipe->compiz, kcrtc_st, dflow);
 | 
						err = komeda_compiz_set_input(pipe->compiz, kcrtc_st, dflow);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return err;
 | 
						return err;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,6 +16,7 @@ komeda_plane_init_data_flow(struct drm_plane_state *st,
 | 
				
			||||||
			    struct komeda_data_flow_cfg *dflow)
 | 
								    struct komeda_data_flow_cfg *dflow)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct drm_framebuffer *fb = st->fb;
 | 
						struct drm_framebuffer *fb = st->fb;
 | 
				
			||||||
 | 
						u32 w, h;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memset(dflow, 0, sizeof(*dflow));
 | 
						memset(dflow, 0, sizeof(*dflow));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,6 +37,13 @@ komeda_plane_init_data_flow(struct drm_plane_state *st,
 | 
				
			||||||
	dflow->in_w = st->src_w >> 16;
 | 
						dflow->in_w = st->src_w >> 16;
 | 
				
			||||||
	dflow->in_h = st->src_h >> 16;
 | 
						dflow->in_h = st->src_h >> 16;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						w = dflow->in_w;
 | 
				
			||||||
 | 
						h = dflow->in_h;
 | 
				
			||||||
 | 
						if (drm_rotation_90_or_270(dflow->rot))
 | 
				
			||||||
 | 
							swap(w, h);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dflow->en_scaling = (w != dflow->out_w) || (h != dflow->out_h);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue