drm/komeda: Add komeda_pipeline/component_get_state_and_set_user
get_state_and_set_user packed get_state and set_user into one function,
which get pipeline/component state for a specific pipeline/component, if
success set the user to it.
v2:
- Rebase.
- Applied commit:
  b962a12050 ("drm/atomic: integrate modeset lock with private objects")
  And delete our private modeset lock for pipeline.
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
							
								
									9801a7eadf
								
							
						
					
					
						commit
						8d537d3bcb
					
				| @ -9,6 +9,7 @@ komeda-y := \ | ||||
| 	komeda_dev.o \
 | ||||
| 	komeda_format_caps.o \
 | ||||
| 	komeda_pipeline.o \
 | ||||
| 	komeda_pipeline_state.o \
 | ||||
| 	komeda_framebuffer.o \
 | ||||
| 	komeda_kms.o \
 | ||||
| 	komeda_crtc.o \
 | ||||
|  | ||||
							
								
								
									
										144
									
								
								drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,144 @@ | ||||
| // SPDX-License-Identifier: GPL-2.0
 | ||||
| /*
 | ||||
|  * (C) COPYRIGHT 2018 ARM Limited. All rights reserved. | ||||
|  * Author: James.Qian.Wang <james.qian.wang@arm.com> | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #include <drm/drm_print.h> | ||||
| #include <linux/clk.h> | ||||
| #include "komeda_dev.h" | ||||
| #include "komeda_kms.h" | ||||
| #include "komeda_pipeline.h" | ||||
| 
 | ||||
| static inline bool is_switching_user(void *old, void *new) | ||||
| { | ||||
| 	if (!old || !new) | ||||
| 		return false; | ||||
| 
 | ||||
| 	return old != new; | ||||
| } | ||||
| 
 | ||||
| struct komeda_pipeline_state * | ||||
| komeda_pipeline_get_state(struct komeda_pipeline *pipe, | ||||
| 			  struct drm_atomic_state *state) | ||||
| { | ||||
| 	struct drm_private_state *priv_st; | ||||
| 
 | ||||
| 	priv_st = drm_atomic_get_private_obj_state(state, &pipe->obj); | ||||
| 	if (IS_ERR(priv_st)) | ||||
| 		return ERR_CAST(priv_st); | ||||
| 
 | ||||
| 	return priv_to_pipe_st(priv_st); | ||||
| } | ||||
| 
 | ||||
| /* Assign pipeline for crtc */ | ||||
| struct komeda_pipeline_state * | ||||
| komeda_pipeline_get_state_and_set_crtc(struct komeda_pipeline *pipe, | ||||
| 				       struct drm_atomic_state *state, | ||||
| 				       struct drm_crtc *crtc) | ||||
| { | ||||
| 	struct komeda_pipeline_state *st; | ||||
| 
 | ||||
| 	st = komeda_pipeline_get_state(pipe, state); | ||||
| 	if (IS_ERR(st)) | ||||
| 		return st; | ||||
| 
 | ||||
| 	if (is_switching_user(crtc, st->crtc)) { | ||||
| 		DRM_DEBUG_ATOMIC("CRTC%d required pipeline%d is busy.\n", | ||||
| 				 drm_crtc_index(crtc), pipe->id); | ||||
| 		return ERR_PTR(-EBUSY); | ||||
| 	} | ||||
| 
 | ||||
| 	/* pipeline only can be disabled when the it is free or unused */ | ||||
| 	if (!crtc && st->active_comps) { | ||||
| 		DRM_DEBUG_ATOMIC("Disabling a busy pipeline:%d.\n", pipe->id); | ||||
| 		return ERR_PTR(-EBUSY); | ||||
| 	} | ||||
| 
 | ||||
| 	st->crtc = crtc; | ||||
| 
 | ||||
| 	if (crtc) { | ||||
| 		struct komeda_crtc_state *kcrtc_st; | ||||
| 
 | ||||
| 		kcrtc_st = to_kcrtc_st(drm_atomic_get_new_crtc_state(state, | ||||
| 								     crtc)); | ||||
| 
 | ||||
| 		kcrtc_st->active_pipes |= BIT(pipe->id); | ||||
| 		kcrtc_st->affected_pipes |= BIT(pipe->id); | ||||
| 	} | ||||
| 	return st; | ||||
| } | ||||
| 
 | ||||
