diff options
Diffstat (limited to 'drivers/media/v4l2-core/v4l2-ctrls.c')
| -rw-r--r-- | drivers/media/v4l2-core/v4l2-ctrls.c | 307 | 
1 files changed, 211 insertions, 96 deletions
| diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index 016cf6204cbb..0d7fe1bd975a 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -421,6 +421,11 @@ const char * const *v4l2_ctrl_get_menu(u32 id)  		"Annex B Start Code",  		NULL,  	}; +	static const char * const h264_hierarchical_coding_type[] = { +		"Hier Coding B", +		"Hier Coding P", +		NULL, +	};  	static const char * const mpeg_mpeg2_level[] = {  		"Low",  		"Main", @@ -697,6 +702,8 @@ const char * const *v4l2_ctrl_get_menu(u32 id)  		return h264_decode_mode;  	case V4L2_CID_STATELESS_H264_START_CODE:  		return h264_start_code; +	case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE: +		return h264_hierarchical_coding_type;  	case V4L2_CID_MPEG_VIDEO_MPEG2_LEVEL:  		return mpeg_mpeg2_level;  	case V4L2_CID_MPEG_VIDEO_MPEG2_PROFILE: @@ -874,6 +881,9 @@ const char *v4l2_ctrl_get_name(u32 id)  	case V4L2_CID_MPEG_VIDEO_HEADER_MODE:			return "Sequence Header Mode";  	case V4L2_CID_MPEG_VIDEO_MAX_REF_PIC:			return "Max Number of Reference Pics";  	case V4L2_CID_MPEG_VIDEO_FRAME_SKIP_MODE:		return "Frame Skip Mode"; +	case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY:		return "Display Delay"; +	case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE:	return "Display Delay Enable"; +	case V4L2_CID_MPEG_VIDEO_AU_DELIMITER:			return "Generate Access Unit Delimiters";  	case V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP:		return "H263 I-Frame QP Value";  	case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP:		return "H263 P-Frame QP Value";  	case V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP:		return "H263 B-Frame QP Value"; @@ -945,12 +955,16 @@ const char *v4l2_ctrl_get_name(u32 id)  	case V4L2_CID_MPEG_VIDEO_VBV_SIZE:			return "VBV Buffer Size";  	case V4L2_CID_MPEG_VIDEO_DEC_PTS:			return "Video Decoder PTS";  	case V4L2_CID_MPEG_VIDEO_DEC_FRAME:			return "Video Decoder Frame Count"; +	case V4L2_CID_MPEG_VIDEO_DEC_CONCEAL_COLOR:		return "Video Decoder Conceal Color";  	case V4L2_CID_MPEG_VIDEO_VBV_DELAY:			return "Initial Delay for VBV Control";  	case V4L2_CID_MPEG_VIDEO_MV_H_SEARCH_RANGE:		return "Horizontal MV Search Range";  	case V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE:		return "Vertical MV Search Range";  	case V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER:		return "Repeat Sequence Header";  	case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME:		return "Force Key Frame";  	case V4L2_CID_MPEG_VIDEO_BASELAYER_PRIORITY_ID:		return "Base Layer Priority ID"; +	case V4L2_CID_MPEG_VIDEO_LTR_COUNT:			return "LTR Count"; +	case V4L2_CID_MPEG_VIDEO_FRAME_LTR_INDEX:		return "Frame LTR Index"; +	case V4L2_CID_MPEG_VIDEO_USE_LTR_FRAMES:		return "Use LTR Frames";  	case V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS:		return "MPEG-2 Slice Parameters";  	case V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION:		return "MPEG-2 Quantization Matrices";  	case V4L2_CID_FWHT_I_FRAME_QP:				return "FWHT I-Frame QP Value"; @@ -971,7 +985,6 @@ const char *v4l2_ctrl_get_name(u32 id)  	case V4L2_CID_MPEG_VIDEO_VP8_PROFILE:			return "VP8 Profile";  	case V4L2_CID_MPEG_VIDEO_VP9_PROFILE:			return "VP9 Profile";  	case V4L2_CID_MPEG_VIDEO_VP9_LEVEL:			return "VP9 Level"; -	case V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER:		return "VP8 Frame Header";  	/* HEVC controls */  	case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP:		return "HEVC I-Frame QP Value"; @@ -1201,6 +1214,13 @@ const char *v4l2_ctrl_get_name(u32 id)  	case V4L2_CID_STATELESS_H264_SLICE_PARAMS:		return "H264 Slice Parameters";  	case V4L2_CID_STATELESS_H264_DECODE_PARAMS:		return "H264 Decode Parameters";  	case V4L2_CID_STATELESS_FWHT_PARAMS:			return "FWHT Stateless Parameters"; +	case V4L2_CID_STATELESS_VP8_FRAME:			return "VP8 Frame Parameters"; + +	/* Colorimetry controls */ +	/* Keep the order of the 'case's the same as in v4l2-controls.h! */ +	case V4L2_CID_COLORIMETRY_CLASS:	return "Colorimetry Controls"; +	case V4L2_CID_COLORIMETRY_HDR10_CLL_INFO:		return "HDR10 Content Light Info"; +	case V4L2_CID_COLORIMETRY_HDR10_MASTERING_DISPLAY:	return "HDR10 Mastering Display";  	default:  		return NULL;  	} @@ -1241,12 +1261,14 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,  	case V4L2_CID_FLASH_READY:  	case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER:  	case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE: +	case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE:  	case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE:  	case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE:  	case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM:  	case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE:  	case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL:  	case V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER: +	case V4L2_CID_MPEG_VIDEO_AU_DELIMITER:  	case V4L2_CID_WIDE_DYNAMIC_RANGE:  	case V4L2_CID_IMAGE_STABILIZATION:  	case V4L2_CID_RDS_RECEPTION: @@ -1276,7 +1298,19 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,  		break;  	case V4L2_CID_MPEG_VIDEO_MV_H_SEARCH_RANGE:  	case V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE: +	case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY: +		*type = V4L2_CTRL_TYPE_INTEGER; +		break; +	case V4L2_CID_MPEG_VIDEO_LTR_COUNT: +		*type = V4L2_CTRL_TYPE_INTEGER; +		break; +	case V4L2_CID_MPEG_VIDEO_FRAME_LTR_INDEX:  		*type = V4L2_CTRL_TYPE_INTEGER; +		*flags |= V4L2_CTRL_FLAG_EXECUTE_ON_WRITE; +		break; +	case V4L2_CID_MPEG_VIDEO_USE_LTR_FRAMES: +		*type = V4L2_CTRL_TYPE_BITMASK; +		*flags |= V4L2_CTRL_FLAG_EXECUTE_ON_WRITE;  		break;  	case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME:  	case V4L2_CID_PAN_RESET: @@ -1326,6 +1360,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,  	case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC:  	case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE:  	case V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE: +	case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE:  	case V4L2_CID_MPEG_VIDEO_MPEG2_LEVEL:  	case V4L2_CID_MPEG_VIDEO_MPEG2_PROFILE:  	case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL: @@ -1389,8 +1424,9 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,  	case V4L2_CID_RF_TUNER_CLASS:  	case V4L2_CID_DETECT_CLASS:  	case V4L2_CID_CODEC_STATELESS_CLASS: +	case V4L2_CID_COLORIMETRY_CLASS:  		*type = V4L2_CTRL_TYPE_CTRL_CLASS; -		/* You can neither read not write these */ +		/* You can neither read nor write these */  		*flags |= V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY;  		*min = *max = *step = *def = 0;  		break; @@ -1430,6 +1466,14 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,  		*max = 0x7fffffffffffffffLL;  		*step = 1;  		break; +	case V4L2_CID_MPEG_VIDEO_DEC_CONCEAL_COLOR: +		*type = V4L2_CTRL_TYPE_INTEGER64; +		*min = 0; +		/* default for 8 bit black, luma is 16, chroma is 128 */ +		*def = 0x8000800010LL; +		*max = 0xffffffffffffLL; +		*step = 1; +		break;  	case V4L2_CID_PIXEL_RATE:  		*type = V4L2_CTRL_TYPE_INTEGER64;  		*flags |= V4L2_CTRL_FLAG_READ_ONLY; @@ -1470,8 +1514,8 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,  	case V4L2_CID_STATELESS_H264_PRED_WEIGHTS:  		*type = V4L2_CTRL_TYPE_H264_PRED_WEIGHTS;  		break; -	case V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER: -		*type = V4L2_CTRL_TYPE_VP8_FRAME_HEADER; +	case V4L2_CID_STATELESS_VP8_FRAME: +		*type = V4L2_CTRL_TYPE_VP8_FRAME;  		break;  	case V4L2_CID_MPEG_VIDEO_HEVC_SPS:  		*type = V4L2_CTRL_TYPE_HEVC_SPS; @@ -1486,6 +1530,12 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,  		*type = V4L2_CTRL_TYPE_AREA;  		*flags |= V4L2_CTRL_FLAG_READ_ONLY;  		break; +	case V4L2_CID_COLORIMETRY_HDR10_CLL_INFO: +		*type = V4L2_CTRL_TYPE_HDR10_CLL_INFO; +		break; +	case V4L2_CID_COLORIMETRY_HDR10_MASTERING_DISPLAY: +		*type = V4L2_CTRL_TYPE_HDR10_MASTERING_DISPLAY; +		break;  	default:  		*type = V4L2_CTRL_TYPE_INTEGER;  		break; @@ -1642,7 +1692,7 @@ static void std_init_compound(const struct v4l2_ctrl *ctrl, u32 idx,  			      union v4l2_ctrl_ptr ptr)  {  	struct v4l2_ctrl_mpeg2_slice_params *p_mpeg2_slice_params; -	struct v4l2_ctrl_vp8_frame_header *p_vp8_frame_header; +	struct v4l2_ctrl_vp8_frame *p_vp8_frame;  	struct v4l2_ctrl_fwht_params *p_fwht_params;  	void *p = ptr.p + idx * ctrl->elem_size; @@ -1666,15 +1716,17 @@ static void std_init_compound(const struct v4l2_ctrl *ctrl, u32 idx,  		p_mpeg2_slice_params->picture.picture_coding_type =  					V4L2_MPEG2_PICTURE_CODING_TYPE_I;  		break; -	case V4L2_CTRL_TYPE_VP8_FRAME_HEADER: -		p_vp8_frame_header = p; -		p_vp8_frame_header->num_dct_parts = 1; +	case V4L2_CTRL_TYPE_VP8_FRAME: +		p_vp8_frame = p; +		p_vp8_frame->num_dct_parts = 1;  		break;  	case V4L2_CTRL_TYPE_FWHT_PARAMS:  		p_fwht_params = p;  		p_fwht_params->version = V4L2_FWHT_VERSION;  		p_fwht_params->width = 1280;  		p_fwht_params->height = 720; +		p_fwht_params->flags = V4L2_FWHT_FL_PIXENC_YUV | +			(2 << V4L2_FWHT_FL_COMPONENTS_NUM_OFFSET);  		break;  	}  } @@ -1781,6 +1833,15 @@ static void std_log(const struct v4l2_ctrl *ctrl)  	case V4L2_CTRL_TYPE_FWHT_PARAMS:  		pr_cont("FWHT_PARAMS");  		break; +	case V4L2_CTRL_TYPE_VP8_FRAME: +		pr_cont("VP8_FRAME"); +		break; +	case V4L2_CTRL_TYPE_HDR10_CLL_INFO: +		pr_cont("HDR10_CLL_INFO"); +		break; +	case V4L2_CTRL_TYPE_HDR10_MASTERING_DISPLAY: +		pr_cont("HDR10_MASTERING_DISPLAY"); +		break;  	default:  		pr_cont("unknown type %d", ctrl->type);  		break; @@ -1823,7 +1884,7 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx,  				 union v4l2_ctrl_ptr ptr)  {  	struct v4l2_ctrl_mpeg2_slice_params *p_mpeg2_slice_params; -	struct v4l2_ctrl_vp8_frame_header *p_vp8_frame_header; +	struct v4l2_ctrl_vp8_frame *p_vp8_frame;  	struct v4l2_ctrl_fwht_params *p_fwht_params;  	struct v4l2_ctrl_h264_sps *p_h264_sps;  	struct v4l2_ctrl_h264_pps *p_h264_pps; @@ -1833,6 +1894,7 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx,  	struct v4l2_ctrl_hevc_sps *p_hevc_sps;  	struct v4l2_ctrl_hevc_pps *p_hevc_pps;  	struct v4l2_ctrl_hevc_slice_params *p_hevc_slice_params; +	struct v4l2_ctrl_hdr10_mastering_display *p_hdr10_mastering;  	struct v4l2_area *area;  	void *p = ptr.p + idx * ctrl->elem_size;  	unsigned int i; @@ -2046,10 +2108,10 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx,  		zero_reserved(*p_h264_dec_params);  		break; -	case V4L2_CTRL_TYPE_VP8_FRAME_HEADER: -		p_vp8_frame_header = p; +	case V4L2_CTRL_TYPE_VP8_FRAME: +		p_vp8_frame = p; -		switch (p_vp8_frame_header->num_dct_parts) { +		switch (p_vp8_frame->num_dct_parts) {  		case 1:  		case 2:  		case 4: @@ -2058,11 +2120,11 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx,  		default:  			return -EINVAL;  		} -		zero_padding(p_vp8_frame_header->segment_header); -		zero_padding(p_vp8_frame_header->lf_header); -		zero_padding(p_vp8_frame_header->quant_header); -		zero_padding(p_vp8_frame_header->entropy_header); -		zero_padding(p_vp8_frame_header->coder_state); +		zero_padding(p_vp8_frame->segment); +		zero_padding(p_vp8_frame->lf); +		zero_padding(p_vp8_frame->quant); +		zero_padding(p_vp8_frame->entropy); +		zero_padding(p_vp8_frame->coder_state);  		break;  	case V4L2_CTRL_TYPE_HEVC_SPS: @@ -2128,6 +2190,53 @@ static int std_validate_compound(const struct v4l2_ctrl *ctrl, u32 idx,  		zero_padding(*p_hevc_slice_params);  		break; +	case V4L2_CTRL_TYPE_HDR10_CLL_INFO: +		break; + +	case V4L2_CTRL_TYPE_HDR10_MASTERING_DISPLAY: +		p_hdr10_mastering = p; + +		for (i = 0; i < 3; ++i) { +			if (p_hdr10_mastering->display_primaries_x[i] < +				V4L2_HDR10_MASTERING_PRIMARIES_X_LOW || +			    p_hdr10_mastering->display_primaries_x[i] > +				V4L2_HDR10_MASTERING_PRIMARIES_X_HIGH || +			    p_hdr10_mastering->display_primaries_y[i] < +				V4L2_HDR10_MASTERING_PRIMARIES_Y_LOW || +			    p_hdr10_mastering->display_primaries_y[i] > +				V4L2_HDR10_MASTERING_PRIMARIES_Y_HIGH) +				return -EINVAL; +		} + +		if (p_hdr10_mastering->white_point_x < +			V4L2_HDR10_MASTERING_WHITE_POINT_X_LOW || +		    p_hdr10_mastering->white_point_x > +			V4L2_HDR10_MASTERING_WHITE_POINT_X_HIGH || +		    p_hdr10_mastering->white_point_y < +			V4L2_HDR10_MASTERING_WHITE_POINT_Y_LOW || +		    p_hdr10_mastering->white_point_y > +			V4L2_HDR10_MASTERING_WHITE_POINT_Y_HIGH) +			return -EINVAL; + +		if (p_hdr10_mastering->max_display_mastering_luminance < +			V4L2_HDR10_MASTERING_MAX_LUMA_LOW || +		    p_hdr10_mastering->max_display_mastering_luminance > +			V4L2_HDR10_MASTERING_MAX_LUMA_HIGH || +		    p_hdr10_mastering->min_display_mastering_luminance < +			V4L2_HDR10_MASTERING_MIN_LUMA_LOW || +		    p_hdr10_mastering->min_display_mastering_luminance > +			V4L2_HDR10_MASTERING_MIN_LUMA_HIGH) +			return -EINVAL; + +		/* The following restriction comes from ITU-T Rec. H.265 spec */ +		if (p_hdr10_mastering->max_display_mastering_luminance == +			V4L2_HDR10_MASTERING_MAX_LUMA_LOW && +		    p_hdr10_mastering->min_display_mastering_luminance == +			V4L2_HDR10_MASTERING_MIN_LUMA_HIGH) +			return -EINVAL; + +		break; +  	case V4L2_CTRL_TYPE_AREA:  		area = p;  		if (!area->width || !area->height) @@ -2395,7 +2504,16 @@ static void new_to_req(struct v4l2_ctrl_ref *ref)  	if (!ref)  		return;  	ptr_to_ptr(ref->ctrl, ref->ctrl->p_new, ref->p_req); -	ref->req = ref; +	ref->valid_p_req = true; +} + +/* Copy the current value to the request value */ +static void cur_to_req(struct v4l2_ctrl_ref *ref) +{ +	if (!ref) +		return; +	ptr_to_ptr(ref->ctrl, ref->ctrl->p_cur, ref->p_req); +	ref->valid_p_req = true;  }  /* Copy the request value to the new value */ @@ -2403,8 +2521,8 @@ static void req_to_new(struct v4l2_ctrl_ref *ref)  {  	if (!ref)  		return; -	if (ref->req) -		ptr_to_ptr(ref->ctrl, ref->req->p_req, ref->ctrl->p_new); +	if (ref->valid_p_req) +		ptr_to_ptr(ref->ctrl, ref->p_req, ref->ctrl->p_new);  	else  		ptr_to_ptr(ref->ctrl, ref->ctrl->p_cur, ref->ctrl->p_new);  } @@ -2541,7 +2659,15 @@ void v4l2_ctrl_handler_free(struct v4l2_ctrl_handler *hdl)  	if (hdl == NULL || hdl->buckets == NULL)  		return; -	if (!hdl->req_obj.req && !list_empty(&hdl->requests)) { +	/* +	 * If the main handler is freed and it is used by handler objects in +	 * outstanding requests, then unbind and put those objects before +	 * freeing the main handler. +	 * +	 * The main handler can be identified by having a NULL ops pointer in +	 * the request object. +	 */ +	if (!hdl->req_obj.ops && !list_empty(&hdl->requests)) {  		struct v4l2_ctrl_handler *req, *next_req;  		list_for_each_entry_safe(req, next_req, &hdl->requests, requests) { @@ -2809,8 +2935,8 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,  	case V4L2_CTRL_TYPE_H264_PRED_WEIGHTS:  		elem_size = sizeof(struct v4l2_ctrl_h264_pred_weights);  		break; -	case V4L2_CTRL_TYPE_VP8_FRAME_HEADER: -		elem_size = sizeof(struct v4l2_ctrl_vp8_frame_header); +	case V4L2_CTRL_TYPE_VP8_FRAME: +		elem_size = sizeof(struct v4l2_ctrl_vp8_frame);  		break;  	case V4L2_CTRL_TYPE_HEVC_SPS:  		elem_size = sizeof(struct v4l2_ctrl_hevc_sps); @@ -2821,6 +2947,12 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,  	case V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS:  		elem_size = sizeof(struct v4l2_ctrl_hevc_slice_params);  		break; +	case V4L2_CTRL_TYPE_HDR10_CLL_INFO: +		elem_size = sizeof(struct v4l2_ctrl_hdr10_cll_info); +		break; +	case V4L2_CTRL_TYPE_HDR10_MASTERING_DISPLAY: +		elem_size = sizeof(struct v4l2_ctrl_hdr10_mastering_display); +		break;  	case V4L2_CTRL_TYPE_AREA:  		elem_size = sizeof(struct v4l2_area);  		break; @@ -3571,39 +3703,8 @@ static void v4l2_ctrl_request_queue(struct media_request_object *obj)  	struct v4l2_ctrl_handler *hdl =  		container_of(obj, struct v4l2_ctrl_handler, req_obj);  	struct v4l2_ctrl_handler *main_hdl = obj->priv; -	struct v4l2_ctrl_handler *prev_hdl = NULL; -	struct v4l2_ctrl_ref *ref_ctrl, *ref_ctrl_prev = NULL;  	mutex_lock(main_hdl->lock); -	if (list_empty(&main_hdl->requests_queued)) -		goto queue; - -	prev_hdl = list_last_entry(&main_hdl->requests_queued, -				   struct v4l2_ctrl_handler, requests_queued); -	/* -	 * Note: prev_hdl and hdl must contain the same list of control -	 * references, so if any differences are detected then that is a -	 * driver bug and the WARN_ON is triggered. -	 */ -	mutex_lock(prev_hdl->lock); -	ref_ctrl_prev = list_first_entry(&prev_hdl->ctrl_refs, -					 struct v4l2_ctrl_ref, node); -	list_for_each_entry(ref_ctrl, &hdl->ctrl_refs, node) { -		if (ref_ctrl->req) -			continue; -		while (ref_ctrl_prev->ctrl->id < ref_ctrl->ctrl->id) { -			/* Should never happen, but just in case... */ -			if (list_is_last(&ref_ctrl_prev->node, -					 &prev_hdl->ctrl_refs)) -				break; -			ref_ctrl_prev = list_next_entry(ref_ctrl_prev, node); -		} -		if (WARN_ON(ref_ctrl_prev->ctrl->id != ref_ctrl->ctrl->id)) -			break; -		ref_ctrl->req = ref_ctrl_prev->req; -	} -	mutex_unlock(prev_hdl->lock); -queue:  	list_add_tail(&hdl->requests_queued, &main_hdl->requests_queued);  	hdl->request_is_queued = true;  	mutex_unlock(main_hdl->lock); @@ -3615,8 +3716,8 @@ static void v4l2_ctrl_request_unbind(struct media_request_object *obj)  		container_of(obj, struct v4l2_ctrl_handler, req_obj);  	struct v4l2_ctrl_handler *main_hdl = obj->priv; -	list_del_init(&hdl->requests);  	mutex_lock(main_hdl->lock); +	list_del_init(&hdl->requests);  	if (hdl->request_is_queued) {  		list_del_init(&hdl->requests_queued);  		hdl->request_is_queued = false; @@ -3660,7 +3761,7 @@ v4l2_ctrl_request_hdl_ctrl_find(struct v4l2_ctrl_handler *hdl, u32 id)  {  	struct v4l2_ctrl_ref *ref = find_ref_lock(hdl, id); -	return (ref && ref->req == ref) ? ref->ctrl : NULL; +	return (ref && ref->valid_p_req) ? ref->ctrl : NULL;  }  EXPORT_SYMBOL_GPL(v4l2_ctrl_request_hdl_ctrl_find); @@ -3675,8 +3776,11 @@ static int v4l2_ctrl_request_bind(struct media_request *req,  	if (!ret) {  		ret = media_request_object_bind(req, &req_ops,  						from, false, &hdl->req_obj); -		if (!ret) +		if (!ret) { +			mutex_lock(from->lock);  			list_add_tail(&hdl->requests, &from->requests); +			mutex_unlock(from->lock); +		}  	}  	return ret;  } @@ -3846,7 +3950,13 @@ static int class_check(struct v4l2_ctrl_handler *hdl, u32 which)  	return find_ref_lock(hdl, which | 1) ? 0 : -EINVAL;  } -/* Get extended controls. Allocates the helpers array if needed. */ +/* + * Get extended controls. Allocates the helpers array if needed. + * + * Note that v4l2_g_ext_ctrls_common() with 'which' set to + * V4L2_CTRL_WHICH_REQUEST_VAL is only called if the request was + * completed, and in that case valid_p_req is true for all controls. + */  static int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl,  				   struct v4l2_ext_controls *cs,  				   struct video_device *vdev) @@ -3855,9 +3965,10 @@ static int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl,  	struct v4l2_ctrl_helper *helpers = helper;  	int ret;  	int i, j; -	bool def_value; +	bool is_default, is_request; -	def_value = (cs->which == V4L2_CTRL_WHICH_DEF_VAL); +	is_default = (cs->which == V4L2_CTRL_WHICH_DEF_VAL); +	is_request = (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL);  	cs->error_idx = cs->count;  	cs->which = V4L2_CTRL_ID2WHICH(cs->which); @@ -3883,11 +3994,9 @@ static int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl,  			ret = -EACCES;  	for (i = 0; !ret && i < cs->count; i++) { -		int (*ctrl_to_user)(struct v4l2_ext_control *c, -				    struct v4l2_ctrl *ctrl);  		struct v4l2_ctrl *master; - -		ctrl_to_user = def_value ? def_to_user : cur_to_user; +		bool is_volatile = false; +		u32 idx = i;  		if (helpers[i].mref == NULL)  			continue; @@ -3897,31 +4006,48 @@ static int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl,  		v4l2_ctrl_lock(master); -		/* g_volatile_ctrl will update the new control values */ -		if (!def_value && +		/* +		 * g_volatile_ctrl will update the new control values. +		 * This makes no sense for V4L2_CTRL_WHICH_DEF_VAL and +		 * V4L2_CTRL_WHICH_REQUEST_VAL. In the case of requests +		 * it is v4l2_ctrl_request_complete() that copies the +		 * volatile controls at the time of request completion +		 * to the request, so you don't want to do that again. +		 */ +		if (!is_default && !is_request &&  		    ((master->flags & V4L2_CTRL_FLAG_VOLATILE) ||  		    (master->has_volatiles && !is_cur_manual(master)))) {  			for (j = 0; j < master->ncontrols; j++)  				cur_to_new(master->cluster[j]);  			ret = call_op(master, g_volatile_ctrl); -			ctrl_to_user = new_to_user; +			is_volatile = true;  		} -		/* If OK, then copy the current (for non-volatile controls) -		   or the new (for volatile controls) control values to the -		   caller */ -		if (!ret) { -			u32 idx = i; -			do { -				if (helpers[idx].ref->req) -					ret = req_to_user(cs->controls + idx, -						helpers[idx].ref->req); -				else -					ret = ctrl_to_user(cs->controls + idx, -						helpers[idx].ref->ctrl); -				idx = helpers[idx].next; -			} while (!ret && idx); +		if (ret) { +			v4l2_ctrl_unlock(master); +			break;  		} + +		/* +		 * Copy the default value (if is_default is true), the +		 * request value (if is_request is true and p_req is valid), +		 * the new volatile value (if is_volatile is true) or the +		 * current value. +		 */ +		do { +			struct v4l2_ctrl_ref *ref = helpers[idx].ref; + +			if (is_default) +				ret = def_to_user(cs->controls + idx, ref->ctrl); +			else if (is_request && ref->valid_p_req) +				ret = req_to_user(cs->controls + idx, ref); +			else if (is_volatile) +				ret = new_to_user(cs->controls + idx, ref->ctrl); +			else +				ret = cur_to_user(cs->controls + idx, ref->ctrl); +			idx = helpers[idx].next; +		} while (!ret && idx); +  		v4l2_ctrl_unlock(master);  	} @@ -4564,8 +4690,6 @@ void v4l2_ctrl_request_complete(struct media_request *req,  		unsigned int i;  		if (ctrl->flags & V4L2_CTRL_FLAG_VOLATILE) { -			ref->req = ref; -  			v4l2_ctrl_lock(master);  			/* g_volatile_ctrl will update the current control values */  			for (i = 0; i < master->ncontrols; i++) @@ -4575,21 +4699,12 @@ void v4l2_ctrl_request_complete(struct media_request *req,  			v4l2_ctrl_unlock(master);  			continue;  		} -		if (ref->req == ref) +		if (ref->valid_p_req)  			continue; +		/* Copy the current control value into the request */  		v4l2_ctrl_lock(ctrl); -		if (ref->req) { -			ptr_to_ptr(ctrl, ref->req->p_req, ref->p_req); -		} else { -			ptr_to_ptr(ctrl, ctrl->p_cur, ref->p_req); -			/* -			 * Set ref->req to ensure that when userspace wants to -			 * obtain the controls of this request it will take -			 * this value and not the current value of the control. -			 */ -			ref->req = ref; -		} +		cur_to_req(ref);  		v4l2_ctrl_unlock(ctrl);  	} @@ -4653,7 +4768,7 @@ int v4l2_ctrl_request_setup(struct media_request *req,  				struct v4l2_ctrl_ref *r =  					find_ref(hdl, master->cluster[i]->id); -				if (r->req && r == r->req) { +				if (r->valid_p_req) {  					have_new_data = true;  					break;  				} | 
