bcm27xx: update 5.4 patches from RPi foundation
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
This commit is contained in:
		| @@ -243,6 +243,8 @@ CONFIG_HAVE_SYSCALL_TRACEPOINTS=y | ||||
| CONFIG_HAVE_UID16=y | ||||
| CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y | ||||
| CONFIG_HW_CONSOLE=y | ||||
| CONFIG_HZ=100 | ||||
| CONFIG_HZ_100=y | ||||
| CONFIG_HZ_FIXED=0 | ||||
| CONFIG_I2C=y | ||||
| # CONFIG_I2C_BCM2708 is not set | ||||
|   | ||||
| @@ -311,6 +311,8 @@ CONFIG_HIGHMEM=y | ||||
| CONFIG_HIGHPTE=y | ||||
| CONFIG_HOTPLUG_CPU=y | ||||
| CONFIG_HW_CONSOLE=y | ||||
| CONFIG_HZ=100 | ||||
| CONFIG_HZ_100=y | ||||
| CONFIG_HZ_FIXED=0 | ||||
| CONFIG_I2C=y | ||||
| # CONFIG_I2C_BCM2708 is not set | ||||
|   | ||||
| @@ -367,6 +367,8 @@ CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y | ||||
| CONFIG_HOLES_IN_ZONE=y | ||||
| CONFIG_HOTPLUG_CPU=y | ||||
| CONFIG_HW_CONSOLE=y | ||||
| CONFIG_HZ=250 | ||||
| CONFIG_HZ_250=y | ||||
| CONFIG_I2C=y | ||||
| # CONFIG_I2C_BCM2708 is not set | ||||
| CONFIG_I2C_BOARDINFO=y | ||||
|   | ||||
| @@ -373,6 +373,8 @@ CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y | ||||
| CONFIG_HOLES_IN_ZONE=y | ||||
| CONFIG_HOTPLUG_CPU=y | ||||
| CONFIG_HW_CONSOLE=y | ||||
| CONFIG_HZ=250 | ||||
| CONFIG_HZ_250=y | ||||
| CONFIG_I2C=y | ||||
| # CONFIG_I2C_BCM2708 is not set | ||||
| CONFIG_I2C_BOARDINFO=y | ||||
|   | ||||
| @@ -0,0 +1,89 @@ | ||||
| From 12b60ef71cc005ee7290f692169d46a7e78df01a Mon Sep 17 00:00:00 2001 | ||||
| From: Yukimasa Sugizaki <4298265+Terminus-IMRC@users.noreply.github.com> | ||||
| Date: Fri, 20 Mar 2020 19:01:23 +0900 | ||||
| Subject: [PATCH] drm/v3d: Replace wait_for macros to remove use of | ||||
|  msleep (#3510) | ||||
|  | ||||
| commit 9daee6141cc9c75b09659b02b1cb9eeb2f5e16cc upstream. | ||||
|  | ||||
| The wait_for macro's for Broadcom V3D driver used msleep, which is | ||||
| inappropriate due to its inaccuracy at low values (minimum wait time | ||||
| is about 30ms on the Raspberry Pi).  This sleep was triggering in | ||||
| v3d_clean_caches(), causing us to only be able to dispatch ~33 compute | ||||
| jobs per second. | ||||
|  | ||||
| This patch replaces the macro with the one from the Intel i915 version | ||||
| which uses usleep_range to provide more accurate waits. | ||||
|  | ||||
| v2: Split from the vc4 patch so that we can confidently apply to | ||||
|     stable (by anholt) | ||||
|  | ||||
| Signed-off-by: James Hughes <james.hughes@raspberrypi.com> | ||||
| Signed-off-by: Eric Anholt <eric@anholt.net> | ||||
| Link: https://patchwork.freedesktop.org/patch/msgid/20200217153145.13780-1-james.hughes@raspberrypi.com | ||||
| Link: https://github.com/raspberrypi/linux/issues/3460 | ||||
| Fixes: 57692c94dcbe ("drm/v3d: Introduce a new DRM driver for Broadcom V3D V3.x+") | ||||
|  | ||||
| Co-authored-by: James Hughes <james.hughes@raspberrypi.com> | ||||
| --- | ||||
|  drivers/gpu/drm/v3d/v3d_drv.h | 41 ++++++++++++++++++++++++----------- | ||||
|  1 file changed, 28 insertions(+), 13 deletions(-) | ||||
|  | ||||
| --- a/drivers/gpu/drm/v3d/v3d_drv.h | ||||
| +++ b/drivers/gpu/drm/v3d/v3d_drv.h | ||||
| @@ -260,27 +260,42 @@ struct v3d_csd_job { | ||||
|  }; | ||||
|   | ||||
|  /** | ||||
| - * _wait_for - magic (register) wait macro | ||||
| + * __wait_for - magic wait macro | ||||
|   * | ||||
| - * Does the right thing for modeset paths when run under kdgb or similar atomic | ||||
| - * contexts. Note that it's important that we check the condition again after | ||||
| - * having timed out, since the timeout could be due to preemption or similar and | ||||
| - * we've never had a chance to check the condition before the timeout. | ||||
| + * Macro to help avoid open coding check/wait/timeout patterns. Note that it's | ||||
| + * important that we check the condition again after having timed out, since the | ||||
| + * timeout could be due to preemption or similar and we've never had a chance to | ||||
| + * check the condition before the timeout. | ||||
|   */ | ||||
| -#define wait_for(COND, MS) ({ \ | ||||
| -	unsigned long timeout__ = jiffies + msecs_to_jiffies(MS) + 1;	\ | ||||
| -	int ret__ = 0;							\ | ||||
| -	while (!(COND)) {						\ | ||||
| -		if (time_after(jiffies, timeout__)) {			\ | ||||
| -			if (!(COND))					\ | ||||
| -				ret__ = -ETIMEDOUT;			\ | ||||
| +#define __wait_for(OP, COND, US, Wmin, Wmax) ({ \ | ||||
| +	const ktime_t end__ = ktime_add_ns(ktime_get_raw(), 1000ll * (US)); \ | ||||
| +	long wait__ = (Wmin); /* recommended min for usleep is 10 us */	\ | ||||
| +	int ret__;							\ | ||||
| +	might_sleep();							\ | ||||
| +	for (;;) {							\ | ||||
| +		const bool expired__ = ktime_after(ktime_get_raw(), end__); \ | ||||
| +		OP;							\ | ||||
| +		/* Guarantee COND check prior to timeout */		\ | ||||
| +		barrier();						\ | ||||
| +		if (COND) {						\ | ||||
| +			ret__ = 0;					\ | ||||
|  			break;						\ | ||||
|  		}							\ | ||||
| -		msleep(1);					\ | ||||
| +		if (expired__) {					\ | ||||
| +			ret__ = -ETIMEDOUT;				\ | ||||
| +			break;						\ | ||||
| +		}							\ | ||||
| +		usleep_range(wait__, wait__ * 2);			\ | ||||
| +		if (wait__ < (Wmax))					\ | ||||
| +			wait__ <<= 1;					\ | ||||
|  	}								\ | ||||
|  	ret__;								\ | ||||
|  }) | ||||
|   | ||||
| +#define _wait_for(COND, US, Wmin, Wmax)	__wait_for(, (COND), (US), (Wmin), \ | ||||
| +						   (Wmax)) | ||||
| +#define wait_for(COND, MS)		_wait_for((COND), (MS) * 1000, 10, 1000) | ||||
| + | ||||
|  static inline unsigned long nsecs_to_jiffies_timeout(const u64 n) | ||||
|  { | ||||
|  	/* nsecs_to_jiffies64() does not guard against overflow */ | ||||
| @@ -0,0 +1,96 @@ | ||||
| From 863dace20e48954a7e013a2e88e27c692ce165b0 Mon Sep 17 00:00:00 2001 | ||||
| From: Nick B <nick@pelagiris.org> | ||||
| Date: Mon, 9 Mar 2020 09:05:39 -0400 | ||||
| Subject: [PATCH] Reduce noise from rpi poe hat fan | ||||
|  | ||||
| This adds 2 extra states, at 40c and 45c, with PWM of 31 and 63 (out | ||||
| of 255) for the rpi poe hat fan.  This significantly improves user | ||||
| experience by providing a smoother ramp up of the fan, from a pwm 0 | ||||
| to 31 to 63 then finally to 150, and additionally makes it very easy | ||||
| for users to further tweak the values as needed for their specific | ||||
| application. | ||||
|  | ||||
| The possible concerns I have are that a hysteresis of 2000 (2c) could | ||||
| be too narrow, and that running the fan more at a reduced temperature | ||||
| (40000 - 40c) could cause problems. | ||||
|  | ||||
| Signed-off-by: Nick B <nick@pelagiris.org> | ||||
| --- | ||||
|  .../arm/boot/dts/overlays/rpi-poe-overlay.dts | 35 ++++++++++++++++--- | ||||
|  1 file changed, 30 insertions(+), 5 deletions(-) | ||||
|  | ||||
| --- a/arch/arm/boot/dts/overlays/rpi-poe-overlay.dts | ||||
| +++ b/arch/arm/boot/dts/overlays/rpi-poe-overlay.dts | ||||
| @@ -14,9 +14,9 @@ | ||||
|  				compatible = "raspberrypi,rpi-poe-fan"; | ||||
|  				firmware = <&firmware>; | ||||
|  				cooling-min-state = <0>; | ||||
| -				cooling-max-state = <2>; | ||||
| +				cooling-max-state = <4>; | ||||
|  				#cooling-cells = <2>; | ||||
| -				cooling-levels = <0 150 255>; | ||||
| +				cooling-levels = <0 31 63 150 255>; | ||||
|  				status = "okay"; | ||||
|  			}; | ||||
|  		}; | ||||
| @@ -27,12 +27,21 @@ | ||||
|  		__overlay__ { | ||||
|  			trips { | ||||
|  				trip0: trip0 { | ||||
| -					temperature = <50000>; | ||||
| -					hysteresis = <5000>; | ||||
| +					temperature = <40000>; | ||||
| +					hysteresis = <2000>; | ||||
|  					type = "active"; | ||||
|  				}; | ||||
|  				trip1: trip1 { | ||||
| - | ||||
| +					temperature = <45000>; | ||||
| +					hysteresis = <2000>; | ||||
| +					type = "active"; | ||||
| +				}; | ||||
| +				trip2: trip2 { | ||||
| +					temperature = <50000>; | ||||
| +					hysteresis = <2000>; | ||||
| +					type = "active"; | ||||
| +				}; | ||||
| +				trip3: trip3 { | ||||
|  					temperature = <55000>; | ||||
|  					hysteresis = <5000>; | ||||
|  					type = "active"; | ||||
| @@ -47,6 +56,14 @@ | ||||
|  					trip = <&trip1>; | ||||
|  					cooling-device = <&fan0 1 2>; | ||||
|  				}; | ||||
| +				map2 { | ||||
| +					trip = <&trip2>; | ||||
| +					cooling-device = <&fan0 2 3>; | ||||
| +				}; | ||||
| +				map3 { | ||||
| +					trip = <&trip3>; | ||||
| +					cooling-device = <&fan0 3 4>; | ||||
| +				}; | ||||
|  			}; | ||||
|  		}; | ||||
|  	}; | ||||
| @@ -58,6 +75,10 @@ | ||||
|  			poe_fan_temp0_hyst =	<&trip0>,"hysteresis:0"; | ||||
|  			poe_fan_temp1 =		<&trip1>,"temperature:0"; | ||||
|  			poe_fan_temp1_hyst =	<&trip1>,"hysteresis:0"; | ||||
| +			poe_fan_temp2 =		<&trip2>,"temperature:0"; | ||||
| +			poe_fan_temp2_hyst =	<&trip2>,"hysteresis:0"; | ||||
| +			poe_fan_temp3 =		<&trip3>,"temperature:0"; | ||||
| +			poe_fan_temp3_hyst =	<&trip3>,"hysteresis:0"; | ||||
|  		}; | ||||
|  	}; | ||||
|   | ||||
| @@ -66,5 +87,9 @@ | ||||
|  		poe_fan_temp0_hyst =	<&trip0>,"hysteresis:0"; | ||||
|  		poe_fan_temp1 =		<&trip1>,"temperature:0"; | ||||
|  		poe_fan_temp1_hyst =	<&trip1>,"hysteresis:0"; | ||||
| +		poe_fan_temp2 =		<&trip2>,"temperature:0"; | ||||
| +		poe_fan_temp2_hyst =	<&trip2>,"hysteresis:0"; | ||||
| +		poe_fan_temp3 =		<&trip3>,"temperature:0"; | ||||
| +		poe_fan_temp3_hyst =	<&trip3>,"hysteresis:0"; | ||||
|  	}; | ||||
|  }; | ||||
| @@ -1,4 +1,4 @@ | ||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 | ||||
| From 60f3874207c50db6f6d9dbac40977843cb77acd5 Mon Sep 17 00:00:00 2001 | ||||
| From: =?UTF-8?q?Petr=20=C5=A0tetiar?= <ynezz@true.cz> | ||||
| Date: Sat, 7 Mar 2020 22:37:52 +0100 | ||||
| Subject: [PATCH] add Sensirion SPS30 to i2c-sensor overlay | ||||
| @@ -10,12 +10,14 @@ Add support for Sensirion SPS30 particulate matter sensor with fixed | ||||
| address 0x69. | ||||
| 
 | ||||
| Signed-off-by: Petr Štetiar <ynezz@true.cz> | ||||
| ---
 | ||||
|  arch/arm/boot/dts/overlays/README                 |  3 +++ | ||||
|  arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts | 15 +++++++++++++++ | ||||
|  2 files changed, 18 insertions(+) | ||||
| 
 | ||||
| diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README
 | ||||
| index 62ad35f78bad..0d7d00ac92c4 100644
 | ||||
| --- a/arch/arm/boot/dts/overlays/README
 | ||||
| +++ b/arch/arm/boot/dts/overlays/README
 | ||||
| @@ -1261,6 +1261,9 @@ Params: addr                    Set the address for the BME280, BME680, BMP280,
 | ||||
| @@ -1261,6 +1261,9 @@ Params: addr                    Set the
 | ||||
|          si7020                  Select the Silicon Labs Si7013/20/21 humidity/ | ||||
|                                  temperature sensor | ||||
|   | ||||
| @@ -25,8 +27,6 @@ index 62ad35f78bad..0d7d00ac92c4 100644 | ||||
|          tmp102                  Select the Texas Instruments TMP102 temp sensor | ||||
|                                  Valid addresses 0x48-0x4b, default 0x48 | ||||
|   | ||||
| diff --git a/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts b/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts
 | ||||
| index 40881d72a157..ce97837b0db5 100644
 | ||||
| --- a/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts
 | ||||
| +++ b/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts
 | ||||
| @@ -231,6 +231,20 @@
 | ||||