| static struct komeda_component_state * | ||||
| komeda_component_get_state(struct komeda_component *c, | ||||
| 			   struct drm_atomic_state *state) | ||||
| { | ||||
| 	struct drm_private_state *priv_st; | ||||
| 
 | ||||
| 	WARN_ON(!drm_modeset_is_locked(&c->pipeline->obj.lock)); | ||||
| 
 | ||||
| 	priv_st = drm_atomic_get_private_obj_state(state, &c->obj); | ||||
| 	if (IS_ERR(priv_st)) | ||||
| 		return ERR_CAST(priv_st); | ||||
| 
 | ||||
| 	return priv_to_comp_st(priv_st); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * komeda_component_get_state_and_set_user() | ||||
|  * | ||||
|  * @c: component to get state and set user | ||||
|  * @state: global atomic state | ||||
|  * @user: direct user, the binding user | ||||
|  * @crtc: the CRTC user, the big boss :) | ||||
|  * | ||||
|  * This function accepts two users: | ||||
|  * -   The direct user: can be plane/crtc/wb_connector depends on component | ||||
|  * -   The big boss (CRTC) | ||||
|  * CRTC is the big boss (the final user), because all component resources | ||||
|  * eventually will be assigned to CRTC, like the layer will be binding to | ||||
|  * kms_plane, but kms plane will be binding to a CRTC eventually. | ||||
|  * | ||||
|  * The big boss (CRTC) is for pipeline assignment, since &komeda_component isn't | ||||
|  * independent and can be assigned to CRTC freely, but belongs to a specific | ||||
|  * pipeline, only pipeline can be shared between crtc, and pipeline as a whole | ||||
|  * (include all the internal components) assigned to a specific CRTC. | ||||
|  * | ||||
|  * So when set a user to komeda_component, need first to check the status of | ||||
|  * component->pipeline to see if the pipeline is available on this specific | ||||
|  * CRTC. if the pipeline is busy (assigned to another CRTC), even the required | ||||
|  * component is free, the component still cannot be assigned to the direct user. | ||||
|  */ | ||||
| struct komeda_component_state * | ||||
| komeda_component_get_state_and_set_user(struct komeda_component *c, | ||||
| 					struct drm_atomic_state *state, | ||||
| 					void *user, | ||||
| 					struct drm_crtc *crtc) | ||||
| { | ||||
| 	struct komeda_pipeline_state *pipe_st; | ||||
| 	struct komeda_component_state *st; | ||||
| 
 | ||||
| 	/* First check if the pipeline is available */ | ||||
| 	pipe_st = komeda_pipeline_get_state_and_set_crtc(c->pipeline, | ||||
| 							 state, crtc); | ||||
| 	if (IS_ERR(pipe_st)) | ||||
| 		return ERR_CAST(pipe_st); | ||||
| 
 | ||||
| 	st = komeda_component_get_state(c, state); | ||||
| 	if (IS_ERR(st)) | ||||
| 		return st; | ||||
| 
 | ||||
| 	/* check if the component has been occupied */ | ||||
| 	if (is_switching_user(user, st->binding_user)) { | ||||
| 		DRM_DEBUG_ATOMIC("required %s is busy.\n", c->name); | ||||
| 		return ERR_PTR(-EBUSY); | ||||
| 	} | ||||
| 
 | ||||
| 	st->binding_user = user; | ||||
| 	/* mark the component as active if user is valid */ | ||||
| 	if (st->binding_user) | ||||
| 		pipe_st->active_comps |= BIT(c->id); | ||||
| 
 | ||||
| 	return st; | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user