diff options
Diffstat (limited to 'drivers/media/v4l2-core/v4l2-ioctl.c')
| -rw-r--r-- | drivers/media/v4l2-core/v4l2-ioctl.c | 69 | 
1 files changed, 59 insertions, 10 deletions
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 21470de62d72..c314025d977e 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -1007,6 +1007,31 @@ static int check_fmt(struct file *file, enum v4l2_buf_type type)  	return -EINVAL;  } +static void v4l_sanitize_colorspace(u32 pixelformat, u32 *colorspace, +				    u32 *encoding, u32 *quantization, +				    u32 *xfer_func) +{ +	bool is_hsv = pixelformat == V4L2_PIX_FMT_HSV24 || +		      pixelformat == V4L2_PIX_FMT_HSV32; + +	if (!v4l2_is_colorspace_valid(*colorspace)) { +		*colorspace = V4L2_COLORSPACE_DEFAULT; +		*encoding = V4L2_YCBCR_ENC_DEFAULT; +		*quantization = V4L2_QUANTIZATION_DEFAULT; +		*xfer_func = V4L2_XFER_FUNC_DEFAULT; +	} + +	if ((!is_hsv && !v4l2_is_ycbcr_enc_valid(*encoding)) || +	    (is_hsv && !v4l2_is_hsv_enc_valid(*encoding))) +		*encoding = V4L2_YCBCR_ENC_DEFAULT; + +	if (!v4l2_is_quant_valid(*quantization)) +		*quantization = V4L2_QUANTIZATION_DEFAULT; + +	if (!v4l2_is_xfer_func_valid(*xfer_func)) +		*xfer_func = V4L2_XFER_FUNC_DEFAULT; +} +  static void v4l_sanitize_format(struct v4l2_format *fmt)  {  	unsigned int offset; @@ -1026,20 +1051,40 @@ static void v4l_sanitize_format(struct v4l2_format *fmt)  	 * field to the magic value when the extended pixel format structure  	 * isn't used by applications.  	 */ +	if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE || +	    fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { +		if (fmt->fmt.pix.priv != V4L2_PIX_FMT_PRIV_MAGIC) { +			fmt->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; -	if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && -	    fmt->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) -		return; +			offset = offsetof(struct v4l2_pix_format, priv) +			       + sizeof(fmt->fmt.pix.priv); +			memset(((void *)&fmt->fmt.pix) + offset, 0, +			       sizeof(fmt->fmt.pix) - offset); +		} +	} -	if (fmt->fmt.pix.priv == V4L2_PIX_FMT_PRIV_MAGIC) -		return; +	/* Replace invalid colorspace values with defaults. */ +	if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE || +	    fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { +		v4l_sanitize_colorspace(fmt->fmt.pix.pixelformat, +					&fmt->fmt.pix.colorspace, +					&fmt->fmt.pix.ycbcr_enc, +					&fmt->fmt.pix.quantization, +					&fmt->fmt.pix.xfer_func); +	} else if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE || +		   fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { +		u32 ycbcr_enc = fmt->fmt.pix_mp.ycbcr_enc; +		u32 quantization = fmt->fmt.pix_mp.quantization; +		u32 xfer_func = fmt->fmt.pix_mp.xfer_func; -	fmt->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; +		v4l_sanitize_colorspace(fmt->fmt.pix_mp.pixelformat, +					&fmt->fmt.pix_mp.colorspace, &ycbcr_enc, +					&quantization, &xfer_func); -	offset = offsetof(struct v4l2_pix_format, priv) -	       + sizeof(fmt->fmt.pix.priv); -	memset(((void *)&fmt->fmt.pix) + offset, 0, -	       sizeof(fmt->fmt.pix) - offset); +		fmt->fmt.pix_mp.ycbcr_enc = ycbcr_enc; +		fmt->fmt.pix_mp.quantization = quantization; +		fmt->fmt.pix_mp.xfer_func = xfer_func; +	}  }  static int v4l_querycap(const struct v4l2_ioctl_ops *ops, @@ -1296,6 +1341,8 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)  	case V4L2_PIX_FMT_XYUV32:	descr = "32-bit XYUV 8-8-8-8"; break;  	case V4L2_PIX_FMT_VUYA32:	descr = "32-bit VUYA 8-8-8-8"; break;  	case V4L2_PIX_FMT_VUYX32:	descr = "32-bit VUYX 8-8-8-8"; break; +	case V4L2_PIX_FMT_YUVA32:	descr = "32-bit YUVA 8-8-8-8"; break; +	case V4L2_PIX_FMT_YUVX32:	descr = "32-bit YUVX 8-8-8-8"; break;  	case V4L2_PIX_FMT_YUV410:	descr = "Planar YUV 4:1:0"; break;  	case V4L2_PIX_FMT_YUV420:	descr = "Planar YUV 4:2:0"; break;  	case V4L2_PIX_FMT_HI240:	descr = "8-bit Dithered RGB (BTTV)"; break; @@ -1306,9 +1353,11 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)  	case V4L2_PIX_FMT_NV61:		descr = "Y/CrCb 4:2:2"; break;  	case V4L2_PIX_FMT_NV24:		descr = "Y/CbCr 4:4:4"; break;  	case V4L2_PIX_FMT_NV42:		descr = "Y/CrCb 4:4:4"; break; +	case V4L2_PIX_FMT_P010:		descr = "10-bit Y/CbCr 4:2:0"; break;  	case V4L2_PIX_FMT_NV12_4L4:	descr = "Y/CbCr 4:2:0 (4x4 Linear)"; break;  	case V4L2_PIX_FMT_NV12_16L16:	descr = "Y/CbCr 4:2:0 (16x16 Linear)"; break;  	case V4L2_PIX_FMT_NV12_32L32:   descr = "Y/CbCr 4:2:0 (32x32 Linear)"; break; +	case V4L2_PIX_FMT_P010_4L4:	descr = "10-bit Y/CbCr 4:2:0 (4x4 Linear)"; break;  	case V4L2_PIX_FMT_NV12M:	descr = "Y/CbCr 4:2:0 (N-C)"; break;  	case V4L2_PIX_FMT_NV21M:	descr = "Y/CrCb 4:2:0 (N-C)"; break;  	case V4L2_PIX_FMT_NV16M:	descr = "Y/CbCr 4:2:2 (N-C)"; break;  | 