| @@ -0,0 +1,157 @@ | ||||
| From 4af6218f1d01e5ae54dc43e4bd2421617c777570 Mon Sep 17 00:00:00 2001 | ||||
| From: Ricardo Ribalda Delgado <ribalda@kernel.org> | ||||
| Date: Mon, 7 Oct 2019 12:06:31 -0300 | ||||
| Subject: [PATCH] media: add V4L2_CTRL_TYPE_AREA control type | ||||
|  | ||||
| Commit d1dc49370f8371b00e682ac409aa1987ce641e93 upstream. | ||||
|  | ||||
| This type contains the width and the height of a rectangular area. | ||||
|  | ||||
| Reviewed-by: Jacopo Mondi <jacopo@jmondi.org> | ||||
| Signed-off-by: Ricardo Ribalda Delgado <ribalda@kernel.org> | ||||
| Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> | ||||
| Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org> | ||||
| --- | ||||
|  drivers/media/v4l2-core/v4l2-ctrls.c | 21 ++++++++++++++ | ||||
|  include/media/v4l2-ctrls.h           | 42 ++++++++++++++++++++++++++++ | ||||
|  include/uapi/linux/videodev2.h       |  6 ++++ | ||||
|  3 files changed, 69 insertions(+) | ||||
|  | ||||
| --- a/drivers/media/v4l2-core/v4l2-ctrls.c | ||||
| +++ b/drivers/media/v4l2-core/v4l2-ctrls.c | ||||
| @@ -1673,6 +1673,7 @@ static int std_validate_compound(const s | ||||
|  { | ||||
|  	struct v4l2_ctrl_mpeg2_slice_params *p_mpeg2_slice_params; | ||||
|  	struct v4l2_ctrl_vp8_frame_header *p_vp8_frame_header; | ||||
| +	struct v4l2_area *area; | ||||
|  	void *p = ptr.p + idx * ctrl->elem_size; | ||||
|   | ||||
|  	switch ((u32)ctrl->type) { | ||||
| @@ -1749,6 +1750,11 @@ static int std_validate_compound(const s | ||||
|  		zero_padding(p_vp8_frame_header->entropy_header); | ||||
|  		zero_padding(p_vp8_frame_header->coder_state); | ||||
|  		break; | ||||
| +	case V4L2_CTRL_TYPE_AREA: | ||||
| +		area = p; | ||||
| +		if (!area->width || !area->height) | ||||
| +			return -EINVAL; | ||||
| +		break; | ||||
|  	default: | ||||
|  		return -EINVAL; | ||||
|  	} | ||||
| @@ -2422,6 +2428,9 @@ static struct v4l2_ctrl *v4l2_ctrl_new(s | ||||
|  	case V4L2_CTRL_TYPE_VP8_FRAME_HEADER: | ||||
|  		elem_size = sizeof(struct v4l2_ctrl_vp8_frame_header); | ||||
|  		break; | ||||
| +	case V4L2_CTRL_TYPE_AREA: | ||||
| +		elem_size = sizeof(struct v4l2_area); | ||||
| +		break; | ||||
|  	default: | ||||
|  		if (type < V4L2_CTRL_COMPOUND_TYPES) | ||||
|  			elem_size = sizeof(s32); | ||||
| @@ -4086,6 +4095,18 @@ int __v4l2_ctrl_s_ctrl_string(struct v4l | ||||
|  } | ||||
|  EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_string); | ||||
|   | ||||
| +int __v4l2_ctrl_s_ctrl_area(struct v4l2_ctrl *ctrl, | ||||
| +			    const struct v4l2_area *area) | ||||
| +{ | ||||
| +	lockdep_assert_held(ctrl->handler->lock); | ||||
| + | ||||
| +	/* It's a driver bug if this happens. */ | ||||
| +	WARN_ON(ctrl->type != V4L2_CTRL_TYPE_AREA); | ||||
| +	*ctrl->p_new.p_area = *area; | ||||
| +	return set_ctrl(NULL, ctrl, 0); | ||||
| +} | ||||
| +EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_area); | ||||
| + | ||||
|  void v4l2_ctrl_request_complete(struct media_request *req, | ||||
|  				struct v4l2_ctrl_handler *main_hdl) | ||||
|  { | ||||
| --- a/include/media/v4l2-ctrls.h | ||||
| +++ b/include/media/v4l2-ctrls.h | ||||
| @@ -50,6 +50,7 @@ struct poll_table_struct; | ||||
|   * @p_h264_slice_params:	Pointer to a struct v4l2_ctrl_h264_slice_params. | ||||
|   * @p_h264_decode_params:	Pointer to a struct v4l2_ctrl_h264_decode_params. | ||||
|   * @p_vp8_frame_header:		Pointer to a VP8 frame header structure. | ||||
| + * @p_area:			Pointer to an area. | ||||
|   * @p:				Pointer to a compound value. | ||||
|   */ | ||||
|  union v4l2_ctrl_ptr { | ||||
| @@ -68,6 +69,7 @@ union v4l2_ctrl_ptr { | ||||
|  	struct v4l2_ctrl_h264_slice_params *p_h264_slice_params; | ||||
|  	struct v4l2_ctrl_h264_decode_params *p_h264_decode_params; | ||||
|  	struct v4l2_ctrl_vp8_frame_header *p_vp8_frame_header; | ||||
| +	struct v4l2_area *p_area; | ||||
|  	void *p; | ||||
|  }; | ||||
|   | ||||
| @@ -1063,6 +1065,46 @@ static inline int v4l2_ctrl_s_ctrl_strin | ||||
|  	v4l2_ctrl_unlock(ctrl); | ||||
|   | ||||
|  	return rval; | ||||
| +} | ||||
| + | ||||
| +/** | ||||
| + * __v4l2_ctrl_s_ctrl_area() - Unlocked variant of v4l2_ctrl_s_ctrl_area(). | ||||
| + * | ||||
| + * @ctrl:	The control. | ||||
| + * @area:	The new area. | ||||
| + * | ||||
| + * This sets the control's new area safely by going through the control | ||||
| + * framework. This function assumes the control's handler is already locked, | ||||
| + * allowing it to be used from within the &v4l2_ctrl_ops functions. | ||||
| + * | ||||
| + * This function is for area type controls only. | ||||
| + */ | ||||
| +int __v4l2_ctrl_s_ctrl_area(struct v4l2_ctrl *ctrl, | ||||
| +			    const struct v4l2_area *area); | ||||
| + | ||||
| +/** | ||||
| + * v4l2_ctrl_s_ctrl_area() - Helper function to set a control's area value | ||||
| + *	 from within a driver. | ||||
| + * | ||||
| + * @ctrl:	The control. | ||||
| + * @area:	The new area. | ||||
| + * | ||||
| + * This sets the control's new area safely by going through the control | ||||
| + * framework. This function will lock the control's handler, so it cannot be | ||||
| + * used from within the &v4l2_ctrl_ops functions. | ||||
| + * | ||||
| + * This function is for area type controls only. | ||||
| + */ | ||||
| +static inline int v4l2_ctrl_s_ctrl_area(struct v4l2_ctrl *ctrl, | ||||
| +					const struct v4l2_area *area) | ||||
| +{ | ||||
| +	int rval; | ||||
| + | ||||
| +	v4l2_ctrl_lock(ctrl); | ||||
| +	rval = __v4l2_ctrl_s_ctrl_area(ctrl, area); | ||||
| +	v4l2_ctrl_unlock(ctrl); | ||||
| + | ||||
| +	return rval; | ||||
|  } | ||||
|   | ||||
|  /* Internal helper functions that deal with control events. */ | ||||
| --- a/include/uapi/linux/videodev2.h | ||||
| +++ b/include/uapi/linux/videodev2.h | ||||
| @@ -427,6 +427,11 @@ struct v4l2_fract { | ||||
|  	__u32   denominator; | ||||
|  }; | ||||
|   | ||||
| +struct v4l2_area { | ||||
| +	__u32   width; | ||||
| +	__u32   height; | ||||
| +}; | ||||
| + | ||||
|  /** | ||||
|    * struct v4l2_capability - Describes V4L2 device caps returned by VIDIOC_QUERYCAP | ||||
|    * | ||||
| @@ -1725,6 +1730,7 @@ enum v4l2_ctrl_type { | ||||
|  	V4L2_CTRL_TYPE_U8	     = 0x0100, | ||||
|  	V4L2_CTRL_TYPE_U16	     = 0x0101, | ||||
|  	V4L2_CTRL_TYPE_U32	     = 0x0102, | ||||
| +	V4L2_CTRL_TYPE_AREA          = 0x0106, | ||||
|  }; | ||||
|   | ||||
|  /*  Used in the VIDIOC_QUERYCTRL ioctl for querying controls */ | ||||
| @@ -0,0 +1,52 @@ | ||||
| From 12eba72027d415bb3dfd4c8124813a322b27c793 Mon Sep 17 00:00:00 2001 | ||||
| From: Ricardo Ribalda Delgado <ribalda@kernel.org> | ||||
| Date: Mon, 7 Oct 2019 12:06:33 -0300 | ||||
| Subject: [PATCH] media: add V4L2_CID_UNIT_CELL_SIZE control | ||||
|  | ||||
| Commit 61fd036d01111679b01e4b92e6bd0cdd33809aea upstream. | ||||
|  | ||||
| This control returns the unit cell size in nanometres. The struct provides | ||||
| the width and the height in separated fields to take into consideration | ||||
| asymmetric pixels and/or hardware binning. | ||||
| This control is required for automatic calibration of sensors/cameras. | ||||
|  | ||||
| Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de> | ||||
| Signed-off-by: Ricardo Ribalda Delgado <ribalda@kernel.org> | ||||
| Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> | ||||
| Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org> | ||||
| --- | ||||
|  drivers/media/v4l2-core/v4l2-ctrls.c | 5 +++++ | ||||
|  include/uapi/linux/v4l2-controls.h   | 1 + | ||||
|  2 files changed, 6 insertions(+) | ||||
|  | ||||
| --- a/drivers/media/v4l2-core/v4l2-ctrls.c | ||||
| +++ b/drivers/media/v4l2-core/v4l2-ctrls.c | ||||
| @@ -995,6 +995,7 @@ const char *v4l2_ctrl_get_name(u32 id) | ||||
|  	case V4L2_CID_AUTO_FOCUS_RANGE:		return "Auto Focus, Range"; | ||||
|  	case V4L2_CID_PAN_SPEED:		return "Pan, Speed"; | ||||
|  	case V4L2_CID_TILT_SPEED:		return "Tilt, Speed"; | ||||
| +	case V4L2_CID_UNIT_CELL_SIZE:		return "Unit Cell Size"; | ||||
|   | ||||
|  	/* FM Radio Modulator controls */ | ||||
|  	/* Keep the order of the 'case's the same as in v4l2-controls.h! */ | ||||
| @@ -1376,6 +1377,10 @@ void v4l2_ctrl_fill(u32 id, const char * | ||||
|  	case V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER: | ||||
|  		*type = V4L2_CTRL_TYPE_VP8_FRAME_HEADER; | ||||
|  		break; | ||||
| +	case V4L2_CID_UNIT_CELL_SIZE: | ||||
| +		*type = V4L2_CTRL_TYPE_AREA; | ||||
| +		*flags |= V4L2_CTRL_FLAG_READ_ONLY; | ||||
| +		break; | ||||
|  	default: | ||||
|  		*type = V4L2_CTRL_TYPE_INTEGER; | ||||
|  		break; | ||||
| --- a/include/uapi/linux/v4l2-controls.h | ||||
| +++ b/include/uapi/linux/v4l2-controls.h | ||||
| @@ -1035,6 +1035,7 @@ enum v4l2_jpeg_chroma_subsampling { | ||||
|  #define V4L2_CID_TEST_PATTERN_GREENR		(V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 5) | ||||
|  #define V4L2_CID_TEST_PATTERN_BLUE		(V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 6) | ||||
|  #define V4L2_CID_TEST_PATTERN_GREENB		(V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 7) | ||||
| +#define V4L2_CID_UNIT_CELL_SIZE			(V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 8) | ||||
|   | ||||
|   | ||||
|  /* Image processing controls */ | ||||
| @@ -0,0 +1,228 @@ | ||||
| From c63ea6a840ad87e32239eb6b771ac8bbc3279b54 Mon Sep 17 00:00:00 2001 | ||||
| From: Benoit Parrot <bparrot@ti.com> | ||||
| Date: Mon, 7 Oct 2019 12:10:07 -0300 | ||||
| Subject: [PATCH] media: v4l2-common: add pixel encoding support | ||||
|  | ||||
| Commit d5a897c8428b38053df4b427a4277b1a0722bfa0 upstream. | ||||
|  | ||||
| It is often useful to figure out if a pixel_format is either YUV or RGB | ||||
| especially for driver who can perform the pixel encoding conversion. | ||||
|  | ||||
| Instead of having each driver implement its own "is_this_yuv/rgb" | ||||
| function based on a restricted set of pixel value, it is better to do | ||||
| this in centralized manner. | ||||
|  | ||||
| We therefore add a pixel_enc member to the v4l2_format_info structure to | ||||
| quickly identify the related pixel encoding. | ||||
| And add helper functions to check pixel encoding. | ||||
|  | ||||
| Signed-off-by: Benoit Parrot <bparrot@ti.com> | ||||
| Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> | ||||
| Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org> | ||||
| --- | ||||
|  drivers/media/v4l2-core/v4l2-common.c | 126 +++++++++++++------------- | ||||
|  include/media/v4l2-common.h           |  33 ++++++- | ||||
|  2 files changed, 95 insertions(+), 64 deletions(-) | ||||
|  | ||||
| --- a/drivers/media/v4l2-core/v4l2-common.c | ||||
| +++ b/drivers/media/v4l2-core/v4l2-common.c | ||||
| @@ -236,77 +236,77 @@ const struct v4l2_format_info *v4l2_form | ||||
|  { | ||||
|  	static const struct v4l2_format_info formats[] = { | ||||
|  		/* RGB formats */ | ||||
| -		{ .format = V4L2_PIX_FMT_BGR24,   .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_RGB24,   .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_HSV24,   .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_BGR32,   .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_XBGR32,  .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_BGRX32,  .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_RGB32,   .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_XRGB32,  .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_RGBX32,  .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_HSV32,   .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_ARGB32,  .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_RGBA32,  .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_ABGR32,  .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_BGRA32,  .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_GREY,    .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_BGR24,   .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_RGB24,   .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_HSV24,   .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 3, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_BGR32,   .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_XBGR32,  .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_BGRX32,  .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_RGB32,   .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_XRGB32,  .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_RGBX32,  .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_HSV32,   .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_ARGB32,  .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_RGBA32,  .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_ABGR32,  .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_BGRA32,  .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_GREY,    .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
|   | ||||
|  		/* YUV packed formats */ | ||||
| -		{ .format = V4L2_PIX_FMT_YUYV,    .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_YVYU,    .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_UYVY,    .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_VYUY,    .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_YUYV,    .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_YVYU,    .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_UYVY,    .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_VYUY,    .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 }, | ||||
|   | ||||
|  		/* YUV planar formats */ | ||||
| -		{ .format = V4L2_PIX_FMT_NV12,    .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 }, | ||||
| -		{ .format = V4L2_PIX_FMT_NV21,    .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 }, | ||||
| -		{ .format = V4L2_PIX_FMT_NV16,    .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_NV61,    .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_NV24,    .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_NV42,    .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| - | ||||
| -		{ .format = V4L2_PIX_FMT_YUV410,  .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 4 }, | ||||
| -		{ .format = V4L2_PIX_FMT_YVU410,  .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 4 }, | ||||
| -		{ .format = V4L2_PIX_FMT_YUV411P, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_YUV420,  .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 }, | ||||
| -		{ .format = V4L2_PIX_FMT_YVU420,  .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 }, | ||||
| -		{ .format = V4L2_PIX_FMT_YUV422P, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_NV12,    .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 }, | ||||
| +		{ .format = V4L2_PIX_FMT_NV21,    .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 }, | ||||
| +		{ .format = V4L2_PIX_FMT_NV16,    .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_NV61,    .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_NV24,    .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_NV42,    .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| + | ||||
| +		{ .format = V4L2_PIX_FMT_YUV410,  .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 4 }, | ||||
| +		{ .format = V4L2_PIX_FMT_YVU410,  .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 4 }, | ||||
| +		{ .format = V4L2_PIX_FMT_YUV411P, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 4, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_YUV420,  .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 }, | ||||
| +		{ .format = V4L2_PIX_FMT_YVU420,  .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 }, | ||||
| +		{ .format = V4L2_PIX_FMT_YUV422P, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 1 }, | ||||
|   | ||||
|  		/* YUV planar formats, non contiguous variant */ | ||||
| -		{ .format = V4L2_PIX_FMT_YUV420M, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 }, | ||||
| -		{ .format = V4L2_PIX_FMT_YVU420M, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 }, | ||||
| -		{ .format = V4L2_PIX_FMT_YUV422M, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_YVU422M, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_YUV444M, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_YVU444M, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| - | ||||
| -		{ .format = V4L2_PIX_FMT_NV12M,   .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 }, | ||||
| -		{ .format = V4L2_PIX_FMT_NV21M,   .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 }, | ||||
| -		{ .format = V4L2_PIX_FMT_NV16M,   .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_NV61M,   .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_YUV420M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 }, | ||||
| +		{ .format = V4L2_PIX_FMT_YVU420M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 2 }, | ||||
| +		{ .format = V4L2_PIX_FMT_YUV422M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_YVU422M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 2, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_YUV444M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_YVU444M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 3, .comp_planes = 3, .bpp = { 1, 1, 1, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| + | ||||
| +		{ .format = V4L2_PIX_FMT_NV12M,   .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 }, | ||||
| +		{ .format = V4L2_PIX_FMT_NV21M,   .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 2 }, | ||||
| +		{ .format = V4L2_PIX_FMT_NV16M,   .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_NV61M,   .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .hdiv = 2, .vdiv = 1 }, | ||||
|   | ||||
|  		/* Bayer RGB formats */ | ||||
| -		{ .format = V4L2_PIX_FMT_SBGGR8,	.mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_SGBRG8,	.mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_SGRBG8,	.mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_SRGGB8,	.mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_SBGGR10,	.mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_SGBRG10,	.mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_SGRBG10,	.mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_SRGGB10,	.mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_SBGGR10ALAW8,	.mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_SGBRG10ALAW8,	.mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_SGRBG10ALAW8,	.mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_SRGGB10ALAW8,	.mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_SBGGR10DPCM8,	.mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_SGBRG10DPCM8,	.mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_SGRBG10DPCM8,	.mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_SRGGB10DPCM8,	.mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_SBGGR12,	.mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_SGBRG12,	.mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_SGRBG12,	.mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| -		{ .format = V4L2_PIX_FMT_SRGGB12,	.mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_SBGGR8,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_SGBRG8,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_SGRBG8,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_SRGGB8,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_SBGGR10,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_SGBRG10,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_SGRBG10,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_SRGGB10,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_SBGGR10ALAW8,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_SGBRG10ALAW8,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_SGRBG10ALAW8,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_SRGGB10ALAW8,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_SBGGR10DPCM8,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_SGBRG10DPCM8,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_SGRBG10DPCM8,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_SRGGB10DPCM8,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_SBGGR12,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_SGBRG12,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_SGRBG12,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_SRGGB12,	.pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
|  	}; | ||||
|  	unsigned int i; | ||||
|   | ||||
| --- a/include/media/v4l2-common.h | ||||
| +++ b/include/media/v4l2-common.h | ||||
| @@ -457,8 +457,24 @@ int v4l2_s_parm_cap(struct video_device | ||||
|  /* Pixel format and FourCC helpers */ | ||||
|   | ||||
|  /** | ||||
| + * enum v4l2_pixel_encoding - specifies the pixel encoding value | ||||
| + * | ||||
| + * @V4L2_PIXEL_ENC_UNKNOWN:	Pixel encoding is unknown/un-initialized | ||||
| + * @V4L2_PIXEL_ENC_YUV:		Pixel encoding is YUV | ||||
| + * @V4L2_PIXEL_ENC_RGB:		Pixel encoding is RGB | ||||
| + * @V4L2_PIXEL_ENC_BAYER:	Pixel encoding is Bayer | ||||
| + */ | ||||
| +enum v4l2_pixel_encoding { | ||||
| +	V4L2_PIXEL_ENC_UNKNOWN = 0, | ||||
| +	V4L2_PIXEL_ENC_YUV = 1, | ||||
| +	V4L2_PIXEL_ENC_RGB = 2, | ||||
| +	V4L2_PIXEL_ENC_BAYER = 3, | ||||
| +}; | ||||
| + | ||||
| +/** | ||||
|   * struct v4l2_format_info - information about a V4L2 format | ||||
|   * @format: 4CC format identifier (V4L2_PIX_FMT_*) | ||||
| + * @pixel_enc: Pixel encoding (see enum v4l2_pixel_encoding above) | ||||
|   * @mem_planes: Number of memory planes, which includes the alpha plane (1 to 4). | ||||
|   * @comp_planes: Number of component planes, which includes the alpha plane (1 to 4). | ||||
|   * @bpp: Array of per-plane bytes per pixel | ||||
| @@ -469,6 +485,7 @@ int v4l2_s_parm_cap(struct video_device | ||||
|   */ | ||||
|  struct v4l2_format_info { | ||||
|  	u32 format; | ||||
| +	u8 pixel_enc; | ||||
|  	u8 mem_planes; | ||||
|  	u8 comp_planes; | ||||
|  	u8 bpp[4]; | ||||
| @@ -478,8 +495,22 @@ struct v4l2_format_info { | ||||
|  	u8 block_h[4]; | ||||
|  }; | ||||
|   | ||||
| -const struct v4l2_format_info *v4l2_format_info(u32 format); | ||||
| +static inline bool v4l2_is_format_rgb(const struct v4l2_format_info *f) | ||||
| +{ | ||||
| +	return f && f->pixel_enc == V4L2_PIXEL_ENC_RGB; | ||||
| +} | ||||
| + | ||||
| +static inline bool v4l2_is_format_yuv(const struct v4l2_format_info *f) | ||||
| +{ | ||||
| +	return f && f->pixel_enc == V4L2_PIXEL_ENC_YUV; | ||||
| +} | ||||
|   | ||||
| +static inline bool v4l2_is_format_bayer(const struct v4l2_format_info *f) | ||||
| +{ | ||||
| +	return f && f->pixel_enc == V4L2_PIXEL_ENC_BAYER; | ||||
| +} | ||||
| + | ||||
| +const struct v4l2_format_info *v4l2_format_info(u32 format); | ||||
|  void v4l2_apply_frmsize_constraints(u32 *width, u32 *height, | ||||
|  				    const struct v4l2_frmsize_stepwise *frmsize); | ||||
|  int v4l2_fill_pixfmt(struct v4l2_pix_format *pixfmt, u32 pixelformat, | ||||
| @@ -0,0 +1,28 @@ | ||||
| From 560f3a9051578499e72ce4b1beaedd007ff46f96 Mon Sep 17 00:00:00 2001 | ||||
| From: Benoit Parrot <bparrot@ti.com> | ||||
| Date: Mon, 7 Oct 2019 12:10:08 -0300 | ||||
| Subject: [PATCH] media: v4l2-common: add RGB565 and RGB55 to | ||||
|  v4l2_format_info | ||||
|  | ||||
| Commit b373f84d77e1c409aacb4ff5bb5726c45fc8b166 upstream. | ||||
|  | ||||
| Add RGB565 and RGB555 to the v4l2_format_info table. | ||||
|  | ||||
| Signed-off-by: Benoit Parrot <bparrot@ti.com> | ||||
| Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> | ||||
| Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org> | ||||
| --- | ||||
|  drivers/media/v4l2-core/v4l2-common.c | 2 ++ | ||||
|  1 file changed, 2 insertions(+) | ||||
|  | ||||
| --- a/drivers/media/v4l2-core/v4l2-common.c | ||||
| +++ b/drivers/media/v4l2-core/v4l2-common.c | ||||
| @@ -251,6 +251,8 @@ const struct v4l2_format_info *v4l2_form | ||||
|  		{ .format = V4L2_PIX_FMT_ABGR32,  .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
|  		{ .format = V4L2_PIX_FMT_BGRA32,  .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
|  		{ .format = V4L2_PIX_FMT_GREY,    .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_RGB565,  .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
| +		{ .format = V4L2_PIX_FMT_RGB555,  .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 1, .vdiv = 1 }, | ||||
|   | ||||
|  		/* YUV packed formats */ | ||||
|  		{ .format = V4L2_PIX_FMT_YUYV,    .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .hdiv = 2, .vdiv = 1 }, | ||||
| @@ -0,0 +1,184 @@ | ||||
| From dfcdc4ed9a514cd5d77dd18c6527f257f8aaf378 Mon Sep 17 00:00:00 2001 | ||||
| From: Hans Verkuil <hverkuil-cisco@xs4all.nl> | ||||
| Date: Fri, 11 Oct 2019 06:32:40 -0300 | ||||
| Subject: [PATCH] media: vb2: add V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF | ||||
|  | ||||
| This patch adds support for the V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF | ||||
| flag. | ||||
|  | ||||
| It also adds a new V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF | ||||
| capability. | ||||
|  | ||||
| Drivers should set vb2_queue->subsystem_flags to | ||||
| VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF to indicate support | ||||
| for this flag. | ||||
|  | ||||
| Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> | ||||
| Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org> | ||||
| --- | ||||
|  Documentation/media/uapi/v4l/buffer.rst         | 13 +++++++++++++ | ||||
|  Documentation/media/uapi/v4l/vidioc-reqbufs.rst |  6 ++++++ | ||||
|  drivers/media/common/videobuf2/videobuf2-v4l2.c | 12 ++++++++++-- | ||||
|  include/media/videobuf2-core.h                  |  3 +++ | ||||
|  include/media/videobuf2-v4l2.h                  |  5 +++++ | ||||
|  include/uapi/linux/videodev2.h                  | 13 ++++++++----- | ||||
|  6 files changed, 45 insertions(+), 7 deletions(-) | ||||
|  | ||||
| --- a/Documentation/media/uapi/v4l/buffer.rst | ||||
| +++ b/Documentation/media/uapi/v4l/buffer.rst | ||||
| @@ -607,6 +607,19 @@ Buffer Flags | ||||
|  	applications shall use this flag for output buffers if the data in | ||||
|  	this buffer has not been created by the CPU but by some | ||||
|  	DMA-capable unit, in which case caches have not been used. | ||||
| +    * .. _`V4L2-BUF-FLAG-M2M-HOLD-CAPTURE-BUF`: | ||||
| + | ||||
| +      - ``V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF`` | ||||
| +      - 0x00000200 | ||||
| +      - Only valid if ``V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF`` is | ||||
| +	set. It is typically used with stateless decoders where multiple | ||||
| +	output buffers each decode to a slice of the decoded frame. | ||||
| +	Applications can set this flag when queueing the output buffer | ||||
| +	to prevent the driver from dequeueing the capture buffer after | ||||
| +	the output buffer has been decoded (i.e. the capture buffer is | ||||
| +	'held'). If the timestamp of this output buffer differs from that | ||||
| +	of the previous output buffer, then that indicates the start of a | ||||
| +	new frame and the previously held capture buffer is dequeued. | ||||
|      * .. _`V4L2-BUF-FLAG-LAST`: | ||||
|   | ||||
|        - ``V4L2_BUF_FLAG_LAST`` | ||||
| --- a/Documentation/media/uapi/v4l/vidioc-reqbufs.rst | ||||
| +++ b/Documentation/media/uapi/v4l/vidioc-reqbufs.rst | ||||
| @@ -125,6 +125,7 @@ aborting or finishing any DMA in progres | ||||
|  .. _V4L2-BUF-CAP-SUPPORTS-DMABUF: | ||||
|  .. _V4L2-BUF-CAP-SUPPORTS-REQUESTS: | ||||
|  .. _V4L2-BUF-CAP-SUPPORTS-ORPHANED-BUFS: | ||||
| +.. _V4L2-BUF-CAP-SUPPORTS-M2M-HOLD-CAPTURE-BUF: | ||||
|   | ||||
|  .. cssclass:: longtable | ||||
|   | ||||
| @@ -150,6 +151,11 @@ aborting or finishing any DMA in progres | ||||
|        - The kernel allows calling :ref:`VIDIOC_REQBUFS` while buffers are still | ||||
|          mapped or exported via DMABUF. These orphaned buffers will be freed | ||||
|          when they are unmapped or when the exported DMABUF fds are closed. | ||||
| +    * - ``V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF`` | ||||
| +      - 0x00000020 | ||||
| +      - Only valid for stateless decoders. If set, then userspace can set the | ||||
| +        ``V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF`` flag to hold off on returning the | ||||
| +	capture buffer until the OUTPUT timestamp changes. | ||||
|   | ||||
|  Return Value | ||||
|  ============ | ||||
| --- a/drivers/media/common/videobuf2/videobuf2-v4l2.c | ||||
| +++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c | ||||
| @@ -49,8 +49,11 @@ module_param(debug, int, 0644); | ||||
|  				 V4L2_BUF_FLAG_REQUEST_FD | \ | ||||
|  				 V4L2_BUF_FLAG_TIMESTAMP_MASK) | ||||
|  /* Output buffer flags that should be passed on to the driver */ | ||||
| -#define V4L2_BUFFER_OUT_FLAGS	(V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME | \ | ||||
| -				 V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_TIMECODE) | ||||
| +#define V4L2_BUFFER_OUT_FLAGS	(V4L2_BUF_FLAG_PFRAME | \ | ||||
| +				 V4L2_BUF_FLAG_BFRAME | \ | ||||
| +				 V4L2_BUF_FLAG_KEYFRAME | \ | ||||
| +				 V4L2_BUF_FLAG_TIMECODE | \ | ||||
| +				 V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF) | ||||
|   | ||||
|  /* | ||||
|   * __verify_planes_array() - verify that the planes array passed in struct | ||||
| @@ -194,6 +197,7 @@ static int vb2_fill_vb2_v4l2_buffer(stru | ||||
|  	} | ||||
|  	vbuf->sequence = 0; | ||||
|  	vbuf->request_fd = -1; | ||||
| +	vbuf->is_held = false; | ||||
|   | ||||
|  	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) { | ||||
|  		switch (b->memory) { | ||||
| @@ -321,6 +325,8 @@ static int vb2_fill_vb2_v4l2_buffer(stru | ||||
|  		 */ | ||||
|  		vbuf->flags &= ~V4L2_BUF_FLAG_TIMECODE; | ||||
|  		vbuf->field = b->field; | ||||
| +		if (!(q->subsystem_flags & VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF)) | ||||
| +			vbuf->flags &= ~V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF; | ||||
|  	} else { | ||||
|  		/* Zero any output buffer flags as this is a capture buffer */ | ||||
|  		vbuf->flags &= ~V4L2_BUFFER_OUT_FLAGS; | ||||
| @@ -654,6 +660,8 @@ static void fill_buf_caps(struct vb2_que | ||||
|  		*caps |= V4L2_BUF_CAP_SUPPORTS_USERPTR; | ||||
|  	if (q->io_modes & VB2_DMABUF) | ||||
|  		*caps |= V4L2_BUF_CAP_SUPPORTS_DMABUF; | ||||
| +	if (q->subsystem_flags & VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF) | ||||
| +		*caps |= V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF; | ||||
|  #ifdef CONFIG_MEDIA_CONTROLLER_REQUEST_API | ||||
|  	if (q->supports_requests) | ||||
|  		*caps |= V4L2_BUF_CAP_SUPPORTS_REQUESTS; | ||||
| --- a/include/media/videobuf2-core.h | ||||
| +++ b/include/media/videobuf2-core.h | ||||
| @@ -505,6 +505,8 @@ struct vb2_buf_ops { | ||||
|   * @buf_ops:	callbacks to deliver buffer information. | ||||
|   *		between user-space and kernel-space. | ||||
|   * @drv_priv:	driver private data. | ||||
| + * @subsystem_flags: Flags specific to the subsystem (V4L2/DVB/etc.). Not used | ||||
| + *		by the vb2 core. | ||||
|   * @buf_struct_size: size of the driver-specific buffer structure; | ||||
|   *		"0" indicates the driver doesn't want to use a custom buffer | ||||
|   *		structure type. for example, ``sizeof(struct vb2_v4l2_buffer)`` | ||||
| @@ -571,6 +573,7 @@ struct vb2_queue { | ||||
|  	const struct vb2_buf_ops	*buf_ops; | ||||
|   | ||||
|  	void				*drv_priv; | ||||
| +	u32				subsystem_flags; | ||||
|  	unsigned int			buf_struct_size; | ||||
|  	u32				timestamp_flags; | ||||
|  	gfp_t				gfp_flags; | ||||
| --- a/include/media/videobuf2-v4l2.h | ||||
| +++ b/include/media/videobuf2-v4l2.h | ||||
| @@ -33,6 +33,7 @@ | ||||
|   * @timecode:	frame timecode. | ||||
|   * @sequence:	sequence count of this frame. | ||||
|   * @request_fd:	the request_fd associated with this buffer | ||||
| + * @is_held:	if true, then this capture buffer was held | ||||
|   * @planes:	plane information (userptr/fd, length, bytesused, data_offset). | ||||
|   * | ||||
|   * Should contain enough information to be able to cover all the fields | ||||
| @@ -46,9 +47,13 @@ struct vb2_v4l2_buffer { | ||||
|  	struct v4l2_timecode	timecode; | ||||
|  	__u32			sequence; | ||||
|  	__s32			request_fd; | ||||
| +	bool			is_held; | ||||
|  	struct vb2_plane	planes[VB2_MAX_PLANES]; | ||||
|  }; | ||||
|   | ||||
| +/* VB2 V4L2 flags as set in vb2_queue.subsystem_flags */ | ||||
| +#define VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF (1 << 0) | ||||
| + | ||||
|  /* | ||||
|   * to_vb2_v4l2_buffer() - cast struct vb2_buffer * to struct vb2_v4l2_buffer * | ||||
|   */ | ||||
| --- a/include/uapi/linux/videodev2.h | ||||
| +++ b/include/uapi/linux/videodev2.h | ||||
| @@ -925,11 +925,12 @@ struct v4l2_requestbuffers { | ||||
|  }; | ||||
|   | ||||
|  /* capabilities for struct v4l2_requestbuffers and v4l2_create_buffers */ | ||||
| -#define V4L2_BUF_CAP_SUPPORTS_MMAP	(1 << 0) | ||||
| -#define V4L2_BUF_CAP_SUPPORTS_USERPTR	(1 << 1) | ||||
| -#define V4L2_BUF_CAP_SUPPORTS_DMABUF	(1 << 2) | ||||
| -#define V4L2_BUF_CAP_SUPPORTS_REQUESTS	(1 << 3) | ||||
| -#define V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS (1 << 4) | ||||
| +#define V4L2_BUF_CAP_SUPPORTS_MMAP			(1 << 0) | ||||
| +#define V4L2_BUF_CAP_SUPPORTS_USERPTR			(1 << 1) | ||||
| +#define V4L2_BUF_CAP_SUPPORTS_DMABUF			(1 << 2) | ||||
| +#define V4L2_BUF_CAP_SUPPORTS_REQUESTS			(1 << 3) | ||||
| +#define V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS		(1 << 4) | ||||
| +#define V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF	(1 << 5) | ||||
|   | ||||
|  /** | ||||
|   * struct v4l2_plane - plane info for multi-planar buffers | ||||
| @@ -1051,6 +1052,8 @@ static inline __u64 v4l2_timeval_to_ns(c | ||||
|  #define V4L2_BUF_FLAG_IN_REQUEST		0x00000080 | ||||
|  /* timecode field is valid */ | ||||
|  #define V4L2_BUF_FLAG_TIMECODE			0x00000100 | ||||
| +/* Don't return the capture buffer until OUTPUT timestamp changes */ | ||||
| +#define V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF	0x00000200 | ||||
|  /* Buffer is prepared for queuing */ | ||||
|  #define V4L2_BUF_FLAG_PREPARED			0x00000400 | ||||
|  /* Cache handling flags */ | ||||
| @@ -0,0 +1,260 @@ | ||||
| From dc9b786e4b9a1262b536b3c9d0fa88e34a2b3f8f Mon Sep 17 00:00:00 2001 | ||||
| From: Hans Verkuil <hverkuil-cisco@xs4all.nl> | ||||
| Date: Fri, 11 Oct 2019 06:32:41 -0300 | ||||
| Subject: [PATCH] media: v4l2-mem2mem: support held capture buffers | ||||
|  | ||||
| Commit f8cca8c97a63d77f48334cde81d15014f43530ef upstream. | ||||
|  | ||||
| Check for held buffers that are ready to be returned to vb2 in | ||||
| __v4l2_m2m_try_queue(). This avoids drivers having to handle this | ||||
| case. | ||||
|  | ||||
| Add v4l2_m2m_buf_done_and_job_finish() to correctly return source | ||||
| and destination buffers and mark the job as finished while taking | ||||
| a held destination buffer into account (i.e. that buffer won't be | ||||
| returned). This has to be done while job_spinlock is held to avoid | ||||
| race conditions. | ||||
|  | ||||
| Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> | ||||
| Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org> | ||||
| --- | ||||
|  drivers/media/v4l2-core/v4l2-mem2mem.c | 130 ++++++++++++++++++------- | ||||
|  include/media/v4l2-mem2mem.h           |  33 ++++++- | ||||
|  2 files changed, 128 insertions(+), 35 deletions(-) | ||||
|  | ||||
| --- a/drivers/media/v4l2-core/v4l2-mem2mem.c | ||||
| +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c | ||||
| @@ -284,7 +284,8 @@ static void v4l2_m2m_try_run(struct v4l2 | ||||
|  static void __v4l2_m2m_try_queue(struct v4l2_m2m_dev *m2m_dev, | ||||
|  				 struct v4l2_m2m_ctx *m2m_ctx) | ||||
|  { | ||||
| -	unsigned long flags_job, flags_out, flags_cap; | ||||
| +	unsigned long flags_job; | ||||
| +	struct vb2_v4l2_buffer *dst, *src; | ||||
|   | ||||
|  	dprintk("Trying to schedule a job for m2m_ctx: %p\n", m2m_ctx); | ||||
|   | ||||
| @@ -307,20 +308,30 @@ static void __v4l2_m2m_try_queue(struct | ||||
|  		goto job_unlock; | ||||
|  	} | ||||
|   | ||||
| -	spin_lock_irqsave(&m2m_ctx->out_q_ctx.rdy_spinlock, flags_out); | ||||
| -	if (list_empty(&m2m_ctx->out_q_ctx.rdy_queue) | ||||
| -	    && !m2m_ctx->out_q_ctx.buffered) { | ||||
| +	src = v4l2_m2m_next_src_buf(m2m_ctx); | ||||
| +	dst = v4l2_m2m_next_dst_buf(m2m_ctx); | ||||
| +	if (!src && !m2m_ctx->out_q_ctx.buffered) { | ||||
|  		dprintk("No input buffers available\n"); | ||||
| -		goto out_unlock; | ||||
| +		goto job_unlock; | ||||
|  	} | ||||
| -	spin_lock_irqsave(&m2m_ctx->cap_q_ctx.rdy_spinlock, flags_cap); | ||||
| -	if (list_empty(&m2m_ctx->cap_q_ctx.rdy_queue) | ||||
| -	    && !m2m_ctx->cap_q_ctx.buffered) { | ||||
| +	if (!dst && !m2m_ctx->cap_q_ctx.buffered) { | ||||
|  		dprintk("No output buffers available\n"); | ||||
| -		goto cap_unlock; | ||||
| +		goto job_unlock; | ||||
| +	} | ||||
| + | ||||
| +	if (src && dst && | ||||
| +	    dst->is_held && dst->vb2_buf.copied_timestamp && | ||||
| +	    dst->vb2_buf.timestamp != src->vb2_buf.timestamp) { | ||||
| +		dst->is_held = false; | ||||
| +		v4l2_m2m_dst_buf_remove(m2m_ctx); | ||||
| +		v4l2_m2m_buf_done(dst, VB2_BUF_STATE_DONE); | ||||
| +		dst = v4l2_m2m_next_dst_buf(m2m_ctx); | ||||
| + | ||||
| +		if (!dst && !m2m_ctx->cap_q_ctx.buffered) { | ||||
| +			dprintk("No output buffers available after returning held buffer\n"); | ||||
| +			goto job_unlock; | ||||
| +		} | ||||
|  	} | ||||
| -	spin_unlock_irqrestore(&m2m_ctx->cap_q_ctx.rdy_spinlock, flags_cap); | ||||
| -	spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock, flags_out); | ||||
|   | ||||
|  	if (m2m_dev->m2m_ops->job_ready | ||||
|  		&& (!m2m_dev->m2m_ops->job_ready(m2m_ctx->priv))) { | ||||
| @@ -331,13 +342,6 @@ static void __v4l2_m2m_try_queue(struct | ||||
|  	list_add_tail(&m2m_ctx->queue, &m2m_dev->job_queue); | ||||
|  	m2m_ctx->job_flags |= TRANS_QUEUED; | ||||
|   | ||||
| -	spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job); | ||||
| -	return; | ||||
| - | ||||
| -cap_unlock: | ||||
| -	spin_unlock_irqrestore(&m2m_ctx->cap_q_ctx.rdy_spinlock, flags_cap); | ||||
| -out_unlock: | ||||
| -	spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock, flags_out); | ||||
|  job_unlock: | ||||
|  	spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job); | ||||
|  } | ||||
| @@ -412,37 +416,97 @@ static void v4l2_m2m_cancel_job(struct v | ||||
|  	} | ||||
|  } | ||||
|   | ||||
| -void v4l2_m2m_job_finish(struct v4l2_m2m_dev *m2m_dev, | ||||
| -			 struct v4l2_m2m_ctx *m2m_ctx) | ||||
| +/* | ||||
| + * Schedule the next job, called from v4l2_m2m_job_finish() or | ||||
| + * v4l2_m2m_buf_done_and_job_finish(). | ||||
| + */ | ||||
| +static void v4l2_m2m_schedule_next_job(struct v4l2_m2m_dev *m2m_dev, | ||||
| +				       struct v4l2_m2m_ctx *m2m_ctx) | ||||
|  { | ||||
| -	unsigned long flags; | ||||
| +	/* | ||||
| +	 * This instance might have more buffers ready, but since we do not | ||||
| +	 * allow more than one job on the job_queue per instance, each has | ||||
| +	 * to be scheduled separately after the previous one finishes. | ||||
| +	 */ | ||||
| +	__v4l2_m2m_try_queue(m2m_dev, m2m_ctx); | ||||
|   | ||||
| -	spin_lock_irqsave(&m2m_dev->job_spinlock, flags); | ||||
| +	/* | ||||
| +	 * We might be running in atomic context, | ||||
| +	 * but the job must be run in non-atomic context. | ||||
| +	 */ | ||||
| +	schedule_work(&m2m_dev->job_work); | ||||
| +} | ||||
| + | ||||
| +/* | ||||
| + * Assumes job_spinlock is held, called from v4l2_m2m_job_finish() or | ||||
| + * v4l2_m2m_buf_done_and_job_finish(). | ||||
| + */ | ||||
| +static bool _v4l2_m2m_job_finish(struct v4l2_m2m_dev *m2m_dev, | ||||
| +				 struct v4l2_m2m_ctx *m2m_ctx) | ||||
| +{ | ||||
|  	if (!m2m_dev->curr_ctx || m2m_dev->curr_ctx != m2m_ctx) { | ||||
| -		spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); | ||||
|  		dprintk("Called by an instance not currently running\n"); | ||||
| -		return; | ||||
| +		return false; | ||||
|  	} | ||||
|   | ||||
|  	list_del(&m2m_dev->curr_ctx->queue); | ||||
|  	m2m_dev->curr_ctx->job_flags &= ~(TRANS_QUEUED | TRANS_RUNNING); | ||||
|  	wake_up(&m2m_dev->curr_ctx->finished); | ||||
|  	m2m_dev->curr_ctx = NULL; | ||||
| +	return true; | ||||
| +} | ||||
|   | ||||
| -	spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); | ||||
| - | ||||
| -	/* This instance might have more buffers ready, but since we do not | ||||
| -	 * allow more than one job on the job_queue per instance, each has | ||||
| -	 * to be scheduled separately after the previous one finishes. */ | ||||
| -	__v4l2_m2m_try_queue(m2m_dev, m2m_ctx); | ||||
| +void v4l2_m2m_job_finish(struct v4l2_m2m_dev *m2m_dev, | ||||
| +			 struct v4l2_m2m_ctx *m2m_ctx) | ||||
| +{ | ||||
| +	unsigned long flags; | ||||
| +	bool schedule_next; | ||||
|   | ||||
| -	/* We might be running in atomic context, | ||||
| -	 * but the job must be run in non-atomic context. | ||||
| +	/* | ||||
| +	 * This function should not be used for drivers that support | ||||
| +	 * holding capture buffers. Those should use | ||||
| +	 * v4l2_m2m_buf_done_and_job_finish() instead. | ||||
|  	 */ | ||||
| -	schedule_work(&m2m_dev->job_work); | ||||
| +	WARN_ON(m2m_ctx->cap_q_ctx.q.subsystem_flags & | ||||
| +		VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF); | ||||
| +	spin_lock_irqsave(&m2m_dev->job_spinlock, flags); | ||||
| +	schedule_next = _v4l2_m2m_job_finish(m2m_dev, m2m_ctx); | ||||
| +	spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); | ||||
| + | ||||
| +	if (schedule_next) | ||||
| +		v4l2_m2m_schedule_next_job(m2m_dev, m2m_ctx); | ||||
|  } | ||||
|  EXPORT_SYMBOL(v4l2_m2m_job_finish); | ||||
|   | ||||
| +void v4l2_m2m_buf_done_and_job_finish(struct v4l2_m2m_dev *m2m_dev, | ||||
| +				      struct v4l2_m2m_ctx *m2m_ctx, | ||||
| +				      enum vb2_buffer_state state) | ||||
| +{ | ||||
| +	struct vb2_v4l2_buffer *src_buf, *dst_buf; | ||||
| +	bool schedule_next = false; | ||||
| +	unsigned long flags; | ||||
| + | ||||
| +	spin_lock_irqsave(&m2m_dev->job_spinlock, flags); | ||||
| +	src_buf = v4l2_m2m_src_buf_remove(m2m_ctx); | ||||
| +	dst_buf = v4l2_m2m_next_dst_buf(m2m_ctx); | ||||
| + | ||||
| +	if (WARN_ON(!src_buf || !dst_buf)) | ||||
| +		goto unlock; | ||||
| +	v4l2_m2m_buf_done(src_buf, state); | ||||
| +	dst_buf->is_held = src_buf->flags & V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF; | ||||
| +	if (!dst_buf->is_held) { | ||||
| +		v4l2_m2m_dst_buf_remove(m2m_ctx); | ||||
| +		v4l2_m2m_buf_done(dst_buf, state); | ||||
| +	} | ||||
| +	schedule_next = _v4l2_m2m_job_finish(m2m_dev, m2m_ctx); | ||||
| +unlock: | ||||
| +	spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); | ||||
| + | ||||
| +	if (schedule_next) | ||||
| +		v4l2_m2m_schedule_next_job(m2m_dev, m2m_ctx); | ||||
| +} | ||||
| +EXPORT_SYMBOL(v4l2_m2m_buf_done_and_job_finish); | ||||
| + | ||||
|  int v4l2_m2m_reqbufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, | ||||
|  		     struct v4l2_requestbuffers *reqbufs) | ||||
|  { | ||||
| --- a/include/media/v4l2-mem2mem.h | ||||
| +++ b/include/media/v4l2-mem2mem.h | ||||
| @@ -21,7 +21,8 @@ | ||||
|   *		callback. | ||||
|   *		The job does NOT have to end before this callback returns | ||||
|   *		(and it will be the usual case). When the job finishes, | ||||
| - *		v4l2_m2m_job_finish() has to be called. | ||||
| + *		v4l2_m2m_job_finish() or v4l2_m2m_buf_done_and_job_finish() | ||||
| + *		has to be called. | ||||
|   * @job_ready:	optional. Should return 0 if the driver does not have a job | ||||
|   *		fully prepared to run yet (i.e. it will not be able to finish a | ||||
|   *		transaction without sleeping). If not provided, it will be | ||||
| @@ -33,7 +34,8 @@ | ||||
|   *		stop the device safely; e.g. in the next interrupt handler), | ||||
|   *		even if the transaction would not have been finished by then. | ||||
|   *		After the driver performs the necessary steps, it has to call | ||||
| - *		v4l2_m2m_job_finish() (as if the transaction ended normally). | ||||
| + *		v4l2_m2m_job_finish() or v4l2_m2m_buf_done_and_job_finish() as | ||||
| + *		if the transaction ended normally. | ||||
|   *		This function does not have to (and will usually not) wait | ||||
|   *		until the device enters a state when it can be stopped. | ||||
|   */ | ||||
| @@ -173,6 +175,33 @@ void v4l2_m2m_try_schedule(struct v4l2_m | ||||
|  void v4l2_m2m_job_finish(struct v4l2_m2m_dev *m2m_dev, | ||||
|  			 struct v4l2_m2m_ctx *m2m_ctx); | ||||
|   | ||||
| +/** | ||||
| + * v4l2_m2m_buf_done_and_job_finish() - return source/destination buffers with | ||||
| + * state and inform the framework that a job has been finished and have it | ||||
| + * clean up | ||||
| + * | ||||
| + * @m2m_dev: opaque pointer to the internal data to handle M2M context | ||||
| + * @m2m_ctx: m2m context assigned to the instance given by struct &v4l2_m2m_ctx | ||||
| + * @state: vb2 buffer state passed to v4l2_m2m_buf_done(). | ||||
| + * | ||||
| + * Drivers that set V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF must use this | ||||
| + * function instead of job_finish() to take held buffers into account. It is | ||||
| + * optional for other drivers. | ||||
| + * | ||||
| + * This function removes the source buffer from the ready list and returns | ||||
| + * it with the given state. The same is done for the destination buffer, unless | ||||
| + * it is marked 'held'. In that case the buffer is kept on the ready list. | ||||
| + * | ||||
| + * After that the job is finished (see job_finish()). | ||||
| + * | ||||
| + * This allows for multiple output buffers to be used to fill in a single | ||||
| + * capture buffer. This is typically used by stateless decoders where | ||||
| + * multiple e.g. H.264 slices contribute to a single decoded frame. | ||||
| + */ | ||||
| +void v4l2_m2m_buf_done_and_job_finish(struct v4l2_m2m_dev *m2m_dev, | ||||
| +				      struct v4l2_m2m_ctx *m2m_ctx, | ||||
| +				      enum vb2_buffer_state state); | ||||
| + | ||||
|  static inline void | ||||
|  v4l2_m2m_buf_done(struct vb2_v4l2_buffer *buf, enum vb2_buffer_state state) | ||||
|  { | ||||
| @@ -0,0 +1,57 @@ | ||||
| From b2ea711d2c21ec021de4ff09a0a2b5b4224f9749 Mon Sep 17 00:00:00 2001 | ||||
| From: Hans Verkuil <hverkuil-cisco@xs4all.nl> | ||||
| Date: Fri, 11 Oct 2019 06:32:42 -0300 | ||||
| Subject: [PATCH] media: videodev2.h: add V4L2_DEC_CMD_FLUSH | ||||
|  | ||||
| Add this new V4L2_DEC_CMD_FLUSH decoder command and document it. | ||||
|  | ||||
| Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com> | ||||
| Reviewed-by: Alexandre Courbot <acourbot@chromium.org> | ||||
| Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> | ||||
| Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net> | ||||
| Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org> | ||||
| --- | ||||
|  Documentation/media/uapi/v4l/vidioc-decoder-cmd.rst | 10 +++++++++- | ||||
|  Documentation/media/videodev2.h.rst.exceptions      |  1 + | ||||
|  include/uapi/linux/videodev2.h                      |  1 + | ||||
|  3 files changed, 11 insertions(+), 1 deletion(-) | ||||
|  | ||||
| --- a/Documentation/media/uapi/v4l/vidioc-decoder-cmd.rst | ||||
| +++ b/Documentation/media/uapi/v4l/vidioc-decoder-cmd.rst | ||||
| @@ -208,7 +208,15 @@ introduced in Linux 3.3. They are, howev | ||||
|  	been started yet, the driver will return an ``EPERM`` error code. When | ||||
|  	the decoder is already running, this command does nothing. No | ||||
|  	flags are defined for this command. | ||||
| - | ||||
| +    * - ``V4L2_DEC_CMD_FLUSH`` | ||||
| +      - 4 | ||||
| +      - Flush any held capture buffers. Only valid for stateless decoders. | ||||
| +	This command is typically used when the application reached the | ||||
| +	end of the stream and the last output buffer had the | ||||
| +	``V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF`` flag set. This would prevent | ||||
| +	dequeueing the capture buffer containing the last decoded frame. | ||||
| +	So this command can be used to explicitly flush that final decoded | ||||
| +	frame. This command does nothing if there are no held capture buffers. | ||||
|   | ||||
|  Return Value | ||||
|  ============ | ||||
| --- a/Documentation/media/videodev2.h.rst.exceptions | ||||
| +++ b/Documentation/media/videodev2.h.rst.exceptions | ||||
| @@ -434,6 +434,7 @@ replace define V4L2_DEC_CMD_START decode | ||||
|  replace define V4L2_DEC_CMD_STOP decoder-cmds | ||||
|  replace define V4L2_DEC_CMD_PAUSE decoder-cmds | ||||
|  replace define V4L2_DEC_CMD_RESUME decoder-cmds | ||||
| +replace define V4L2_DEC_CMD_FLUSH decoder-cmds | ||||
|   | ||||
|  replace define V4L2_DEC_CMD_START_MUTE_AUDIO decoder-cmds | ||||
|  replace define V4L2_DEC_CMD_PAUSE_TO_BLACK decoder-cmds | ||||
| --- a/include/uapi/linux/videodev2.h | ||||
| +++ b/include/uapi/linux/videodev2.h | ||||
| @@ -1989,6 +1989,7 @@ struct v4l2_encoder_cmd { | ||||
|  #define V4L2_DEC_CMD_STOP        (1) | ||||
|  #define V4L2_DEC_CMD_PAUSE       (2) | ||||
|  #define V4L2_DEC_CMD_RESUME      (3) | ||||
| +#define V4L2_DEC_CMD_FLUSH       (4) | ||||
|   | ||||
|  /* Flags for V4L2_DEC_CMD_START */ | ||||
|  #define V4L2_DEC_CMD_START_MUTE_AUDIO	(1 << 0) | ||||
| @@ -0,0 +1,96 @@ | ||||
| From 1decb017f990ea61ab421e316bf1af3a5199b73a Mon Sep 17 00:00:00 2001 | ||||
| From: Jernej Skrabec <jernej.skrabec@siol.net> | ||||
| Date: Fri, 11 Oct 2019 06:32:43 -0300 | ||||
| Subject: [PATCH] media: v4l2-mem2mem: add stateless_(try_)decoder_cmd | ||||
|  ioctl helpers | ||||
|  | ||||
| Commit bef41d93aac64b54c3008ca6170bec54f85784f5 upstream. | ||||
|  | ||||
| These helpers are used by stateless codecs when they support multiple | ||||
| slices per frame and hold capture buffer flag is set. It's expected that | ||||
| all such codecs will use this code. | ||||
|  | ||||
| Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net> | ||||
| Co-developed-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> | ||||
| Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> | ||||
| Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org> | ||||
| --- | ||||
|  drivers/media/v4l2-core/v4l2-mem2mem.c | 53 ++++++++++++++++++++++++++ | ||||
|  include/media/v4l2-mem2mem.h           |  4 ++ | ||||
|  2 files changed, 57 insertions(+) | ||||
|  | ||||
| --- a/drivers/media/v4l2-core/v4l2-mem2mem.c | ||||
| +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c | ||||
| @@ -1218,6 +1218,59 @@ int v4l2_m2m_ioctl_try_decoder_cmd(struc | ||||
|  } | ||||
|  EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_try_decoder_cmd); | ||||
|   | ||||
| +int v4l2_m2m_ioctl_stateless_try_decoder_cmd(struct file *file, void *fh, | ||||
| +					     struct v4l2_decoder_cmd *dc) | ||||
| +{ | ||||
| +	if (dc->cmd != V4L2_DEC_CMD_FLUSH) | ||||
| +		return -EINVAL; | ||||
| + | ||||
| +	dc->flags = 0; | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| +EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_stateless_try_decoder_cmd); | ||||
| + | ||||
| +int v4l2_m2m_ioctl_stateless_decoder_cmd(struct file *file, void *priv, | ||||
| +					 struct v4l2_decoder_cmd *dc) | ||||
| +{ | ||||
| +	struct v4l2_fh *fh = file->private_data; | ||||
| +	struct vb2_v4l2_buffer *out_vb, *cap_vb; | ||||
| +	struct v4l2_m2m_dev *m2m_dev = fh->m2m_ctx->m2m_dev; | ||||
| +	unsigned long flags; | ||||
| +	int ret; | ||||
| + | ||||
| +	ret = v4l2_m2m_ioctl_stateless_try_decoder_cmd(file, priv, dc); | ||||
| +	if (ret < 0) | ||||
| +		return ret; | ||||
| + | ||||
| +	spin_lock_irqsave(&m2m_dev->job_spinlock, flags); | ||||
| +	out_vb = v4l2_m2m_last_src_buf(fh->m2m_ctx); | ||||
| +	cap_vb = v4l2_m2m_last_dst_buf(fh->m2m_ctx); | ||||
| + | ||||
| +	/* | ||||
| +	 * If there is an out buffer pending, then clear any HOLD flag. | ||||
| +	 * | ||||
| +	 * By clearing this flag we ensure that when this output | ||||
| +	 * buffer is processed any held capture buffer will be released. | ||||
| +	 */ | ||||
| +	if (out_vb) { | ||||
| +		out_vb->flags &= ~V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF; | ||||
| +	} else if (cap_vb && cap_vb->is_held) { | ||||
| +		/* | ||||
| +		 * If there were no output buffers, but there is a | ||||
| +		 * capture buffer that is held, then release that | ||||
| +		 * buffer. | ||||
| +		 */ | ||||
| +		cap_vb->is_held = false; | ||||
| +		v4l2_m2m_dst_buf_remove(fh->m2m_ctx); | ||||
| +		v4l2_m2m_buf_done(cap_vb, VB2_BUF_STATE_DONE); | ||||
| +	} | ||||
| +	spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| +EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_stateless_decoder_cmd); | ||||
| + | ||||
|  /* | ||||
|   * v4l2_file_operations helpers. It is assumed here same lock is used | ||||
|   * for the output and the capture buffer queue. | ||||
| --- a/include/media/v4l2-mem2mem.h | ||||
| +++ b/include/media/v4l2-mem2mem.h | ||||
| @@ -701,6 +701,10 @@ int v4l2_m2m_ioctl_try_encoder_cmd(struc | ||||
|  				   struct v4l2_encoder_cmd *ec); | ||||
|  int v4l2_m2m_ioctl_try_decoder_cmd(struct file *file, void *fh, | ||||
|  				   struct v4l2_decoder_cmd *dc); | ||||
| +int v4l2_m2m_ioctl_stateless_try_decoder_cmd(struct file *file, void *fh, | ||||
| +					     struct v4l2_decoder_cmd *dc); | ||||
| +int v4l2_m2m_ioctl_stateless_decoder_cmd(struct file *file, void *priv, | ||||
| +					 struct v4l2_decoder_cmd *dc); | ||||
|  int v4l2_m2m_fop_mmap(struct file *file, struct vm_area_struct *vma); | ||||
|  __poll_t v4l2_m2m_fop_poll(struct file *file, poll_table *wait); | ||||
|   | ||||
| @@ -0,0 +1,69 @@ | ||||
| From 1d55acac432983ad8301f5430c42ac549b4b4c6f Mon Sep 17 00:00:00 2001 | ||||
| From: Hans Verkuil <hverkuil-cisco@xs4all.nl> | ||||
| Date: Fri, 11 Oct 2019 06:32:44 -0300 | ||||
| Subject: [PATCH] media: v4l2-mem2mem: add new_frame detection | ||||
|  | ||||
| Commit f07602ac388723233e9e3c5a05b54baf34e0a3e9 upstream. | ||||
|  | ||||
| Drivers that support VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF | ||||
| typically want to know if a new frame is started (i.e. the first | ||||
| slice is about to be processed). Add a new_frame bool to v4l2_m2m_ctx | ||||
| and set it accordingly. | ||||
|  | ||||
| Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> | ||||
| Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org> | ||||
| --- | ||||
|  drivers/media/v4l2-core/v4l2-mem2mem.c | 11 +++++++++-- | ||||
|  include/media/v4l2-mem2mem.h           |  7 +++++++ | ||||
|  2 files changed, 16 insertions(+), 2 deletions(-) | ||||
|  | ||||
| --- a/drivers/media/v4l2-core/v4l2-mem2mem.c | ||||
| +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c | ||||
| @@ -319,8 +319,10 @@ static void __v4l2_m2m_try_queue(struct | ||||
|  		goto job_unlock; | ||||
|  	} | ||||
|   | ||||
| -	if (src && dst && | ||||
| -	    dst->is_held && dst->vb2_buf.copied_timestamp && | ||||
| +	m2m_ctx->new_frame = true; | ||||
| + | ||||
| +	if (src && dst && dst->is_held && | ||||
| +	    dst->vb2_buf.copied_timestamp && | ||||
|  	    dst->vb2_buf.timestamp != src->vb2_buf.timestamp) { | ||||
|  		dst->is_held = false; | ||||
|  		v4l2_m2m_dst_buf_remove(m2m_ctx); | ||||
| @@ -333,6 +335,11 @@ static void __v4l2_m2m_try_queue(struct | ||||
|  		} | ||||
|  	} | ||||
|   | ||||
| +	if (src && dst && (m2m_ctx->cap_q_ctx.q.subsystem_flags & | ||||
| +			   VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF)) | ||||
| +		m2m_ctx->new_frame = !dst->vb2_buf.copied_timestamp || | ||||
| +			dst->vb2_buf.timestamp != src->vb2_buf.timestamp; | ||||
| + | ||||
|  	if (m2m_dev->m2m_ops->job_ready | ||||
|  		&& (!m2m_dev->m2m_ops->job_ready(m2m_ctx->priv))) { | ||||
|  		dprintk("Driver not ready\n"); | ||||
| --- a/include/media/v4l2-mem2mem.h | ||||
| +++ b/include/media/v4l2-mem2mem.h | ||||
| @@ -75,6 +75,11 @@ struct v4l2_m2m_queue_ctx { | ||||
|   * struct v4l2_m2m_ctx - Memory to memory context structure | ||||
|   * | ||||
|   * @q_lock: struct &mutex lock | ||||
| + * @new_frame: valid in the device_run callback: if true, then this | ||||
| + *		starts a new frame; if false, then this is a new slice | ||||
| + *		for an existing frame. This is always true unless | ||||
| + *		V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF is set, which | ||||
| + *		indicates slicing support. | ||||
|   * @m2m_dev: opaque pointer to the internal data to handle M2M context | ||||
|   * @cap_q_ctx: Capture (output to memory) queue context | ||||
|   * @out_q_ctx: Output (input from memory) queue context | ||||
| @@ -91,6 +96,8 @@ struct v4l2_m2m_ctx { | ||||
|  	/* optional cap/out vb2 queues lock */ | ||||
|  	struct mutex			*q_lock; | ||||
|   | ||||
| +	bool				new_frame; | ||||
| + | ||||
|  	/* internal use only */ | ||||
|  	struct v4l2_m2m_dev		*m2m_dev; | ||||
|   | ||||
| @@ -0,0 +1,46 @@ | ||||
| From 20076d276d045c03f809bb16f0e1fafcfe63a81f Mon Sep 17 00:00:00 2001 | ||||
| From: Ricardo Ribalda Delgado <ribalda@kernel.org> | ||||
| Date: Mon, 7 Oct 2019 12:06:32 -0300 | ||||
| Subject: [PATCH] media: Documentation: media: Document | ||||
|  V4L2_CTRL_TYPE_AREA | ||||
|  | ||||
| Commit 8ae3a0862993c09a8ef0f9abb379553370c517e3 upstream. | ||||
|  | ||||
| A struct v4l2_area containing the width and the height of a rectangular | ||||
| area. | ||||
|  | ||||
| Reviewed-by: Jacopo Mondi <jacopo@jmondi.org> | ||||
| Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de> | ||||
| Signed-off-by: Ricardo Ribalda Delgado <ribalda@kernel.org> | ||||
| Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> | ||||
| Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org> | ||||
| --- | ||||
|  Documentation/media/uapi/v4l/vidioc-queryctrl.rst | 6 ++++++ | ||||
|  Documentation/media/videodev2.h.rst.exceptions    | 1 + | ||||
|  2 files changed, 7 insertions(+) | ||||
|  | ||||
| --- a/Documentation/media/uapi/v4l/vidioc-queryctrl.rst | ||||
| +++ b/Documentation/media/uapi/v4l/vidioc-queryctrl.rst | ||||
| @@ -443,6 +443,12 @@ See also the examples in :ref:`control`. | ||||
|        - n/a | ||||
|        - A struct :c:type:`v4l2_ctrl_mpeg2_quantization`, containing MPEG-2 | ||||
|  	quantization matrices for stateless video decoders. | ||||
| +    * - ``V4L2_CTRL_TYPE_AREA`` | ||||
| +      - n/a | ||||
| +      - n/a | ||||
| +      - n/a | ||||
| +      - A struct :c:type:`v4l2_area`, containing the width and the height | ||||
| +        of a rectangular area. Units depend on the use case. | ||||
|      * - ``V4L2_CTRL_TYPE_H264_SPS`` | ||||
|        - n/a | ||||
|        - n/a | ||||
| --- a/Documentation/media/videodev2.h.rst.exceptions | ||||
| +++ b/Documentation/media/videodev2.h.rst.exceptions | ||||
| @@ -141,6 +141,7 @@ replace symbol V4L2_CTRL_TYPE_H264_PPS : | ||||
|  replace symbol V4L2_CTRL_TYPE_H264_SCALING_MATRIX :c:type:`v4l2_ctrl_type` | ||||
|  replace symbol V4L2_CTRL_TYPE_H264_SLICE_PARAMS :c:type:`v4l2_ctrl_type` | ||||
|  replace symbol V4L2_CTRL_TYPE_H264_DECODE_PARAMS :c:type:`v4l2_ctrl_type` | ||||
| +replace symbol V4L2_CTRL_TYPE_AREA :c:type:`v4l2_ctrl_type` | ||||
|   | ||||
|  # V4L2 capability defines | ||||
|  replace define V4L2_CAP_VIDEO_CAPTURE device-capabilities | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -0,0 +1,37 @@ | ||||
| From 73d8a76ec5b5e1240af4142a9ccbd39179d779af Mon Sep 17 00:00:00 2001 | ||||
| From: Jernej Skrabec <jernej.skrabec@siol.net> | ||||
| Date: Wed, 6 Nov 2019 08:02:53 +0100 | ||||
| Subject: [PATCH] media: v4l2-mem2mem: Fix hold buf flag checks | ||||
|  | ||||
| Commit 1076df3a77b490d33429560a9e0603b3673223e2 upstream. | ||||
|  | ||||
| Hold buf flag is set on output queue, not capture. Fix that. | ||||
|  | ||||
| Fixes: f07602ac3887 ("media: v4l2-mem2mem: add new_frame detection") | ||||
| Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net> | ||||
| Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> | ||||
| Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org> | ||||
| --- | ||||
|  drivers/media/v4l2-core/v4l2-mem2mem.c | 4 ++-- | ||||
|  1 file changed, 2 insertions(+), 2 deletions(-) | ||||
|  | ||||
| --- a/drivers/media/v4l2-core/v4l2-mem2mem.c | ||||
| +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c | ||||
| @@ -335,7 +335,7 @@ static void __v4l2_m2m_try_queue(struct | ||||
|  		} | ||||
|  	} | ||||
|   | ||||
| -	if (src && dst && (m2m_ctx->cap_q_ctx.q.subsystem_flags & | ||||
| +	if (src && dst && (m2m_ctx->out_q_ctx.q.subsystem_flags & | ||||
|  			   VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF)) | ||||
|  		m2m_ctx->new_frame = !dst->vb2_buf.copied_timestamp || | ||||
|  			dst->vb2_buf.timestamp != src->vb2_buf.timestamp; | ||||
| @@ -474,7 +474,7 @@ void v4l2_m2m_job_finish(struct v4l2_m2m | ||||
|  	 * holding capture buffers. Those should use | ||||
|  	 * v4l2_m2m_buf_done_and_job_finish() instead. | ||||
|  	 */ | ||||
| -	WARN_ON(m2m_ctx->cap_q_ctx.q.subsystem_flags & | ||||
| +	WARN_ON(m2m_ctx->out_q_ctx.q.subsystem_flags & | ||||
|  		VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF); | ||||
|  	spin_lock_irqsave(&m2m_dev->job_spinlock, flags); | ||||
|  	schedule_next = _v4l2_m2m_job_finish(m2m_dev, m2m_ctx); | ||||
| @@ -0,0 +1,50 @@ | ||||
| From 662256810630f6ac6d06ee0cdc5f4660b25f7e98 Mon Sep 17 00:00:00 2001 | ||||
| From: Paul Kocialkowski <paul.kocialkowski@bootlin.com> | ||||
| Date: Tue, 22 Oct 2019 12:26:53 -0300 | ||||
| Subject: [PATCH] media: pixfmt: Document the HEVC slice pixel format | ||||
|  | ||||
| Commit de06f289283298e2938445019999cec46435375c upstream. | ||||
|  | ||||
| Document the current state of the HEVC slice pixel format. | ||||
| The format will need to evolve in the future, which is why it is | ||||
| not part of the public API. | ||||
|  | ||||
| Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com> | ||||
| Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> | ||||
| Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org> | ||||
| --- | ||||
|  .../media/uapi/v4l/pixfmt-compressed.rst      | 23 +++++++++++++++++++ | ||||
|  1 file changed, 23 insertions(+) | ||||
|  | ||||
| --- a/Documentation/media/uapi/v4l/pixfmt-compressed.rst | ||||
| +++ b/Documentation/media/uapi/v4l/pixfmt-compressed.rst | ||||
| @@ -188,6 +188,29 @@ Compressed Formats | ||||
|  	If :ref:`VIDIOC_ENUM_FMT` reports ``V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM`` | ||||
|  	then the decoder has no	requirements since it can parse all the | ||||
|  	information from the raw bytestream. | ||||
| +    * .. _V4L2-PIX-FMT-HEVC-SLICE: | ||||
| + | ||||
| +      - ``V4L2_PIX_FMT_HEVC_SLICE`` | ||||
| +      - 'S265' | ||||
| +      - HEVC parsed slice data, as extracted from the HEVC bitstream. | ||||
| +	This format is adapted for stateless video decoders that implement a | ||||
| +	HEVC pipeline (using the :ref:`mem2mem` and :ref:`media-request-api`). | ||||
| +	This pixelformat has two modifiers that must be set at least once | ||||
| +	through the ``V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE`` | ||||
| +        and ``V4L2_CID_MPEG_VIDEO_HEVC_START_CODE`` controls. | ||||
| +	Metadata associated with the frame to decode is required to be passed | ||||
| +	through the following controls : | ||||
| +        * ``V4L2_CID_MPEG_VIDEO_HEVC_SPS`` | ||||
| +        * ``V4L2_CID_MPEG_VIDEO_HEVC_PPS`` | ||||
| +        * ``V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS`` | ||||
| +	See the :ref:`associated Codec Control IDs <v4l2-mpeg-hevc>`. | ||||
| +	Buffers associated with this pixel format must contain the appropriate | ||||
| +	number of macroblocks to decode a full corresponding frame. | ||||
| + | ||||
| +	.. note:: | ||||
| + | ||||
| +	   This format is not yet part of the public kernel API and it | ||||
| +	   is expected to change. | ||||
|      * .. _V4L2-PIX-FMT-FWHT: | ||||
|   | ||||
|        - ``V4L2_PIX_FMT_FWHT`` | ||||
| @@ -0,0 +1,150 @@ | ||||
| From 70b5a28786215c996503210abd3e44c200771640 Mon Sep 17 00:00:00 2001 | ||||
| From: Jernej Skrabec <jernej.skrabec@siol.net> | ||||
| Date: Fri, 13 Dec 2019 17:04:25 +0100 | ||||
| Subject: [PATCH] media: uapi: hevc: Add scaling matrix control | ||||
|  | ||||
| Taken from https://patchwork.linuxtv.org/patch/60728/ | ||||
| Changes (mainly documentation) have been requested. | ||||
|  | ||||
| HEVC has a scaling matrix concept. Add support for it. | ||||
|  | ||||
| Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net> | ||||
| --- | ||||
|  .../media/uapi/v4l/ext-ctrls-codec.rst        | 41 +++++++++++++++++++ | ||||
|  .../media/uapi/v4l/pixfmt-compressed.rst      |  1 + | ||||
|  drivers/media/v4l2-core/v4l2-ctrls.c          | 10 +++++ | ||||
|  include/media/hevc-ctrls.h                    | 11 +++++ | ||||
|  4 files changed, 63 insertions(+) | ||||
|  | ||||
| --- a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst | ||||
| +++ b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst | ||||
| @@ -4174,6 +4174,47 @@ enum v4l2_mpeg_video_hevc_size_of_length | ||||
|        - ``padding[6]`` | ||||
|        - Applications and drivers must set this to zero. | ||||
|   | ||||
| +``V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX (struct)`` | ||||
| +    Specifies the scaling matrix (as extracted from the bitstream) for | ||||
| +    the associated HEVC slice data. The bitstream parameters are | ||||
| +    defined according to :ref:`hevc`, section 7.4.5 "Scaling list | ||||
| +    data semantics". For further documentation, refer to the above | ||||
| +    specification, unless there is an explicit comment stating | ||||
| +    otherwise. | ||||
| + | ||||
| +    .. note:: | ||||
| + | ||||
| +       This compound control is not yet part of the public kernel API and | ||||
| +       it is expected to change. | ||||
| + | ||||
| +.. c:type:: v4l2_ctrl_hevc_scaling_matrix | ||||
| + | ||||
| +.. cssclass:: longtable | ||||
| + | ||||
| +.. flat-table:: struct v4l2_ctrl_hevc_scaling_matrix | ||||
| +    :header-rows:  0 | ||||
| +    :stub-columns: 0 | ||||
| +    :widths:       1 1 2 | ||||
| + | ||||
| +    * - __u8 | ||||
| +      - ``scaling_list_4x4[6][16]`` | ||||
| +      - | ||||
| +    * - __u8 | ||||
| +      - ``scaling_list_8x8[6][64]`` | ||||
| +      - | ||||
| +    * - __u8 | ||||
| +      - ``scaling_list_16x16[6][64]`` | ||||
| +      - | ||||
| +    * - __u8 | ||||
| +      - ``scaling_list_32x32[2][64]`` | ||||
| +      - | ||||
| +    * - __u8 | ||||
| +      - ``scaling_list_dc_coef_16x16[6]`` | ||||
| +      - | ||||
| +    * - __u8 | ||||
| +      - ``scaling_list_dc_coef_32x32[2]`` | ||||
| +      - | ||||
| + | ||||
|  ``V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE (enum)`` | ||||
|      Specifies the decoding mode to use. Currently exposes slice-based and | ||||
|      frame-based decoding but new modes might be added later on. | ||||
| --- a/Documentation/media/uapi/v4l/pixfmt-compressed.rst | ||||
| +++ b/Documentation/media/uapi/v4l/pixfmt-compressed.rst | ||||
| @@ -203,6 +203,7 @@ Compressed Formats | ||||
|          * ``V4L2_CID_MPEG_VIDEO_HEVC_SPS`` | ||||
|          * ``V4L2_CID_MPEG_VIDEO_HEVC_PPS`` | ||||
|          * ``V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS`` | ||||
| +        * ``V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX`` | ||||
|  	See the :ref:`associated Codec Control IDs <v4l2-mpeg-hevc>`. | ||||
|  	Buffers associated with this pixel format must contain the appropriate | ||||
|  	number of macroblocks to decode a full corresponding frame. | ||||
| --- a/drivers/media/v4l2-core/v4l2-ctrls.c | ||||
| +++ b/drivers/media/v4l2-core/v4l2-ctrls.c | ||||
| @@ -974,6 +974,7 @@ const char *v4l2_ctrl_get_name(u32 id) | ||||
|  	case V4L2_CID_MPEG_VIDEO_HEVC_SPS:			return "HEVC Sequence Parameter Set"; | ||||
|  	case V4L2_CID_MPEG_VIDEO_HEVC_PPS:			return "HEVC Picture Parameter Set"; | ||||
|  	case V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS:		return "HEVC Slice Parameters"; | ||||
| +	case V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX:		return "HEVC Scaling Matrix"; | ||||
|  	case V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE:		return "HEVC Decode Mode"; | ||||
|  	case V4L2_CID_MPEG_VIDEO_HEVC_START_CODE:		return "HEVC Start Code"; | ||||
|   | ||||
| @@ -1406,6 +1407,9 @@ void v4l2_ctrl_fill(u32 id, const char * | ||||
|  	case V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS: | ||||
|  		*type = V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS; | ||||
|  		break; | ||||
| +	case V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX: | ||||
| +		*type = V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX; | ||||
| +		break; | ||||
|  	case V4L2_CID_UNIT_CELL_SIZE: | ||||
|  		*type = V4L2_CTRL_TYPE_AREA; | ||||
|  		*flags |= V4L2_CTRL_FLAG_READ_ONLY; | ||||
| @@ -1852,6 +1856,9 @@ static int std_validate_compound(const s | ||||
|  		zero_padding(*p_hevc_slice_params); | ||||
|  		break; | ||||
|   | ||||
| +	case V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX: | ||||
| +		break; | ||||
| + | ||||
|  	case V4L2_CTRL_TYPE_AREA: | ||||
|  		area = p; | ||||
|  		if (!area->width || !area->height) | ||||
| @@ -2540,6 +2547,9 @@ static struct v4l2_ctrl *v4l2_ctrl_new(s | ||||
|  	case V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS: | ||||
|  		elem_size = sizeof(struct v4l2_ctrl_hevc_slice_params); | ||||
|  		break; | ||||
| +	case V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX: | ||||
| +		elem_size = sizeof(struct v4l2_ctrl_hevc_scaling_matrix); | ||||
| +		break; | ||||
|  	case V4L2_CTRL_TYPE_AREA: | ||||
|  		elem_size = sizeof(struct v4l2_area); | ||||
|  		break; | ||||
| --- a/include/media/hevc-ctrls.h | ||||
| +++ b/include/media/hevc-ctrls.h | ||||
| @@ -19,6 +19,7 @@ | ||||
|  #define V4L2_CID_MPEG_VIDEO_HEVC_SPS		(V4L2_CID_MPEG_BASE + 1008) | ||||
|  #define V4L2_CID_MPEG_VIDEO_HEVC_PPS		(V4L2_CID_MPEG_BASE + 1009) | ||||
|  #define V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS	(V4L2_CID_MPEG_BASE + 1010) | ||||
| +#define V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX	(V4L2_CID_MPEG_BASE + 1011) | ||||
|  #define V4L2_CID_MPEG_VIDEO_HEVC_DECODE_MODE	(V4L2_CID_MPEG_BASE + 1015) | ||||
|  #define V4L2_CID_MPEG_VIDEO_HEVC_START_CODE	(V4L2_CID_MPEG_BASE + 1016) | ||||
|   | ||||
| @@ -26,6 +27,7 @@ | ||||
|  #define V4L2_CTRL_TYPE_HEVC_SPS 0x0120 | ||||
|  #define V4L2_CTRL_TYPE_HEVC_PPS 0x0121 | ||||
|  #define V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS 0x0122 | ||||
| +#define V4L2_CTRL_TYPE_HEVC_SCALING_MATRIX 0x0123 | ||||
|   | ||||
|  enum v4l2_mpeg_video_hevc_decode_mode { | ||||
|  	V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED, | ||||
| @@ -209,4 +211,13 @@ struct v4l2_ctrl_hevc_slice_params { | ||||
|  	__u64	flags; | ||||
|  }; | ||||
|   | ||||
| +struct v4l2_ctrl_hevc_scaling_matrix { | ||||
| +	__u8	scaling_list_4x4[6][16]; | ||||
| +	__u8	scaling_list_8x8[6][64]; | ||||
| +	__u8	scaling_list_16x16[6][64]; | ||||
| +	__u8	scaling_list_32x32[2][64]; | ||||
| +	__u8	scaling_list_dc_coef_16x16[6]; | ||||
| +	__u8	scaling_list_dc_coef_32x32[2]; | ||||
| +}; | ||||
| + | ||||
|  #endif | ||||
| @@ -0,0 +1,61 @@ | ||||
| From 88eb3b015b6f61252fd214d39fc7fc0379ee0442 Mon Sep 17 00:00:00 2001 | ||||
| From: Jernej Skrabec <jernej.skrabec@siol.net> | ||||
| Date: Fri, 13 Dec 2019 17:04:27 +0100 | ||||
| Subject: [PATCH] media: uapi: hevc: Add segment address field | ||||
|  | ||||
| From https://patchwork.linuxtv.org/patch/60725/ | ||||
| Changes requested, but mainly docs. | ||||
|  | ||||
| If HEVC frame consists of multiple slices, segment address has to be | ||||
| known in order to properly decode it. | ||||
|  | ||||
| Add segment address field to slice parameters. | ||||
|  | ||||
| Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net> | ||||
| --- | ||||
|  Documentation/media/uapi/v4l/ext-ctrls-codec.rst | 5 ++++- | ||||
|  include/media/hevc-ctrls.h                       | 5 ++++- | ||||
|  2 files changed, 8 insertions(+), 2 deletions(-) | ||||
|  | ||||
| --- a/Documentation/media/uapi/v4l/ext-ctrls-codec.rst | ||||
| +++ b/Documentation/media/uapi/v4l/ext-ctrls-codec.rst | ||||
| @@ -3969,6 +3969,9 @@ enum v4l2_mpeg_video_hevc_size_of_length | ||||
|      * - __u32 | ||||
|        - ``data_bit_offset`` | ||||
|        - Offset (in bits) to the video data in the current slice data. | ||||
| +    * - __u32 | ||||
| +      - ``slice_segment_addr`` | ||||
| +      - | ||||
|      * - __u8 | ||||
|        - ``nal_unit_type`` | ||||
|        - | ||||
| @@ -4046,7 +4049,7 @@ enum v4l2_mpeg_video_hevc_size_of_length | ||||
|        - ``num_rps_poc_lt_curr`` | ||||
|        - The number of reference pictures in the long-term set. | ||||
|      * - __u8 | ||||
| -      - ``padding[7]`` | ||||
| +      - ``padding[5]`` | ||||
|        - Applications and drivers must set this to zero. | ||||
|      * - struct :c:type:`v4l2_hevc_dpb_entry` | ||||
|        - ``dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]`` | ||||
| --- a/include/media/hevc-ctrls.h | ||||
| +++ b/include/media/hevc-ctrls.h | ||||
| @@ -167,6 +167,9 @@ struct v4l2_ctrl_hevc_slice_params { | ||||
|  	__u32	bit_size; | ||||
|  	__u32	data_bit_offset; | ||||
|   | ||||
| +	/* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ | ||||
| +	__u32	slice_segment_addr; | ||||
| + | ||||
|  	/* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */ | ||||
|  	__u8	nal_unit_type; | ||||
|  	__u8	nuh_temporal_id_plus1; | ||||
| @@ -200,7 +203,7 @@ struct v4l2_ctrl_hevc_slice_params { | ||||
|  	__u8	num_rps_poc_st_curr_after; | ||||
|  	__u8	num_rps_poc_lt_curr; | ||||
|   | ||||
| -	__u8	padding; | ||||
| +	__u8	padding[5]; | ||||
|   | ||||
|  	/* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ | ||||
|  	struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; | ||||
| @@ -0,0 +1,23 @@ | ||||
| From e8355c6b60adb6704c9fb863f380f2d7b457d82c Mon Sep 17 00:00:00 2001 | ||||
| From: Dave Stevenson <dave.stevenson@raspberrypi.com> | ||||
| Date: Mon, 23 Mar 2020 18:34:01 +0000 | ||||
| Subject: [PATCH] media: hevc_ctrls: Add slice param dependent slice | ||||
|  segment | ||||
|  | ||||
| Adds V4L2_HEVC_SLICE_PARAMS_FLAG_DEPENDENT_SLICE_SEGMENT define. | ||||
|  | ||||
| Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com> | ||||
| --- | ||||
|  include/media/hevc-ctrls.h | 1 + | ||||
|  1 file changed, 1 insertion(+) | ||||
|  | ||||
| --- a/include/media/hevc-ctrls.h | ||||
| +++ b/include/media/hevc-ctrls.h | ||||
| @@ -162,6 +162,7 @@ struct v4l2_hevc_pred_weight_table { | ||||
|  #define V4L2_HEVC_SLICE_PARAMS_FLAG_USE_INTEGER_MV		(1ULL << 6) | ||||
|  #define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_DEBLOCKING_FILTER_DISABLED (1ULL << 7) | ||||
|  #define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED (1ULL << 8) | ||||
| +#define V4L2_HEVC_SLICE_PARAMS_FLAG_DEPENDENT_SLICE_SEGMENT	(1ULL << 9) | ||||
|   | ||||
|  struct v4l2_ctrl_hevc_slice_params { | ||||
|  	__u32	bit_size; | ||||
| @@ -0,0 +1,40 @@ | ||||
| From 6a42d17668699234bfa2d459e29cc2732e59759b Mon Sep 17 00:00:00 2001 | ||||
| From: Dave Stevenson <dave.stevenson@raspberrypi.com> | ||||
| Date: Mon, 23 Mar 2020 19:00:17 +0000 | ||||
| Subject: [PATCH] media: uapi: Add hevc ctrls for WPP decoding | ||||
|  | ||||
| WPP can allow greater parallelism within the decode, but needs | ||||
| offset information to be passed in. | ||||
|  | ||||
| Adds num_entry_point_offsets and entry_point_offset_minus1 to | ||||
| v4l2_ctrl_hevc_slice_params. | ||||
|  | ||||
| This is based on Jernej Skrabec's patches for cedrus which | ||||
| implement the same feature. | ||||
|  | ||||
| Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com> | ||||
| --- | ||||
|  include/media/hevc-ctrls.h | 5 ++++- | ||||
|  1 file changed, 4 insertions(+), 1 deletion(-) | ||||
|  | ||||
| --- a/include/media/hevc-ctrls.h | ||||
| +++ b/include/media/hevc-ctrls.h | ||||
| @@ -170,6 +170,7 @@ struct v4l2_ctrl_hevc_slice_params { | ||||
|   | ||||
|  	/* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ | ||||
|  	__u32	slice_segment_addr; | ||||
| +	__u32	num_entry_point_offsets; | ||||
|   | ||||
|  	/* ISO/IEC 23008-2, ITU-T Rec. H.265: NAL unit header */ | ||||
|  	__u8	nal_unit_type; | ||||
| @@ -204,7 +205,9 @@ struct v4l2_ctrl_hevc_slice_params { | ||||
|  	__u8	num_rps_poc_st_curr_after; | ||||
|  	__u8	num_rps_poc_lt_curr; | ||||
|   | ||||
| -	__u8	padding[5]; | ||||
| +	__u8	padding; | ||||
| + | ||||
| +	__u32	entry_point_offset_minus1[256]; | ||||
|   | ||||
|  	/* ISO/IEC 23008-2, ITU-T Rec. H.265: General slice segment header */ | ||||
|  	struct v4l2_hevc_dpb_entry dpb[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]; | ||||
| @@ -0,0 +1,302 @@ | ||||
| From a8f52dad0ed65192eb880a4a1ca90b236e99711e Mon Sep 17 00:00:00 2001 | ||||
| From: Dave Stevenson <dave.stevenson@raspberrypi.com> | ||||
| Date: Fri, 24 Jan 2020 14:28:21 +0000 | ||||
| Subject: [PATCH] media: videodev2.h: Add a format for column YUV4:2:0 | ||||
|  modes | ||||
|  | ||||
| Some of the Broadcom codec blocks use a column based YUV4:2:0 image | ||||
| format, so add the documentation and defines for both 8 and 10 bit | ||||
| versions. | ||||
|  | ||||
| Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com> | ||||
| --- | ||||
|  .../media/uapi/v4l/pixfmt-nv12-col128.rst     | 215 ++++++++++++++++++ | ||||
|  Documentation/media/uapi/v4l/pixfmt-nv12.rst  |  14 +- | ||||
|  Documentation/media/uapi/v4l/yuv-formats.rst  |   1 + | ||||
|  drivers/media/v4l2-core/v4l2-ioctl.c          |   2 + | ||||
|  include/uapi/linux/videodev2.h                |   4 + | ||||
|  5 files changed, 233 insertions(+), 3 deletions(-) | ||||
|  create mode 100644 Documentation/media/uapi/v4l/pixfmt-nv12-col128.rst | ||||
|  | ||||
| --- /dev/null | ||||
| +++ b/Documentation/media/uapi/v4l/pixfmt-nv12-col128.rst | ||||
| @@ -0,0 +1,215 @@ | ||||
| +.. Permission is granted to copy, distribute and/or modify this | ||||
| +.. document under the terms of the GNU Free Documentation License, | ||||
| +.. Version 1.1 or any later version published by the Free Software | ||||
| +.. Foundation, with no Invariant Sections, no Front-Cover Texts | ||||
| +.. and no Back-Cover Texts. A copy of the license is included at | ||||
| +.. Documentation/media/uapi/fdl-appendix.rst. | ||||
| +.. | ||||
| +.. TODO: replace it to GFDL-1.1-or-later WITH no-invariant-sections | ||||
| + | ||||
| +.. _V4L2_PIX_FMT_NV12_COL128: | ||||
| +.. _V4L2_PIX_FMT_NV12_10_COL128: | ||||
| + | ||||
| +******************************************************************************** | ||||
| +V4L2_PIX_FMT_NV12_COL128, V4L2_PIX_FMT_NV12_10_COL128 | ||||
| +******************************************************************************** | ||||
| + | ||||
| + | ||||
| +V4L2_PIX_FMT_NV21_COL128 | ||||
| +Formats with ½ horizontal and vertical chroma resolution. This format | ||||
| +has two planes - one for luminance and one for chrominance. Chroma | ||||
| +samples are interleaved. The difference to ``V4L2_PIX_FMT_NV12`` is the | ||||
| +memory layout. The image is split into columns of 128 bytes wide rather than | ||||
| +being in raster order. | ||||
| + | ||||
| +V4L2_PIX_FMT_NV12_10_COL128 | ||||
| +Follows the same pattern as ``V4L2_PIX_FMT_NV21_COL128`` with 128 byte, but is | ||||
| +a 10bit format with 3 10-bit samples being packed into 4 bytes. Each 128 byte | ||||
| +wide column therefore contains 96 samples. | ||||
| + | ||||
| + | ||||
| +Description | ||||
| +=========== | ||||
| + | ||||
| +This is the two-plane versions of the YUV 4:2:0 format where data is | ||||
| +grouped into 128 byte wide columns. The three components are separated into | ||||
| +two sub-images or planes. The Y plane has one byte per pixel and pixels | ||||
| +are grouped into 128 byte wide columns. The CbCr plane has the same width, | ||||
| +in bytes, as the Y plane (and the image), but is half as tall in pixels. | ||||
| +The chroma plane is also in 128 byte columns, reflecting 64 Cb and 64 Cr | ||||
| +samples. | ||||
| + | ||||
| +The chroma samples for a column follow the luma samples. If there is any | ||||
| +paddding, then that will be reflected via the selection API. | ||||
| +The luma height must be a multiple of 2 lines. | ||||
| + | ||||
| +The normal bytesperline is effectively fixed at 128. However the format | ||||
| +requires knowledge of the stride between columns, therefore the bytesperline | ||||
| +value has been repurposed to denote the number of 128 byte long lines between | ||||
| +the start of each column. | ||||
| + | ||||
| +**Byte Order.** | ||||
| + | ||||
| + | ||||
| +.. flat-table:: | ||||
| +    :header-rows:  0 | ||||
| +    :stub-columns: 0 | ||||
| +    :widths: 12 12 12 12 12 4 12 12 12 12 | ||||
| + | ||||
| +    * - start + 0: | ||||
| +      - Y'\ :sub:`0,0` | ||||
| +      - Y'\ :sub:`0,1` | ||||
| +      - Y'\ :sub:`0,2` | ||||
| +      - Y'\ :sub:`0,3` | ||||
| +      - ... | ||||
| +      - Y'\ :sub:`0,124` | ||||
| +      - Y'\ :sub:`0,125` | ||||
| +      - Y'\ :sub:`0,126` | ||||
| +      - Y'\ :sub:`0,127` | ||||
| +    * - start + 128: | ||||
| +      - Y'\ :sub:`1,0` | ||||
| +      - Y'\ :sub:`1,1` | ||||
| +      - Y'\ :sub:`1,2` | ||||
| +      - Y'\ :sub:`1,3` | ||||
| +      - ... | ||||
| +      - Y'\ :sub:`1,124` | ||||
| +      - Y'\ :sub:`1,125` | ||||
| +      - Y'\ :sub:`1,126` | ||||
| +      - Y'\ :sub:`1,127` | ||||
| +    * - start + 256: | ||||
| +      - Y'\ :sub:`2,0` | ||||
| +      - Y'\ :sub:`2,1` | ||||
| +      - Y'\ :sub:`2,2` | ||||
| +      - Y'\ :sub:`2,3` | ||||
| +      - ... | ||||
| +      - Y'\ :sub:`2,124` | ||||
| +      - Y'\ :sub:`2,125` | ||||
| +      - Y'\ :sub:`2,126` | ||||
| +      - Y'\ :sub:`2,127` | ||||
| +    * - ... | ||||
| +      - ... | ||||
| +      - ... | ||||
| +      - ... | ||||
| +      - ... | ||||
| +      - ... | ||||
| +      - ... | ||||
| +      - ... | ||||
| +    * - start + ((height-1) * 128): | ||||
| +      - Y'\ :sub:`height-1,0` | ||||
| +      - Y'\ :sub:`height-1,1` | ||||
| +      - Y'\ :sub:`height-1,2` | ||||
| +      - Y'\ :sub:`height-1,3` | ||||
| +      - ... | ||||
| +      - Y'\ :sub:`height-1,124` | ||||
| +      - Y'\ :sub:`height-1,125` | ||||
| +      - Y'\ :sub:`height-1,126` | ||||
| +      - Y'\ :sub:`height-1,127` | ||||
| +    * - start + ((height) * 128): | ||||
| +      - Cb\ :sub:`0,0` | ||||
| +      - Cr\ :sub:`0,0` | ||||
| +      - Cb\ :sub:`0,1` | ||||
| +      - Cr\ :sub:`0,1` | ||||
| +      - ... | ||||
| +      - Cb\ :sub:`0,62` | ||||
| +      - Cr\ :sub:`0,62` | ||||
| +      - Cb\ :sub:`0,63` | ||||
| +      - Cr\ :sub:`0,63` | ||||
| +    * - start + ((height+1) * 128): | ||||
| +      - Cb\ :sub:`1,0` | ||||
| +      - Cr\ :sub:`1,0` | ||||
| +      - Cb\ :sub:`1,1` | ||||
| +      - Cr\ :sub:`1,1` | ||||
| +      - ... | ||||
| +      - Cb\ :sub:`1,62` | ||||
| +      - Cr\ :sub:`1,62` | ||||
| +      - Cb\ :sub:`1,63` | ||||
| +      - Cr\ :sub:`1,63` | ||||
| +    * - ... | ||||
| +      - ... | ||||
| +      - ... | ||||
| +      - ... | ||||
| +      - ... | ||||
| +      - ... | ||||
| +      - ... | ||||
| +      - ... | ||||
| +    * - start + ((height+(height/2)-1) * 128): | ||||
| +      - Cb\ :sub:`(height/2)-1,0` | ||||
| +      - Cr\ :sub:`(height/2)-1,0` | ||||
| +      - Cb\ :sub:`(height/2)-1,1` | ||||
| +      - Cr\ :sub:`(height/2)-1,1` | ||||
| +      - ... | ||||
| +      - Cb\ :sub:`(height/2)-1,62` | ||||
| +      - Cr\ :sub:`(height/2)-1,62` | ||||
| +      - Cb\ :sub:`(height/2)-1,63` | ||||
| +      - Cr\ :sub:`(height/2)-1,63` | ||||
| +    * - start + (bytesperline * 128): | ||||
| +      - Y'\ :sub:`0,128` | ||||
| +      - Y'\ :sub:`0,129` | ||||
| +      - Y'\ :sub:`0,130` | ||||
| +      - Y'\ :sub:`0,131` | ||||
| +      - ... | ||||
| +      - Y'\ :sub:`0,252` | ||||
| +      - Y'\ :sub:`0,253` | ||||
| +      - Y'\ :sub:`0,254` | ||||
| +      - Y'\ :sub:`0,255` | ||||
| +    * - ... | ||||
| +      - ... | ||||
| +      - ... | ||||
| +      - ... | ||||
| +      - ... | ||||
| +      - ... | ||||
| +      - ... | ||||
| +      - ... | ||||
| + | ||||
| +V4L2_PIX_FMT_NV12_10_COL128 uses the same 128 byte column structure, but | ||||
| +encodes 10-bit YUV. | ||||
| +3 10-bit values are packed into 4 bytes as bits 9:0, 19:10, and 29:20, with | ||||
| +bits 30 & 31 unused. For the luma plane, bits 9:0 are Y0, 19:10 are Y1, and | ||||
| +29:20 are Y2. For the chroma plane the samples always come in pairs of Cr | ||||
| +and Cb, so it needs to be considered 6 values packed in 8 bytes. | ||||
| + | ||||
| +Bit-packed representation. | ||||
| + | ||||
| +.. raw:: latex | ||||
| + | ||||
| +    \small | ||||
| + | ||||
| +.. tabularcolumns:: |p{1.2cm}||p{1.2cm}||p{1.2cm}||p{1.2cm}|p{3.2cm}|p{3.2cm}| | ||||
| + | ||||
| +.. flat-table:: | ||||
| +    :header-rows:  0 | ||||
| +    :stub-columns: 0 | ||||
| +    :widths: 8 8 8 8 | ||||
| + | ||||
| +    * - Y'\ :sub:`00[7:0]` | ||||
| +      - Y'\ :sub:`01[5:0] (bits 7--2)` Y'\ :sub:`00[9:8]`\ (bits 1--0) | ||||
| +      - Y'\ :sub:`02[3:0] (bits 7--4)` Y'\ :sub:`01[9:6]`\ (bits 3--0) | ||||
| +      - unused (bits 7--6)` Y'\ :sub:`02[9:4]`\ (bits 5--0) | ||||
| + | ||||
| +.. raw:: latex | ||||
| + | ||||
| +    \small | ||||
| + | ||||
| +.. tabularcolumns:: |p{1.2cm}||p{1.2cm}||p{1.2cm}||p{1.2cm}|p{3.2cm}|p{3.2cm}| | ||||
| + | ||||
| +.. flat-table:: | ||||
| +    :header-rows:  0 | ||||
| +    :stub-columns: 0 | ||||
| +    :widths: 12 12 12 12 12 12 12 12 | ||||
| + | ||||
| +    * - Cb\ :sub:`00[7:0]` | ||||
| +      - Cr\ :sub:`00[5:0]`\ (bits 7--2) Cb\ :sub:`00[9:8]`\ (bits 1--0) | ||||
| +      - Cb\ :sub:`01[3:0]`\ (bits 7--4) Cr\ :sub:`00[9:6]`\ (bits 3--0) | ||||
| +      - unused (bits 7--6) Cb\ :sub:`02[9:4]`\ (bits 5--0) | ||||
| +      - Cr\ :sub:`01[7:0]` | ||||
| +      - Cb\ :sub:`02[5:0]`\ (bits 7--2) Cr\ :sub:`01[9:8]`\ (bits 1--0) | ||||
| +      - Cr\ :sub:`02[3:0]`\ (bits 7--4) Cb\ :sub:`02[9:6]`\ (bits 3--0) | ||||
| +      - unused (bits 7--6) Cr\ :sub:`02[9:4]`\ (bits 5--0) | ||||
| + | ||||
| +.. raw:: latex | ||||
| + | ||||
| +    \normalsize | ||||
| + | ||||
| + | ||||
| + | ||||
| + | ||||
| --- a/Documentation/media/uapi/v4l/pixfmt-nv12.rst | ||||
| +++ b/Documentation/media/uapi/v4l/pixfmt-nv12.rst | ||||
| @@ -10,9 +10,9 @@ | ||||
|  .. _V4L2-PIX-FMT-NV12: | ||||
|  .. _V4L2-PIX-FMT-NV21: | ||||
|   | ||||
| -****************************************************** | ||||
| -V4L2_PIX_FMT_NV12 ('NV12'), V4L2_PIX_FMT_NV21 ('NV21') | ||||
| -****************************************************** | ||||
| +******************************************************************************** | ||||
| +V4L2_PIX_FMT_NV12 ('NV12'), V4L2_PIX_FMT_NV21 ('NV21'), V4L2_PIX_FMT_NV12_COL128 | ||||
| +******************************************************************************** | ||||
|   | ||||
|   | ||||
|  V4L2_PIX_FMT_NV21 | ||||
| @@ -38,6 +38,14 @@ with a Cr byte. | ||||
|  If the Y plane has pad bytes after each row, then the CbCr plane has as | ||||
|  many pad bytes after its rows. | ||||
|   | ||||
| +``V4L2_PIX_FMT_NV12_COL128`` is the tiled version of | ||||
| +``V4L2_PIX_FMT_NV12`` with the image broken down into 128 pixel wide columns of | ||||
| +Y followed by the associated combined CbCr plane. | ||||
| +The normal bytesperline is effectively fixed at 128. However the format | ||||
| +requires knowledge of the stride between columns, therefore the bytesperline | ||||
| +value has been repurposed to denote the number of 128 byte long lines between | ||||
| +the start of each column. | ||||
| + | ||||
|  **Byte Order.** | ||||
|  Each cell is one byte. | ||||
|   | ||||
| --- a/Documentation/media/uapi/v4l/yuv-formats.rst | ||||
| +++ b/Documentation/media/uapi/v4l/yuv-formats.rst | ||||
| @@ -57,6 +57,7 @@ to brightness information. | ||||
|      pixfmt-nv12 | ||||
|      pixfmt-nv12m | ||||
|      pixfmt-nv12mt | ||||
| +    pixfmt-nv12-col128 | ||||
|      pixfmt-nv16 | ||||
|      pixfmt-nv16m | ||||
|      pixfmt-nv24 | ||||
| --- a/drivers/media/v4l2-core/v4l2-ioctl.c | ||||
| +++ b/drivers/media/v4l2-core/v4l2-ioctl.c | ||||
| @@ -1258,6 +1258,8 @@ static void v4l_fill_fmtdesc(struct v4l2 | ||||
|  	case V4L2_PIX_FMT_NV61M:	descr = "Y/CrCb 4:2:2 (N-C)"; break; | ||||
|  	case V4L2_PIX_FMT_NV12MT:	descr = "Y/CbCr 4:2:0 (64x32 MB, N-C)"; break; | ||||
|  	case V4L2_PIX_FMT_NV12MT_16X16:	descr = "Y/CbCr 4:2:0 (16x16 MB, N-C)"; break; | ||||
| +	case V4L2_PIX_FMT_NV12_COL128:	descr = "Y/CbCr 4:2:0 (128b cols)"; break; | ||||
| +	case V4L2_PIX_FMT_NV12_10_COL128: descr = "10-bit Y/CbCr 4:2:0 (128b cols)"; break; | ||||
|  	case V4L2_PIX_FMT_YUV420M:	descr = "Planar YUV 4:2:0 (N-C)"; break; | ||||
|  	case V4L2_PIX_FMT_YVU420M:	descr = "Planar YVU 4:2:0 (N-C)"; break; | ||||
|  	case V4L2_PIX_FMT_YUV422M:	descr = "Planar YUV 4:2:2 (N-C)"; break; | ||||
| --- a/include/uapi/linux/videodev2.h | ||||
| +++ b/include/uapi/linux/videodev2.h | ||||
| @@ -737,6 +737,10 @@ struct v4l2_pix_format { | ||||
|  #define V4L2_PIX_FMT_INZI     v4l2_fourcc('I', 'N', 'Z', 'I') /* Intel Planar Greyscale 10-bit and Depth 16-bit */ | ||||
|  #define V4L2_PIX_FMT_SUNXI_TILED_NV12 v4l2_fourcc('S', 'T', '1', '2') /* Sunxi Tiled NV12 Format */ | ||||
|  #define V4L2_PIX_FMT_CNF4     v4l2_fourcc('C', 'N', 'F', '4') /* Intel 4-bit packed depth confidence information */ | ||||
| +#define V4L2_PIX_FMT_NV12_COL128 v4l2_fourcc('N', 'C', '1', '2') /* 12  Y/CbCr 4:2:0 128 pixel wide column */ | ||||
| +#define V4L2_PIX_FMT_NV12_10_COL128 v4l2_fourcc('N', 'C', '3', '0') | ||||
| +								/* Y/CbCr 4:2:0 10bpc, 3x10 packed as 4 bytes in | ||||
| +								 * a 128 bytes / 96 pixel wide column */ | ||||
|   | ||||
|  /* 10bit raw bayer packed, 32 bytes for every 25 pixels, last LSB 6 bits unused */ | ||||
|  #define V4L2_PIX_FMT_IPU3_SBGGR10	v4l2_fourcc('i', 'p', '3', 'b') /* IPU3 packed 10-bit BGGR bayer */ | ||||
| @@ -0,0 +1,274 @@ | ||||
| From b8ae9d55d468a9f55524296247dba93531c29c99 Mon Sep 17 00:00:00 2001 | ||||
| From: John Cox <jc@kynesim.co.uk> | ||||
| Date: Thu, 5 Mar 2020 14:46:54 +0000 | ||||
| Subject: [PATCH] media: v4l2-mem2mem: allow request job buffer | ||||
|  processing after job finish | ||||
|  | ||||
| Allow the capture buffer to be detached from a v4l2 request job such | ||||
| that another job can start before the capture buffer is returned. This | ||||
| allows h/w codecs that can process multiple requests at the same time | ||||
| to operate more efficiently. | ||||
|  | ||||
| Signed-off-by: John Cox <jc@kynesim.co.uk> | ||||
| --- | ||||
|  drivers/media/v4l2-core/v4l2-mem2mem.c | 105 +++++++++++++++++++++++-- | ||||
|  include/media/v4l2-mem2mem.h           |  47 +++++++++++ | ||||
|  include/media/videobuf2-v4l2.h         |   3 + | ||||
|  3 files changed, 149 insertions(+), 6 deletions(-) | ||||
|  | ||||
| --- a/drivers/media/v4l2-core/v4l2-mem2mem.c | ||||
| +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c | ||||
| @@ -399,15 +399,18 @@ static void v4l2_m2m_cancel_job(struct v | ||||
|  { | ||||
|  	struct v4l2_m2m_dev *m2m_dev; | ||||
|  	unsigned long flags; | ||||
| +	bool det_abort_req; | ||||
|   | ||||
|  	m2m_dev = m2m_ctx->m2m_dev; | ||||
|  	spin_lock_irqsave(&m2m_dev->job_spinlock, flags); | ||||
|   | ||||
| +	det_abort_req = !list_empty(&m2m_ctx->det_list); | ||||
|  	m2m_ctx->job_flags |= TRANS_ABORT; | ||||
|  	if (m2m_ctx->job_flags & TRANS_RUNNING) { | ||||
|  		spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); | ||||
|  		if (m2m_dev->m2m_ops->job_abort) | ||||
|  			m2m_dev->m2m_ops->job_abort(m2m_ctx->priv); | ||||
| +		det_abort_req = false; | ||||
|  		dprintk("m2m_ctx %p running, will wait to complete\n", m2m_ctx); | ||||
|  		wait_event(m2m_ctx->finished, | ||||
|  				!(m2m_ctx->job_flags & TRANS_RUNNING)); | ||||
| @@ -421,6 +424,11 @@ static void v4l2_m2m_cancel_job(struct v | ||||
|  		/* Do nothing, was not on queue/running */ | ||||
|  		spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); | ||||
|  	} | ||||
| + | ||||
| +	/* Wait for detached buffers to come back too */ | ||||
| +	if (det_abort_req && m2m_dev->m2m_ops->job_abort) | ||||
| +		m2m_dev->m2m_ops->job_abort(m2m_ctx->priv); | ||||
| +	wait_event(m2m_ctx->det_empty, list_empty(&m2m_ctx->det_list)); | ||||
|  } | ||||
|   | ||||
|  /* | ||||
| @@ -458,6 +466,7 @@ static bool _v4l2_m2m_job_finish(struct | ||||
|   | ||||
|  	list_del(&m2m_dev->curr_ctx->queue); | ||||
|  	m2m_dev->curr_ctx->job_flags &= ~(TRANS_QUEUED | TRANS_RUNNING); | ||||
| +	m2m_ctx->cap_detached = false; | ||||
|  	wake_up(&m2m_dev->curr_ctx->finished); | ||||
|  	m2m_dev->curr_ctx = NULL; | ||||
|  	return true; | ||||
| @@ -485,6 +494,80 @@ void v4l2_m2m_job_finish(struct v4l2_m2m | ||||
|  } | ||||
|  EXPORT_SYMBOL(v4l2_m2m_job_finish); | ||||
|   | ||||
| +struct vb2_v4l2_buffer *_v4l2_m2m_cap_buf_detach(struct v4l2_m2m_ctx *m2m_ctx) | ||||
| +{ | ||||
| +	struct vb2_v4l2_buffer *buf; | ||||
| + | ||||
| +	buf = v4l2_m2m_dst_buf_remove(m2m_ctx); | ||||
| +	list_add_tail(&container_of(buf, struct v4l2_m2m_buffer, vb)->list, | ||||
| +		      &m2m_ctx->det_list); | ||||
| +	m2m_ctx->cap_detached = true; | ||||
| +	buf->is_held = true; | ||||
| +	buf->det_state = VB2_BUF_STATE_ACTIVE; | ||||
| + | ||||
| +	return buf; | ||||
| +} | ||||
| + | ||||
| +struct vb2_v4l2_buffer *v4l2_m2m_cap_buf_detach(struct v4l2_m2m_dev *m2m_dev, | ||||
| +						struct v4l2_m2m_ctx *m2m_ctx) | ||||
| +{ | ||||
| +	unsigned long flags; | ||||
| +	struct vb2_v4l2_buffer *src_buf, *dst_buf; | ||||
| + | ||||
| +	spin_lock_irqsave(&m2m_dev->job_spinlock, flags); | ||||
| + | ||||
| +	dst_buf = NULL; | ||||
| +	src_buf = v4l2_m2m_next_src_buf(m2m_ctx); | ||||
| + | ||||
| +	if (!(src_buf->flags & V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF) && | ||||
| +	    !m2m_ctx->cap_detached) | ||||
| +		dst_buf = _v4l2_m2m_cap_buf_detach(m2m_ctx); | ||||
| + | ||||
| +	spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); | ||||
| +	return dst_buf; | ||||
| +} | ||||
| +EXPORT_SYMBOL(v4l2_m2m_cap_buf_detach); | ||||
| + | ||||
| +static void _v4l2_m2m_cap_buf_return(struct v4l2_m2m_ctx *m2m_ctx, | ||||
| +				     struct vb2_v4l2_buffer *buf, | ||||
| +				     enum vb2_buffer_state state) | ||||
| +{ | ||||
| +	buf->det_state = state; | ||||
| + | ||||
| +	/* | ||||
| +	 * Always signal done in the order we got stuff | ||||
| +	 * Stop if we find a buf that is still in use | ||||
| +	 */ | ||||
| +	while (!list_empty(&m2m_ctx->det_list)) { | ||||
| +		buf = &list_first_entry(&m2m_ctx->det_list, | ||||
| +					struct v4l2_m2m_buffer, list)->vb; | ||||
| +		state = buf->det_state; | ||||
| +		if (state != VB2_BUF_STATE_DONE && | ||||
| +		    state != VB2_BUF_STATE_ERROR) | ||||
| +			return; | ||||
| +		list_del(&container_of(buf, struct v4l2_m2m_buffer, vb)->list); | ||||
| +		buf->det_state = VB2_BUF_STATE_DEQUEUED; | ||||
| +		v4l2_m2m_buf_done(buf, state); | ||||
| +	} | ||||
| +	wake_up(&m2m_ctx->det_empty); | ||||
| +} | ||||
| + | ||||
| +void v4l2_m2m_cap_buf_return(struct v4l2_m2m_dev *m2m_dev, | ||||
| +			     struct v4l2_m2m_ctx *m2m_ctx, | ||||
| +			     struct vb2_v4l2_buffer *buf, | ||||
| +			     enum vb2_buffer_state state) | ||||
| +{ | ||||
| +	unsigned long flags; | ||||
| + | ||||
| +	if (!buf) | ||||
| +		return; | ||||
| + | ||||
| +	spin_lock_irqsave(&m2m_dev->job_spinlock, flags); | ||||
| +	_v4l2_m2m_cap_buf_return(m2m_ctx, buf, state); | ||||
| +	spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); | ||||
| +} | ||||
| +EXPORT_SYMBOL(v4l2_m2m_cap_buf_return); | ||||
| + | ||||
|  void v4l2_m2m_buf_done_and_job_finish(struct v4l2_m2m_dev *m2m_dev, | ||||
|  				      struct v4l2_m2m_ctx *m2m_ctx, | ||||
|  				      enum vb2_buffer_state state) | ||||
| @@ -495,15 +578,23 @@ void v4l2_m2m_buf_done_and_job_finish(st | ||||
|   | ||||
|  	spin_lock_irqsave(&m2m_dev->job_spinlock, flags); | ||||
|  	src_buf = v4l2_m2m_src_buf_remove(m2m_ctx); | ||||
| -	dst_buf = v4l2_m2m_next_dst_buf(m2m_ctx); | ||||
|   | ||||
| -	if (WARN_ON(!src_buf || !dst_buf)) | ||||
| +	if (WARN_ON(!src_buf)) | ||||
|  		goto unlock; | ||||
|  	v4l2_m2m_buf_done(src_buf, state); | ||||
| -	dst_buf->is_held = src_buf->flags & V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF; | ||||
| -	if (!dst_buf->is_held) { | ||||
| -		v4l2_m2m_dst_buf_remove(m2m_ctx); | ||||
| -		v4l2_m2m_buf_done(dst_buf, state); | ||||
| + | ||||
| +	if (!m2m_ctx->cap_detached) { | ||||
| +		dst_buf = v4l2_m2m_next_dst_buf(m2m_ctx); | ||||
| +		if (WARN_ON(!dst_buf)) | ||||
| +			goto unlock; | ||||
| + | ||||
| +		dst_buf->is_held = src_buf->flags | ||||
| +				    & V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF; | ||||
| + | ||||
| +		if (!dst_buf->is_held) { | ||||
| +			dst_buf = _v4l2_m2m_cap_buf_detach(m2m_ctx); | ||||
| +			_v4l2_m2m_cap_buf_return(m2m_ctx, dst_buf, state); | ||||
| +		} | ||||
|  	} | ||||
|  	schedule_next = _v4l2_m2m_job_finish(m2m_dev, m2m_ctx); | ||||
|  unlock: | ||||
| @@ -983,12 +1074,14 @@ struct v4l2_m2m_ctx *v4l2_m2m_ctx_init(s | ||||
|  	m2m_ctx->priv = drv_priv; | ||||
|  	m2m_ctx->m2m_dev = m2m_dev; | ||||
|  	init_waitqueue_head(&m2m_ctx->finished); | ||||
| +	init_waitqueue_head(&m2m_ctx->det_empty); | ||||
|   | ||||
|  	out_q_ctx = &m2m_ctx->out_q_ctx; | ||||
|  	cap_q_ctx = &m2m_ctx->cap_q_ctx; | ||||
|   | ||||
|  	INIT_LIST_HEAD(&out_q_ctx->rdy_queue); | ||||
|  	INIT_LIST_HEAD(&cap_q_ctx->rdy_queue); | ||||
| +	INIT_LIST_HEAD(&m2m_ctx->det_list); | ||||
|  	spin_lock_init(&out_q_ctx->rdy_spinlock); | ||||
|  	spin_lock_init(&cap_q_ctx->rdy_spinlock); | ||||
|   | ||||
| --- a/include/media/v4l2-mem2mem.h | ||||
| +++ b/include/media/v4l2-mem2mem.h | ||||
| @@ -88,6 +88,9 @@ struct v4l2_m2m_queue_ctx { | ||||
|   *		%TRANS_QUEUED, %TRANS_RUNNING and %TRANS_ABORT. | ||||
|   * @finished: Wait queue used to signalize when a job queue finished. | ||||
|   * @priv: Instance private data | ||||
| + * @cap_detached: Current job's capture buffer has been detached | ||||
| + * @det_list: List of detached (post-job but still in flight) capture buffers | ||||
| + * @det_empty: Wait queue signalled when det_list goes empty | ||||
|   * | ||||
|   * The memory to memory context is specific to a file handle, NOT to e.g. | ||||
|   * a device. | ||||
| @@ -111,6 +114,11 @@ struct v4l2_m2m_ctx { | ||||
|  	wait_queue_head_t		finished; | ||||
|   | ||||
|  	void				*priv; | ||||
| + | ||||
| +	/* Detached buffer handling */ | ||||
| +	bool	cap_detached; | ||||
| +	struct list_head		det_list; | ||||
| +	wait_queue_head_t		det_empty; | ||||
|  }; | ||||
|   | ||||
|  /** | ||||
| @@ -216,6 +224,45 @@ v4l2_m2m_buf_done(struct vb2_v4l2_buffer | ||||
|  } | ||||
|   | ||||
|  /** | ||||
| + * v4l2_m2m_cap_buf_detach() - detach the capture buffer from the job and | ||||
| + * return it. | ||||
| + * | ||||
| + * @m2m_dev: opaque pointer to the internal data to handle M2M context | ||||
| + * @m2m_ctx: m2m context assigned to the instance given by struct &v4l2_m2m_ctx | ||||
| + * | ||||
| + * This function is designed to be used in conjunction with | ||||
| + * v4l2_m2m_buf_done_and_job_finish(). It allows the next job to start | ||||
| + * execution before the capture buffer is returned to the user which can be | ||||
| + * important if the underlying processing has multiple phases that are more | ||||
| + * efficiently executed in parallel. | ||||
| + * | ||||
| + * If used then it must be called before v4l2_m2m_buf_done_and_job_finish() | ||||
| + * as otherwise the buffer will have already gone. | ||||
| + * | ||||
| + * It is the callers reponsibilty to ensure that all detached buffers are | ||||
| + * returned. | ||||
| + */ | ||||
| +struct vb2_v4l2_buffer *v4l2_m2m_cap_buf_detach(struct v4l2_m2m_dev *m2m_dev, | ||||
| +						struct v4l2_m2m_ctx *m2m_ctx); | ||||
| + | ||||
| +/** | ||||
| + * v4l2_m2m_cap_buf_return() - return a capture buffer, previously detached | ||||
| + * with v4l2_m2m_cap_buf_detach() to the user. | ||||
| + * | ||||
| + * @m2m_dev: opaque pointer to the internal data to handle M2M context | ||||
| + * @m2m_ctx: m2m context assigned to the instance given by struct &v4l2_m2m_ctx | ||||
| + * @buf: the buffer to return | ||||
| + * @state: vb2 buffer state passed to v4l2_m2m_buf_done(). | ||||
| + * | ||||
| + * Buffers returned by this function will be returned to the user in the order | ||||
| + * of the original jobs rather than the order in which this function is called. | ||||
| + */ | ||||
| +void v4l2_m2m_cap_buf_return(struct v4l2_m2m_dev *m2m_dev, | ||||
| +			     struct v4l2_m2m_ctx *m2m_ctx, | ||||
| +			     struct vb2_v4l2_buffer *buf, | ||||
| +			     enum vb2_buffer_state state); | ||||
| + | ||||
| +/** | ||||
|   * v4l2_m2m_reqbufs() - multi-queue-aware REQBUFS multiplexer | ||||
|   * | ||||
|   * @file: pointer to struct &file | ||||
| --- a/include/media/videobuf2-v4l2.h | ||||
| +++ b/include/media/videobuf2-v4l2.h | ||||
| @@ -35,6 +35,8 @@ | ||||
|   * @request_fd:	the request_fd associated with this buffer | ||||
|   * @is_held:	if true, then this capture buffer was held | ||||
|   * @planes:	plane information (userptr/fd, length, bytesused, data_offset). | ||||
| + * @det_state:	if a detached request capture buffer then this contains its | ||||
| + *		current state | ||||
|   * | ||||
|   * Should contain enough information to be able to cover all the fields | ||||
|   * of &struct v4l2_buffer at ``videodev2.h``. | ||||
| @@ -49,6 +51,7 @@ struct vb2_v4l2_buffer { | ||||
|  	__s32			request_fd; | ||||
|  	bool			is_held; | ||||
|  	struct vb2_plane	planes[VB2_MAX_PLANES]; | ||||
| +	enum vb2_buffer_state	det_state; | ||||
|  }; | ||||
|   | ||||
|  /* VB2 V4L2 flags as set in vb2_queue.subsystem_flags */ | ||||
| @@ -0,0 +1,106 @@ | ||||
| From 15b4e8fa2d5101b989856c42cdae6ec764c99db0 Mon Sep 17 00:00:00 2001 | ||||
| From: Dave Stevenson <dave.stevenson@raspberrypi.com> | ||||
| Date: Tue, 17 Mar 2020 10:53:16 +0000 | ||||
| Subject: [PATCH] media: dt-bindings: media: Add binding for the | ||||
|  Raspberry PI HEVC decoder | ||||
|  | ||||
| Adds a binding for the HEVC decoder found on the BCM2711 / Raspberry Pi 4. | ||||
|  | ||||
| Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com> | ||||
| --- | ||||
|  .../bindings/media/rpivid_hevc.yaml           | 72 +++++++++++++++++++ | ||||
|  MAINTAINERS                                   |  7 ++ | ||||
|  2 files changed, 79 insertions(+) | ||||
|  create mode 100644 Documentation/devicetree/bindings/media/rpivid_hevc.yaml | ||||
|  | ||||
| --- /dev/null | ||||
| +++ b/Documentation/devicetree/bindings/media/rpivid_hevc.yaml | ||||
| @@ -0,0 +1,72 @@ | ||||
| +# SPDX-License-Identifier: GPL-2.0-only | ||||
| +%YAML 1.2 | ||||
| +--- | ||||
| +$id: http://devicetree.org/schemas/media/rpivid_hevc.yaml# | ||||
| +$schema: http://devicetree.org/meta-schemas/core.yaml# | ||||
| + | ||||
| +title: Raspberry Pi HEVC Decoder | ||||
| + | ||||
| +maintainers: | ||||
| +  - Raspberry Pi <kernel-list@raspberrypi.com> | ||||
| + | ||||
| +description: |- | ||||
| +  The Camera Adaptation Layer (CAL) is a key component for image capture | ||||
| +  applications. The capture module provides the system interface and the | ||||
| +  processing capability to connect CSI2 image-sensor modules to the | ||||
| +  DRA72x device. | ||||
| + | ||||
| +properties: | ||||
| +  compatible: | ||||
| +    enum: | ||||
| +      - raspberrypi,rpivid-vid-decoder | ||||
| + | ||||
| +  reg: | ||||
| +    minItems: 2 | ||||
| +    items: | ||||
| +      - description: The HEVC main register region | ||||
| +      - description: The Interrupt controller register region | ||||
| + | ||||
| +  reg-names: | ||||
| +    minItems: 2 | ||||
| +    items: | ||||
| +      - const: hevc | ||||
| +      - const: intc | ||||
| + | ||||
| +  interrupts: | ||||
| +    maxItems: 1 | ||||
| + | ||||
| +  clocks: | ||||
| +    items: | ||||
| +      - description: The HEVC block clock | ||||
| + | ||||
| +  clock-names: | ||||
| +    items: | ||||
| +      - const: hevc | ||||
| + | ||||
| +required: | ||||
| +  - compatible | ||||
| +  - reg | ||||
| +  - reg-names | ||||
| +  - interrupts | ||||
| +  - clocks | ||||
| + | ||||
| +additionalProperties: false | ||||
| + | ||||
| +examples: | ||||
| +  - | | ||||
| +    #include <dt-bindings/interrupt-controller/arm-gic.h> | ||||
| + | ||||
| +    video-codec@7eb10000 { | ||||
| +        compatible = "raspberrypi,rpivid-vid-decoder"; | ||||
| +        reg = <0x0 0x7eb10000 0x1000>,	/* INTC */ | ||||
| +              <0x0 0x7eb00000 0x10000>; /* HEVC */ | ||||
| +        reg-names = "intc", | ||||
| +                    "hevc"; | ||||
| + | ||||
| +        interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>; | ||||
| + | ||||
| +        clocks = <&clk 0>; | ||||
| +        clock-names = "hevc"; | ||||
| +    }; | ||||
| + | ||||
| +... | ||||
| --- a/MAINTAINERS | ||||
| +++ b/MAINTAINERS | ||||
| @@ -3198,6 +3198,13 @@ N:	bcm2711 | ||||
|  N:	bcm2835 | ||||
|  F:	drivers/staging/vc04_services | ||||
|   | ||||
| +BROADCOM BCM2711 HEVC DECODER | ||||
| +M:	Raspberry Pi Kernel Maintenance <kernel-list@raspberrypi.com> | ||||
| +L:	linux-media@vger.kernel.org | ||||
| +S:	Maintained | ||||
| +F:	Documentation/devicetree/bindings/media/rpivid_hevc.jaml | ||||
| +F:	drivers/staging/media/rpivid | ||||
| + | ||||
|  BROADCOM BCM2835 CAMERA DRIVER | ||||
|  M:	Dave Stevenson <dave.stevenson@raspberrypi.org> | ||||
|  L:	linux-media@vger.kernel.org | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -0,0 +1,102 @@ | ||||
| From b1d6499e00b6061ecc7061335199acf86f54d31a Mon Sep 17 00:00:00 2001 | ||||
| From: Dave Stevenson <dave.stevenson@raspberrypi.com> | ||||
| Date: Fri, 13 Mar 2020 16:52:55 +0000 | ||||
| Subject: [PATCH] dtoverlays: Add overlay to enable the HEVC V4L2 | ||||
|  driver | ||||
|  | ||||
| This replaces the rpivid_mem register mapping driver. | ||||
| When the driver is complete, these DT changes should be | ||||
| merged into the base DT instead of being an overlay. | ||||
|  | ||||
| Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com> | ||||
| --- | ||||
|  arch/arm/boot/dts/overlays/Makefile           |  1 + | ||||
|  arch/arm/boot/dts/overlays/README             |  7 +++ | ||||
|  .../boot/dts/overlays/rpivid-v4l2-overlay.dts | 55 +++++++++++++++++++ | ||||
|  4 files changed, 63 insertions(+), 2 deletions(-) | ||||
|  create mode 100644 arch/arm/boot/dts/overlays/rpivid-v4l2-overlay.dts | ||||
|  | ||||
| --- a/arch/arm/boot/dts/overlays/Makefile | ||||
| +++ b/arch/arm/boot/dts/overlays/Makefile | ||||
| @@ -140,6 +140,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ | ||||
|  	rpi-proto.dtbo \ | ||||
|  	rpi-sense.dtbo \ | ||||
|  	rpi-tv.dtbo \ | ||||
| +	rpivid-v4l2.dtbo \ | ||||
|  	rra-digidac1-wm8741-audio.dtbo \ | ||||
|  	sc16is750-i2c.dtbo \ | ||||
|  	sc16is752-i2c.dtbo \ | ||||
| --- a/arch/arm/boot/dts/overlays/README | ||||
| +++ b/arch/arm/boot/dts/overlays/README | ||||
| @@ -2064,6 +2064,13 @@ Load:   dtoverlay=rpi-tv | ||||
|  Params: <None> | ||||
|   | ||||
|   | ||||
| +Name:   rpivid-v4l2 | ||||
| +Info:   Load the V4L2 stateless video decoder driver for the HEVC block, | ||||
| +        disabling the memory mapped devices in the process. | ||||
| +Load:   dtoverlay=rpivid-v4l2 | ||||
| +Params: <None> | ||||
| + | ||||
| + | ||||
|  Name:   rra-digidac1-wm8741-audio | ||||
|  Info:   Configures the Red Rocks Audio DigiDAC1 soundcard | ||||
|  Load:   dtoverlay=rra-digidac1-wm8741-audio | ||||
| --- /dev/null | ||||
| +++ b/arch/arm/boot/dts/overlays/rpivid-v4l2-overlay.dts | ||||
| @@ -0,0 +1,55 @@ | ||||
| +// SPDX-License-Identifier: GPL-2.0-only | ||||
| +// Definitions for Raspberry Pi video decode engine | ||||
| +/dts-v1/; | ||||
| +/plugin/; | ||||
| + | ||||
| +#include <dt-bindings/interrupt-controller/arm-gic.h> | ||||
| + | ||||
| +/{ | ||||
| +	compatible = "brcm,bcm2711"; | ||||
| + | ||||
| +	fragment@0 { | ||||
| +		target = <&scb>; | ||||
| +		__overlay__ { | ||||
| +			/* needed to avoid dtc warning */ | ||||
| +			#address-cells = <2>; | ||||
| +			#size-cells = <1>; | ||||
| +			codec@7eb10000 { | ||||
| +				compatible = "raspberrypi,rpivid-vid-decoder"; | ||||
| +				reg = <0x0 0x7eb10000 0x1000>,	/* INTC */ | ||||
| +				      <0x0 0x7eb00000 0x10000>; /* HEVC */ | ||||
| +				reg-names = "intc", | ||||
| +					    "hevc"; | ||||
| + | ||||
| +				interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>; | ||||
| + | ||||
| +				clocks = <&hevc_clk>; | ||||
| +				clock-names = "hevc"; | ||||
| + | ||||
| +				hevc_clk: hevc_clk { | ||||
| +					compatible = "fixed-clock"; | ||||
| +					#clock-cells = <0>; | ||||
| +					clock-frequency = <500000000>; | ||||
| +				}; | ||||
| +			}; | ||||
| +		}; | ||||
| +	}; | ||||
| + | ||||
| +	fragment@1 { | ||||
| +		target = <&scb>; | ||||
| +		__overlay__ { | ||||
| +			hevc-decoder@7eb00000 { | ||||
| +				status = "disabled"; | ||||
| +			}; | ||||
| +			rpivid-local-intc@7eb10000 { | ||||
| +				status = "disabled"; | ||||
| +			}; | ||||
| +			h264-decoder@7eb20000 { | ||||
| +				status = "disabled"; | ||||
| +			}; | ||||
| +			vp9-decoder@7eb30000 { | ||||
| +				status = "disabled"; | ||||
| +			}; | ||||
| +		}; | ||||
| +	}; | ||||
| +}; | ||||
		Reference in New Issue
	
	Block a user
	 Álvaro Fernández Rojas
					Álvaro Fernández Rojas