diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-10-29 14:29:58 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-10-29 14:29:58 -0700 |
commit | 134bf98c5596605af90f104716ef912e8f7eb56b (patch) | |
tree | b41d585cc432100933e790ad8cab21e970e6d8f6 | |
parent | 044ee890286153a1aefb40cb8b6659921aecb38b (diff) | |
parent | 3b796aa60af087f5fec75aee9b17f2130f2b9adc (diff) | |
download | linux-134bf98c5596605af90f104716ef912e8f7eb56b.tar.bz2 |
Merge tag 'media/v4.20-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab:
- new dvb frontend driver: lnbh29
- new sensor drivers: imx319 and imx 355
- some old soc_camera driver renames to avoid conflict with new
drivers
- new i.MX Pixel Pipeline (PXP) mem-to-mem platform driver
- a new V4L2 frontend for the FWHT codec
- several other improvements, bug fixes, code cleanups, etc
* tag 'media/v4.20-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (289 commits)
media: rename soc_camera I2C drivers
media: cec: forgot to cancel delayed work
media: vivid: Support 480p for webcam capture
media: v4l2-tpg: fix kernel oops when enabling HFLIP and OSD
media: vivid: Add 16-bit bayer to format list
media: v4l2-tpg-core: Add 16-bit bayer
media: pvrusb2: replace `printk` with `pr_*`
media: venus: vdec: fix decoded data size
media: cx231xx: fix potential sign-extension overflow on large shift
media: dt-bindings: media: rcar_vin: add device tree support for r8a7744
media: isif: fix a NULL pointer dereference bug
media: exynos4-is: make const array config_ids static
media: cx23885: make const array addr_list static
media: ivtv: make const array addr_list static
media: bttv-input: make const array addr_list static
media: cx18: Don't check for address of video_dev
media: dw9807-vcm: Fix probe error handling
media: dw9714: Remove useless error message
media: dw9714: Fix error handling in probe function
media: cec: name for RC passthrough device does not need 'RC for'
...
578 files changed, 14612 insertions, 4590 deletions
diff --git a/Documentation/devicetree/bindings/media/fsl-pxp.txt b/Documentation/devicetree/bindings/media/fsl-pxp.txt new file mode 100644 index 000000000000..2477e7f87381 --- /dev/null +++ b/Documentation/devicetree/bindings/media/fsl-pxp.txt @@ -0,0 +1,26 @@ +Freescale Pixel Pipeline +======================== + +The Pixel Pipeline (PXP) is a memory-to-memory graphics processing engine +that supports scaling, colorspace conversion, alpha blending, rotation, and +pixel conversion via lookup table. Different versions are present on various +i.MX SoCs from i.MX23 to i.MX7. + +Required properties: +- compatible: should be "fsl,<soc>-pxp", where SoC can be one of imx23, imx28, + imx6dl, imx6sl, imx6ul, imx6sx, imx6ull, or imx7d. +- reg: the register base and size for the device registers +- interrupts: the PXP interrupt, two interrupts for imx6ull and imx7d. +- clock-names: should be "axi" +- clocks: the PXP AXI clock + +Example: + +pxp@21cc000 { + compatible = "fsl,imx6ull-pxp"; + reg = <0x021cc000 0x4000>; + interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>; + clock-names = "axi"; + clocks = <&clks IMX6UL_CLK_PXP>; +}; diff --git a/Documentation/devicetree/bindings/media/i2c/adv748x.txt b/Documentation/devicetree/bindings/media/i2c/adv748x.txt index 21ffb5ed8183..5dddc95f9cc4 100644 --- a/Documentation/devicetree/bindings/media/i2c/adv748x.txt +++ b/Documentation/devicetree/bindings/media/i2c/adv748x.txt @@ -10,7 +10,11 @@ Required Properties: - "adi,adv7481" for the ADV7481 - "adi,adv7482" for the ADV7482 - - reg: I2C slave address + - reg: I2C slave addresses + The ADV748x has up to twelve 256-byte maps that can be accessed via the + main I2C ports. Each map has it own I2C address and acts as a standard + slave device on the I2C bus. The main address is mandatory, others are + optional and remain at default values if not specified. Optional Properties: @@ -18,6 +22,11 @@ Optional Properties: "intrq3". All interrupts are optional. The "intrq3" interrupt is only available on the adv7481 - interrupts: Specify the interrupt lines for the ADV748x + - reg-names : Names of maps with programmable addresses. + It shall contain all maps needing a non-default address. + Possible map names are: + "main", "dpll", "cp", "hdmi", "edid", "repeater", + "infoframe", "cbus", "cec", "sdp", "txa", "txb" The device node must contain one 'port' child node per device input and output port, in accordance with the video interface bindings defined in @@ -47,7 +56,10 @@ Example: video-receiver@70 { compatible = "adi,adv7482"; - reg = <0x70>; + reg = <0x70 0x71 0x72 0x73 0x74 0x75 + 0x60 0x61 0x62 0x63 0x64 0x65>; + reg-names = "main", "dpll", "cp", "hdmi", "edid", "repeater", + "infoframe", "cbus", "cec", "sdp", "txa", "txb"; #address-cells = <1>; #size-cells = <0>; @@ -73,7 +85,7 @@ Example: }; }; - port@10 { + port@a { reg = <10>; adv7482_txa: endpoint { @@ -83,7 +95,7 @@ Example: }; }; - port@11 { + port@b { reg = <11>; adv7482_txb: endpoint { diff --git a/Documentation/devicetree/bindings/media/i2c/adv7604.txt b/Documentation/devicetree/bindings/media/i2c/adv7604.txt index dcf57e7c60eb..b3e688b77a38 100644 --- a/Documentation/devicetree/bindings/media/i2c/adv7604.txt +++ b/Documentation/devicetree/bindings/media/i2c/adv7604.txt @@ -66,7 +66,7 @@ Example: * other maps will retain their default addresses. */ reg = <0x4c>, <0x66>; - reg-names "main", "edid"; + reg-names = "main", "edid"; reset-gpios = <&ioexp 0 GPIO_ACTIVE_LOW>; hpd-gpios = <&ioexp 2 GPIO_ACTIVE_HIGH>; diff --git a/Documentation/devicetree/bindings/media/i2c/dongwoon,dw9807.txt b/Documentation/devicetree/bindings/media/i2c/dongwoon,dw9807-vcm.txt index c4701f1eaaf6..c4701f1eaaf6 100644 --- a/Documentation/devicetree/bindings/media/i2c/dongwoon,dw9807.txt +++ b/Documentation/devicetree/bindings/media/i2c/dongwoon,dw9807-vcm.txt diff --git a/Documentation/devicetree/bindings/media/rcar_vin.txt b/Documentation/devicetree/bindings/media/rcar_vin.txt index 2f420050d57f..d329a4e8ac58 100644 --- a/Documentation/devicetree/bindings/media/rcar_vin.txt +++ b/Documentation/devicetree/bindings/media/rcar_vin.txt @@ -11,6 +11,7 @@ on Gen3 platforms to a CSI-2 receiver. - compatible: Must be one or more of the following - "renesas,vin-r8a7743" for the R8A7743 device + - "renesas,vin-r8a7744" for the R8A7744 device - "renesas,vin-r8a7745" for the R8A7745 device - "renesas,vin-r8a7778" for the R8A7778 device - "renesas,vin-r8a7779" for the R8A7779 device diff --git a/Documentation/devicetree/bindings/media/renesas,ceu.txt b/Documentation/devicetree/bindings/media/renesas,ceu.txt index 8a7a616e9019..3e2a2652eb19 100644 --- a/Documentation/devicetree/bindings/media/renesas,ceu.txt +++ b/Documentation/devicetree/bindings/media/renesas,ceu.txt @@ -17,15 +17,19 @@ Required properties: The CEU supports a single parallel input and should contain a single 'port' subnode with a single 'endpoint'. Connection to input devices are modeled according to the video interfaces OF bindings specified in: -Documentation/devicetree/bindings/media/video-interfaces.txt +[1] Documentation/devicetree/bindings/media/video-interfaces.txt Optional endpoint properties applicable to parallel input bus described in the above mentioned "video-interfaces.txt" file are supported. -- hsync-active: Active state of the HSYNC signal, 0/1 for LOW/HIGH respectively. - If property is not present, default is active high. -- vsync-active: Active state of the VSYNC signal, 0/1 for LOW/HIGH respectively. - If property is not present, default is active high. +- hsync-active: See [1] for description. If property is not present, + default is active high. +- vsync-active: See [1] for description. If property is not present, + default is active high. +- bus-width: See [1] for description. Accepted values are '8' and '16'. + If property is not present, default is '8'. +- field-even-active: See [1] for description. If property is not present, + an even field is identified by a logic 0 (active-low signal). Example: diff --git a/Documentation/devicetree/bindings/media/video-interfaces.txt b/Documentation/devicetree/bindings/media/video-interfaces.txt index baf9d9756b3c..f884ada0bffc 100644 --- a/Documentation/devicetree/bindings/media/video-interfaces.txt +++ b/Documentation/devicetree/bindings/media/video-interfaces.txt @@ -100,10 +100,12 @@ Optional endpoint properties slave device (data source) by the master device (data sink). In the master mode the data source device is also the source of the synchronization signals. - bus-type: data bus type. Possible values are: - 0 - autodetect based on other properties (MIPI CSI-2 D-PHY, parallel or Bt656) 1 - MIPI CSI-2 C-PHY 2 - MIPI CSI1 3 - CCP2 + 4 - MIPI CSI-2 D-PHY + 5 - Parallel + 6 - Bt.656 - bus-width: number of data lines actively used, valid for the parallel busses. - data-shift: on the parallel data busses, if bus-width is used to specify the number of data lines, data-shift can be used to specify which data lines are diff --git a/Documentation/media/kapi/cec-core.rst b/Documentation/media/kapi/cec-core.rst index 1d989c544370..bca1d9d1d223 100644 --- a/Documentation/media/kapi/cec-core.rst +++ b/Documentation/media/kapi/cec-core.rst @@ -268,6 +268,10 @@ to 1, if the hardware does support retry then either set these counters to 0 if the hardware provides no feedback of which errors occurred and how many times, or fill in the correct values as reported by the hardware. +Be aware that calling these functions can immediately start a new transmit +if there is one pending in the queue. So make sure that the hardware is in +a state where new transmits can be started *before* calling these functions. + The cec_transmit_attempt_done() function is a helper for cases where the hardware never retries, so the transmit is always for just a single attempt. It will call cec_transmit_done() in turn, filling in 1 for the diff --git a/Documentation/media/kapi/v4l2-subdev.rst b/Documentation/media/kapi/v4l2-subdev.rst index e1f0b726e438..1280e05b662b 100644 --- a/Documentation/media/kapi/v4l2-subdev.rst +++ b/Documentation/media/kapi/v4l2-subdev.rst @@ -247,20 +247,28 @@ performed using the :c:func:`v4l2_async_unregister_subdev` call. Subdevices registered this way are stored in a global list of subdevices, ready to be picked up by bridge drivers. -Bridge drivers in turn have to register a notifier object with an array of -subdevice descriptors that the bridge device needs for its operation. This is +Bridge drivers in turn have to register a notifier object. This is performed using the :c:func:`v4l2_async_notifier_register` call. To unregister the notifier the driver has to call :c:func:`v4l2_async_notifier_unregister`. The former of the two functions -takes two arguments: a pointer to struct :c:type:`v4l2_device` and a pointer to -struct :c:type:`v4l2_async_notifier`. The latter contains a pointer to an array -of pointers to subdevice descriptors of type struct :c:type:`v4l2_async_subdev` -type. The V4L2 core will then use these descriptors to match asynchronously -registered -subdevices to them. If a match is detected the ``.bound()`` notifier callback -is called. After all subdevices have been located the .complete() callback is -called. When a subdevice is removed from the system the .unbind() method is -called. All three callbacks are optional. +takes two arguments: a pointer to struct :c:type:`v4l2_device` and a +pointer to struct :c:type:`v4l2_async_notifier`. + +Before registering the notifier, bridge drivers must do two things: +first, the notifier must be initialized using the +:c:func:`v4l2_async_notifier_init`. Second, bridge drivers can then +begin to form a list of subdevice descriptors that the bridge device +needs for its operation. Subdevice descriptors are added to the notifier +using the :c:func:`v4l2_async_notifier_add_subdev` call. This function +takes two arguments: a pointer to struct :c:type:`v4l2_async_notifier`, +and a pointer to the subdevice descripter, which is of type struct +:c:type:`v4l2_async_subdev`. + +The V4L2 core will then use these descriptors to match asynchronously +registered subdevices to them. If a match is detected the ``.bound()`` +notifier callback is called. After all subdevices have been located the +.complete() callback is called. When a subdevice is removed from the +system the .unbind() method is called. All three callbacks are optional. V4L2 sub-device userspace API ----------------------------- diff --git a/Documentation/media/uapi/cec/cec-func-poll.rst b/Documentation/media/uapi/cec/cec-func-poll.rst index d49f1ee0742d..c698c969635c 100644 --- a/Documentation/media/uapi/cec/cec-func-poll.rst +++ b/Documentation/media/uapi/cec/cec-func-poll.rst @@ -74,4 +74,5 @@ is returned, and the ``errno`` variable is set appropriately: The call was interrupted by a signal. ``EINVAL`` - The ``nfds`` argument is greater than ``OPEN_MAX``. + The ``nfds`` value exceeds the ``RLIMIT_NOFILE`` value. Use + ``getrlimit()`` to obtain this value. diff --git a/Documentation/media/uapi/cec/cec-ioc-receive.rst b/Documentation/media/uapi/cec/cec-ioc-receive.rst index e964074cd15b..b25e48afaa08 100644 --- a/Documentation/media/uapi/cec/cec-ioc-receive.rst +++ b/Documentation/media/uapi/cec/cec-ioc-receive.rst @@ -16,10 +16,10 @@ CEC_RECEIVE, CEC_TRANSMIT - Receive or transmit a CEC message Synopsis ======== -.. c:function:: int ioctl( int fd, CEC_RECEIVE, struct cec_msg *argp ) +.. c:function:: int ioctl( int fd, CEC_RECEIVE, struct cec_msg \*argp ) :name: CEC_RECEIVE -.. c:function:: int ioctl( int fd, CEC_TRANSMIT, struct cec_msg *argp ) +.. c:function:: int ioctl( int fd, CEC_TRANSMIT, struct cec_msg \*argp ) :name: CEC_TRANSMIT Arguments @@ -272,6 +272,19 @@ View On' messages from initiator 0xf ('Unregistered') to destination 0 ('TV'). - The transmit failed after one or more retries. This status bit is mutually exclusive with :ref:`CEC_TX_STATUS_OK <CEC-TX-STATUS-OK>`. Other bits can still be set to explain which failures were seen. + * .. _`CEC-TX-STATUS-ABORTED`: + + - ``CEC_TX_STATUS_ABORTED`` + - 0x40 + - The transmit was aborted due to an HDMI disconnect, or the adapter + was unconfigured, or a transmit was interrupted, or the driver + returned an error when attempting to start a transmit. + * .. _`CEC-TX-STATUS-TIMEOUT`: + + - ``CEC_TX_STATUS_TIMEOUT`` + - 0x80 + - The transmit timed out. This should not normally happen and this + indicates a driver problem. .. tabularcolumns:: |p{5.6cm}|p{0.9cm}|p{11.0cm}| @@ -300,6 +313,14 @@ View On' messages from initiator 0xf ('Unregistered') to destination 0 ('TV'). - The message was received successfully but the reply was ``CEC_MSG_FEATURE_ABORT``. This status is only set if this message was the reply to an earlier transmitted message. + * .. _`CEC-RX-STATUS-ABORTED`: + + - ``CEC_RX_STATUS_ABORTED`` + - 0x08 + - The wait for a reply to an earlier transmitted message was aborted + because the HDMI cable was disconnected, the adapter was unconfigured + or the :ref:`CEC_TRANSMIT <CEC_RECEIVE>` that waited for a + reply was interrupted. diff --git a/Documentation/media/uapi/mediactl/media-ioc-device-info.rst b/Documentation/media/uapi/mediactl/media-ioc-device-info.rst index 649cb3d9e058..c6f224e404b7 100644 --- a/Documentation/media/uapi/mediactl/media-ioc-device-info.rst +++ b/Documentation/media/uapi/mediactl/media-ioc-device-info.rst @@ -26,6 +26,7 @@ Arguments File descriptor returned by :ref:`open() <media-func-open>`. ``argp`` + Pointer to struct :c:type:`media_device_info`. Description diff --git a/Documentation/media/uapi/mediactl/media-ioc-enum-entities.rst b/Documentation/media/uapi/mediactl/media-ioc-enum-entities.rst index fc2e39c070c9..02738640e34e 100644 --- a/Documentation/media/uapi/mediactl/media-ioc-enum-entities.rst +++ b/Documentation/media/uapi/mediactl/media-ioc-enum-entities.rst @@ -26,6 +26,7 @@ Arguments File descriptor returned by :ref:`open() <media-func-open>`. ``argp`` + Pointer to struct :c:type:`media_entity_desc`. Description diff --git a/Documentation/media/uapi/mediactl/media-ioc-enum-links.rst b/Documentation/media/uapi/mediactl/media-ioc-enum-links.rst index f158c134e9b0..b89aaae373df 100644 --- a/Documentation/media/uapi/mediactl/media-ioc-enum-links.rst +++ b/Documentation/media/uapi/mediactl/media-ioc-enum-links.rst @@ -26,6 +26,7 @@ Arguments File descriptor returned by :ref:`open() <media-func-open>`. ``argp`` + Pointer to struct :c:type:`media_links_enum`. Description diff --git a/Documentation/media/uapi/mediactl/media-ioc-g-topology.rst b/Documentation/media/uapi/mediactl/media-ioc-g-topology.rst index bac128c7eda9..4e1c59238371 100644 --- a/Documentation/media/uapi/mediactl/media-ioc-g-topology.rst +++ b/Documentation/media/uapi/mediactl/media-ioc-g-topology.rst @@ -26,6 +26,7 @@ Arguments File descriptor returned by :ref:`open() <media-func-open>`. ``argp`` + Pointer to struct :c:type:`media_v2_topology`. Description diff --git a/Documentation/media/uapi/mediactl/media-ioc-setup-link.rst b/Documentation/media/uapi/mediactl/media-ioc-setup-link.rst index ae5194940100..e345e7dc9ad7 100644 --- a/Documentation/media/uapi/mediactl/media-ioc-setup-link.rst +++ b/Documentation/media/uapi/mediactl/media-ioc-setup-link.rst @@ -26,6 +26,7 @@ Arguments File descriptor returned by :ref:`open() <media-func-open>`. ``argp`` + Pointer to struct :c:type:`media_link_desc`. Description diff --git a/Documentation/media/uapi/v4l/biblio.rst b/Documentation/media/uapi/v4l/biblio.rst index 1cedcfc04327..386d6cf83e9c 100644 --- a/Documentation/media/uapi/v4l/biblio.rst +++ b/Documentation/media/uapi/v4l/biblio.rst @@ -226,16 +226,6 @@ xvYCC :author: International Electrotechnical Commission (http://www.iec.ch) -.. _adobergb: - -AdobeRGB -======== - - -:title: Adobe© RGB (1998) Color Image Encoding Version 2005-05 - -:author: Adobe Systems Incorporated (http://www.adobe.com) - .. _oprgb: opRGB diff --git a/Documentation/media/uapi/v4l/colorspaces-defs.rst b/Documentation/media/uapi/v4l/colorspaces-defs.rst index 410907fe9415..f24615544792 100644 --- a/Documentation/media/uapi/v4l/colorspaces-defs.rst +++ b/Documentation/media/uapi/v4l/colorspaces-defs.rst @@ -51,8 +51,8 @@ whole range, 0-255, dividing the angular value by 1.41. The enum - See :ref:`col-rec709`. * - ``V4L2_COLORSPACE_SRGB`` - See :ref:`col-srgb`. - * - ``V4L2_COLORSPACE_ADOBERGB`` - - See :ref:`col-adobergb`. + * - ``V4L2_COLORSPACE_OPRGB`` + - See :ref:`col-oprgb`. * - ``V4L2_COLORSPACE_BT2020`` - See :ref:`col-bt2020`. * - ``V4L2_COLORSPACE_DCI_P3`` @@ -90,8 +90,8 @@ whole range, 0-255, dividing the angular value by 1.41. The enum - Use the Rec. 709 transfer function. * - ``V4L2_XFER_FUNC_SRGB`` - Use the sRGB transfer function. - * - ``V4L2_XFER_FUNC_ADOBERGB`` - - Use the AdobeRGB transfer function. + * - ``V4L2_XFER_FUNC_OPRGB`` + - Use the opRGB transfer function. * - ``V4L2_XFER_FUNC_SMPTE240M`` - Use the SMPTE 240M transfer function. * - ``V4L2_XFER_FUNC_NONE`` diff --git a/Documentation/media/uapi/v4l/colorspaces-details.rst b/Documentation/media/uapi/v4l/colorspaces-details.rst index b5d551b9cc8f..09fabf4cd412 100644 --- a/Documentation/media/uapi/v4l/colorspaces-details.rst +++ b/Documentation/media/uapi/v4l/colorspaces-details.rst @@ -290,15 +290,14 @@ Y' is clamped to the range [0…1] and Cb and Cr are clamped to the range 170M/BT.601. The Y'CbCr quantization is limited range. -.. _col-adobergb: +.. _col-oprgb: -Colorspace Adobe RGB (V4L2_COLORSPACE_ADOBERGB) +Colorspace opRGB (V4L2_COLORSPACE_OPRGB) =============================================== -The :ref:`adobergb` standard defines the colorspace used by computer -graphics that use the AdobeRGB colorspace. This is also known as the -:ref:`oprgb` standard. The default transfer function is -``V4L2_XFER_FUNC_ADOBERGB``. The default Y'CbCr encoding is +The :ref:`oprgb` standard defines the colorspace used by computer +graphics that use the opRGB colorspace. The default transfer function is +``V4L2_XFER_FUNC_OPRGB``. The default Y'CbCr encoding is ``V4L2_YCBCR_ENC_601``. The default Y'CbCr quantization is limited range. @@ -312,7 +311,7 @@ The chromaticities of the primary colors and the white reference are: .. tabularcolumns:: |p{4.4cm}|p{4.4cm}|p{8.7cm}| -.. flat-table:: Adobe RGB Chromaticities +.. flat-table:: opRGB Chromaticities :header-rows: 1 :stub-columns: 0 :widths: 1 1 2 diff --git a/Documentation/media/uapi/v4l/func-poll.rst b/Documentation/media/uapi/v4l/func-poll.rst index 360bc6523ae2..967fe8920729 100644 --- a/Documentation/media/uapi/v4l/func-poll.rst +++ b/Documentation/media/uapi/v4l/func-poll.rst @@ -113,4 +113,5 @@ EINTR The call was interrupted by a signal. EINVAL - The ``nfds`` argument is greater than ``OPEN_MAX``. + The ``nfds`` value exceeds the ``RLIMIT_NOFILE`` value. Use + ``getrlimit()`` to obtain this value. diff --git a/Documentation/media/uapi/v4l/meta-formats.rst b/Documentation/media/uapi/v4l/meta-formats.rst index 0c4e1ecf5879..cf971d5ad9ea 100644 --- a/Documentation/media/uapi/v4l/meta-formats.rst +++ b/Documentation/media/uapi/v4l/meta-formats.rst @@ -12,6 +12,7 @@ These formats are used for the :ref:`metadata` interface only. .. toctree:: :maxdepth: 1 + pixfmt-meta-d4xx pixfmt-meta-uvc pixfmt-meta-vsp1-hgo pixfmt-meta-vsp1-hgt diff --git a/Documentation/media/uapi/v4l/pixfmt-compressed.rst b/Documentation/media/uapi/v4l/pixfmt-compressed.rst index d382e7a5c38e..d04b18adac33 100644 --- a/Documentation/media/uapi/v4l/pixfmt-compressed.rst +++ b/Documentation/media/uapi/v4l/pixfmt-compressed.rst @@ -101,4 +101,4 @@ Compressed Formats - 'FWHT' - Video elementary stream using a codec based on the Fast Walsh Hadamard Transform. This codec is implemented by the vicodec ('Virtual Codec') - driver. See the vicodec-codec.h header for more details. + driver. See the codec-fwht.h header for more details. diff --git a/Documentation/media/uapi/v4l/pixfmt-meta-d4xx.rst b/Documentation/media/uapi/v4l/pixfmt-meta-d4xx.rst new file mode 100644 index 000000000000..63bf1a2c9116 --- /dev/null +++ b/Documentation/media/uapi/v4l/pixfmt-meta-d4xx.rst @@ -0,0 +1,210 @@ +.. -*- coding: utf-8; mode: rst -*- + +.. _v4l2-meta-fmt-d4xx: + +******************************* +V4L2_META_FMT_D4XX ('D4XX') +******************************* + +Intel D4xx UVC Cameras Metadata + + +Description +=========== + +Intel D4xx (D435 and other) cameras include per-frame metadata in their UVC +payload headers, following the Microsoft(R) UVC extension proposal [1_]. That +means, that the private D4XX metadata, following the standard UVC header, is +organised in blocks. D4XX cameras implement several standard block types, +proposed by Microsoft, and several proprietary ones. Supported standard metadata +types are MetadataId_CaptureStats (ID 3), MetadataId_CameraExtrinsics (ID 4), +and MetadataId_CameraIntrinsics (ID 5). For their description see [1_]. This +document describes proprietary metadata types, used by D4xx cameras. + +V4L2_META_FMT_D4XX buffers follow the metadata buffer layout of +V4L2_META_FMT_UVC with the only difference, that it also includes proprietary +payload header data. D4xx cameras use bulk transfers and only send one payload +per frame, therefore their headers cannot be larger than 255 bytes. + +Below are proprietary Microsoft style metadata types, used by D4xx cameras, +where all fields are in little endian order: + +.. flat-table:: D4xx metadata + :widths: 1 4 + :header-rows: 1 + :stub-columns: 0 + + * - Field + - Description + * - :cspan:`1` *Depth Control* + * - __u32 ID + - 0x80000000 + * - __u32 Size + - Size in bytes (currently 56) + * - __u32 Version + - Version of this structure. The documentation herein corresponds to + version xxx. The version number will be incremented when new fields are + added. + * - __u32 Flags + - A bitmask of flags: see [2_] below + * - __u32 Gain + - Gain value in internal units, same as the V4L2_CID_GAIN control, used to + capture the frame + * - __u32 Exposure + - Exposure time (in microseconds) used to capture the frame + * - __u32 Laser power + - Power of the laser LED 0-360, used for depth measurement + * - __u32 AE mode + - 0: manual; 1: automatic exposure + * - __u32 Exposure priority + - Exposure priority value: 0 - constant frame rate + * - __u32 AE ROI left + - Left border of the AE Region of Interest (all ROI values are in pixels + and lie between 0 and maximum width or height respectively) + * - __u32 AE ROI right + - Right border of the AE Region of Interest + * - __u32 AE ROI top + - Top border of the AE Region of Interest + * - __u32 AE ROI bottom + - Bottom border of the AE Region of Interest + * - __u32 Preset + - Preset selector value, default: 0, unless changed by the user + * - __u32 Laser mode + - 0: off, 1: on + * - :cspan:`1` *Capture Timing* + * - __u32 ID + - 0x80000001 + * - __u32 Size + - Size in bytes (currently 40) + * - __u32 Version + - Version of this structure. The documentation herein corresponds to + version xxx. The version number will be incremented when new fields are + added. + * - __u32 Flags + - A bitmask of flags: see [3_] below + * - __u32 Frame counter + - Monotonically increasing counter + * - __u32 Optical time + - Time in microseconds from the beginning of a frame till its middle + * - __u32 Readout time + - Time, used to read out a frame in microseconds + * - __u32 Exposure time + - Frame exposure time in microseconds + * - __u32 Frame interval + - In microseconds = 1000000 / framerate + * - __u32 Pipe latency + - Time in microseconds from start of frame to data in USB buffer + * - :cspan:`1` *Configuration* + * - __u32 ID + - 0x80000002 + * - __u32 Size + - Size in bytes (currently 40) + * - __u32 Version + - Version of this structure. The documentation herein corresponds to + version xxx. The version number will be incremented when new fields are + added. + * - __u32 Flags + - A bitmask of flags: see [4_] below + * - __u8 Hardware type + - Camera hardware version [5_] + * - __u8 SKU ID + - Camera hardware configuration [6_] + * - __u32 Cookie + - Internal synchronisation + * - __u16 Format + - Image format code [7_] + * - __u16 Width + - Width in pixels + * - __u16 Height + - Height in pixels + * - __u16 Framerate + - Requested frame rate per second + * - __u16 Trigger + - Byte 0: bit 0: depth and RGB are synchronised, bit 1: external trigger + +.. _1: + +[1] https://docs.microsoft.com/en-us/windows-hardware/drivers/stream/uvc-extensions-1-5 + +.. _2: + +[2] Depth Control flags specify which fields are valid: :: + + 0x00000001 Gain + 0x00000002 Exposure + 0x00000004 Laser power + 0x00000008 AE mode + 0x00000010 Exposure priority + 0x00000020 AE ROI + 0x00000040 Preset + +.. _3: + +[3] Capture Timing flags specify which fields are valid: :: + + 0x00000001 Frame counter + 0x00000002 Optical time + 0x00000004 Readout time + 0x00000008 Exposure time + 0x00000010 Frame interval + 0x00000020 Pipe latency + +.. _4: + +[4] Configuration flags specify which fields are valid: :: + + 0x00000001 Hardware type + 0x00000002 SKU ID + 0x00000004 Cookie + 0x00000008 Format + 0x00000010 Width + 0x00000020 Height + 0x00000040 Framerate + 0x00000080 Trigger + 0x00000100 Cal count + +.. _5: + +[5] Camera model: :: + + 0 DS5 + 1 IVCAM2 + +.. _6: + +[6] 8-bit camera hardware configuration bitfield: :: + + [1:0] depthCamera + 00: no depth + 01: standard depth + 10: wide depth + 11: reserved + [2] depthIsActive - has a laser projector + [3] RGB presence + [4] Inertial Measurement Unit (IMU) presence + [5] projectorType + 0: HPTG + 1: Princeton + [6] 0: a projector, 1: an LED + [7] reserved + +.. _7: + +[7] Image format codes per video streaming interface: + +Depth: :: + + 1 Z16 + 2 Z + +Left sensor: :: + + 1 Y8 + 2 UYVY + 3 R8L8 + 4 Calibration + 5 W10 + +Fish Eye sensor: :: + + 1 RAW8 diff --git a/Documentation/media/uapi/v4l/vidioc-cropcap.rst b/Documentation/media/uapi/v4l/vidioc-cropcap.rst index a65dbec6b20b..0a7b8287fd38 100644 --- a/Documentation/media/uapi/v4l/vidioc-cropcap.rst +++ b/Documentation/media/uapi/v4l/vidioc-cropcap.rst @@ -58,7 +58,7 @@ overlay devices. - Type of the data stream, set by the application. Only these types are valid here: ``V4L2_BUF_TYPE_VIDEO_CAPTURE``, ``V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE``, ``V4L2_BUF_TYPE_VIDEO_OUTPUT``, ``V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE`` and - ``V4L2_BUF_TYPE_VIDEO_OVERLAY``. See :c:type:`v4l2_buf_type` and the note above. + ``V4L2_BUF_TYPE_VIDEO_OVERLAY``. See :c:type:`v4l2_buf_type` and the note below. * - struct :ref:`v4l2_rect <v4l2-rect-crop>` - ``bounds`` - Defines the window within capturing or output is possible, this diff --git a/Documentation/media/uapi/v4l/vidioc-dqevent.rst b/Documentation/media/uapi/v4l/vidioc-dqevent.rst index cb3565f36793..04416b6943c0 100644 --- a/Documentation/media/uapi/v4l/vidioc-dqevent.rst +++ b/Documentation/media/uapi/v4l/vidioc-dqevent.rst @@ -379,7 +379,17 @@ call. - 0x0001 - This event gets triggered when a resolution change is detected at an input. This can come from an input connector or from a video - decoder. + decoder. Applications will have to query the new resolution (if + any, the signal may also have been lost). + + *Important*: even if the new video timings appear identical to the old + ones, receiving this event indicates that there was an issue with the + video signal and you must stop and restart streaming + (:ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>` + followed by :ref:`VIDIOC_STREAMON <VIDIOC_STREAMON>`). The reason is + that many devices are not able to recover from a temporary loss of + signal and so restarting streaming I/O is required in order for the + hardware to synchronize to the video signal. Return Value diff --git a/Documentation/media/uapi/v4l/vidioc-g-crop.rst b/Documentation/media/uapi/v4l/vidioc-g-crop.rst index a6ed43ba9ca3..b95ba6743cbd 100644 --- a/Documentation/media/uapi/v4l/vidioc-g-crop.rst +++ b/Documentation/media/uapi/v4l/vidioc-g-crop.rst @@ -84,7 +84,7 @@ When cropping is not supported then no parameters are changed and - Type of the data stream, set by the application. Only these types are valid here: ``V4L2_BUF_TYPE_VIDEO_CAPTURE``, ``V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE``, ``V4L2_BUF_TYPE_VIDEO_OUTPUT``, ``V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE`` and - ``V4L2_BUF_TYPE_VIDEO_OVERLAY``. See :c:type:`v4l2_buf_type` and the note above. + ``V4L2_BUF_TYPE_VIDEO_OVERLAY``. See :c:type:`v4l2_buf_type` and the note below. * - struct :c:type:`v4l2_rect` - ``c`` - Cropping rectangle. The same co-ordinate system as for struct diff --git a/Documentation/media/uapi/v4l/vidioc-g-dv-timings.rst b/Documentation/media/uapi/v4l/vidioc-g-dv-timings.rst index 1a034e825161..35cba2c8d459 100644 --- a/Documentation/media/uapi/v4l/vidioc-g-dv-timings.rst +++ b/Documentation/media/uapi/v4l/vidioc-g-dv-timings.rst @@ -257,14 +257,19 @@ EBUSY will also be cleared. This is a read-only flag, applications must not set this. * - ``V4L2_DV_FL_REDUCED_FPS`` - - CEA-861 specific: only valid for video transmitters, the flag is - cleared by receivers. It is also only valid for formats with the - ``V4L2_DV_FL_CAN_REDUCE_FPS`` flag set, for other formats the - flag will be cleared by the driver. If the application sets this - flag, then the pixelclock used to set up the transmitter is - divided by 1.001 to make it compatible with NTSC framerates. If - the transmitter can't generate such frequencies, then the flag - will also be cleared. + - CEA-861 specific: only valid for video transmitters or video + receivers that have the ``V4L2_DV_FL_CAN_DETECT_REDUCED_FPS`` + set. This flag is cleared otherwise. It is also only valid for + formats with the ``V4L2_DV_FL_CAN_REDUCE_FPS`` flag set, for other + formats the flag will be cleared by the driver. + + If the application sets this flag for a transmitter, then the + pixelclock used to set up the transmitter is divided by 1.001 to + make it compatible with NTSC framerates. If the transmitter can't + generate such frequencies, then the flag will be cleared. + + If a video receiver detects that the format uses a reduced framerate, + then it will set this flag to signal this to the application. * - ``V4L2_DV_FL_HALF_LINE`` - Specific to interlaced formats: if set, then the vertical backporch of field 1 (aka the odd field) is really one half-line @@ -294,3 +299,9 @@ EBUSY - If set, then the hdmi_vic field is valid and contains the Video Identification Code as per the HDMI standard (HDMI Vendor Specific InfoFrame). + * - ``V4L2_DV_FL_CAN_DETECT_REDUCED_FPS`` + - CEA-861 specific: only valid for video receivers, the flag is + cleared by transmitters. + If set, then the hardware can detect the difference between + regular framerates and framerates reduced by 1000/1001. E.g.: + 60 vs 59.94 Hz, 30 vs 29.97 Hz or 24 vs 23.976 Hz. diff --git a/Documentation/media/videodev2.h.rst.exceptions b/Documentation/media/videodev2.h.rst.exceptions index ca9f0edc579e..1f4340dd9a37 100644 --- a/Documentation/media/videodev2.h.rst.exceptions +++ b/Documentation/media/videodev2.h.rst.exceptions @@ -56,7 +56,8 @@ replace symbol V4L2_MEMORY_USERPTR :c:type:`v4l2_memory` # Documented enum v4l2_colorspace replace symbol V4L2_COLORSPACE_470_SYSTEM_BG :c:type:`v4l2_colorspace` replace symbol V4L2_COLORSPACE_470_SYSTEM_M :c:type:`v4l2_colorspace` -replace symbol V4L2_COLORSPACE_ADOBERGB :c:type:`v4l2_colorspace` +replace symbol V4L2_COLORSPACE_OPRGB :c:type:`v4l2_colorspace` +replace define V4L2_COLORSPACE_ADOBERGB :c:type:`v4l2_colorspace` replace symbol V4L2_COLORSPACE_BT2020 :c:type:`v4l2_colorspace` replace symbol V4L2_COLORSPACE_DCI_P3 :c:type:`v4l2_colorspace` replace symbol V4L2_COLORSPACE_DEFAULT :c:type:`v4l2_colorspace` @@ -69,7 +70,8 @@ replace symbol V4L2_COLORSPACE_SRGB :c:type:`v4l2_colorspace` # Documented enum v4l2_xfer_func replace symbol V4L2_XFER_FUNC_709 :c:type:`v4l2_xfer_func` -replace symbol V4L2_XFER_FUNC_ADOBERGB :c:type:`v4l2_xfer_func` +replace symbol V4L2_XFER_FUNC_OPRGB :c:type:`v4l2_xfer_func` +replace define V4L2_XFER_FUNC_ADOBERGB :c:type:`v4l2_xfer_func` replace symbol V4L2_XFER_FUNC_DCI_P3 :c:type:`v4l2_xfer_func` replace symbol V4L2_XFER_FUNC_DEFAULT :c:type:`v4l2_xfer_func` replace symbol V4L2_XFER_FUNC_NONE :c:type:`v4l2_xfer_func` @@ -278,6 +280,7 @@ replace define V4L2_DV_BT_STD_SDI dv-bt-standards replace define V4L2_DV_FL_REDUCED_BLANKING dv-bt-standards replace define V4L2_DV_FL_CAN_REDUCE_FPS dv-bt-standards +replace define V4L2_DV_FL_CAN_DETECT_REDUCED_FPS dv-bt-standards replace define V4L2_DV_FL_REDUCED_FPS dv-bt-standards replace define V4L2_DV_FL_HALF_LINE dv-bt-standards replace define V4L2_DV_FL_IS_CE_VIDEO dv-bt-standards diff --git a/MAINTAINERS b/MAINTAINERS index c6c9cc1019ad..ea1648fdcfb4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4546,13 +4546,15 @@ L: linux-media@vger.kernel.org T: git git://linuxtv.org/media_tree.git S: Maintained F: drivers/media/i2c/dw9714.c +F: Documentation/devicetree/bindings/media/i2c/dongwoon,dw9714.txt DONGWOON DW9807 LENS VOICE COIL DRIVER M: Sakari Ailus <sakari.ailus@linux.intel.com> L: linux-media@vger.kernel.org T: git git://linuxtv.org/media_tree.git S: Maintained -F: drivers/media/i2c/dw9807.c +F: drivers/media/i2c/dw9807-vcm.c +F: Documentation/devicetree/bindings/media/i2c/dongwoon,dw9807-vcm.txt DOUBLETALK DRIVER M: "James R. Van Zandt" <jrv@vanzandt.mv.com> @@ -9086,11 +9088,10 @@ F: drivers/media/dvb-frontends/cxd2880/* F: drivers/media/spi/cxd2880* MEDIA DRIVERS FOR DIGITAL DEVICES PCIE DEVICES -M: Daniel Scheller <d.scheller.oss@gmail.com> L: linux-media@vger.kernel.org W: https://linuxtv.org T: git git://linuxtv.org/media_tree.git -S: Maintained +S: Orphan F: drivers/media/pci/ddbridge/* MEDIA DRIVERS FOR FREESCALE IMX @@ -9105,6 +9106,13 @@ F: drivers/staging/media/imx/ F: include/linux/imx-media.h F: include/media/imx.h +MEDIA DRIVER FOR FREESCALE IMX PXP +M: Philipp Zabel <p.zabel@pengutronix.de> +L: linux-media@vger.kernel.org +T: git git://linuxtv.org/media_tree.git +S: Maintained +F: drivers/media/platform/imx-pxp.[ch] + MEDIA DRIVERS FOR HELENE M: Abylay Ospan <aospan@netup.ru> L: linux-media@vger.kernel.org @@ -9135,11 +9143,10 @@ S: Supported F: drivers/media/dvb-frontends/lnbh25* MEDIA DRIVERS FOR MXL5XX TUNER DEMODULATORS -M: Daniel Scheller <d.scheller.oss@gmail.com> L: linux-media@vger.kernel.org W: https://linuxtv.org T: git git://linuxtv.org/media_tree.git -S: Maintained +S: Orphan F: drivers/media/dvb-frontends/mxl5xx* MEDIA DRIVERS FOR NETUP PCI UNIVERSAL DVB devices @@ -9182,7 +9189,7 @@ F: drivers/media/platform/rcar-fcp.c F: include/media/rcar-fcp.h MEDIA DRIVERS FOR RENESAS - FDP1 -M: Kieran Bingham <kieran@bingham.xyz> +M: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com> L: linux-media@vger.kernel.org L: linux-renesas-soc@vger.kernel.org T: git git://linuxtv.org/media_tree.git @@ -9202,6 +9209,7 @@ F: drivers/media/platform/rcar-vin/ MEDIA DRIVERS FOR RENESAS - VSP1 M: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +M: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com> L: linux-media@vger.kernel.org L: linux-renesas-soc@vger.kernel.org T: git git://linuxtv.org/media_tree.git @@ -9210,19 +9218,17 @@ F: Documentation/devicetree/bindings/media/renesas,vsp1.txt F: drivers/media/platform/vsp1/ MEDIA DRIVERS FOR ST STV0910 DEMODULATOR ICs -M: Daniel Scheller <d.scheller.oss@gmail.com> L: linux-media@vger.kernel.org W: https://linuxtv.org T: git git://linuxtv.org/media_tree.git -S: Maintained +S: Orphan F: drivers/media/dvb-frontends/stv0910* MEDIA DRIVERS FOR ST STV6111 TUNER ICs -M: Daniel Scheller <d.scheller.oss@gmail.com> L: linux-media@vger.kernel.org W: https://linuxtv.org T: git git://linuxtv.org/media_tree.git -S: Maintained +S: Orphan F: drivers/media/dvb-frontends/stv6111* MEDIA DRIVERS FOR STM32 - DCMI @@ -13719,6 +13725,20 @@ S: Maintained F: drivers/media/i2c/imx274.c F: Documentation/devicetree/bindings/media/i2c/imx274.txt +SONY IMX319 SENSOR DRIVER +M: Bingbu Cao <bingbu.cao@intel.com> +L: linux-media@vger.kernel.org +T: git git://linuxtv.org/media_tree.git +S: Maintained +F: drivers/media/i2c/imx319.c + +SONY IMX355 SENSOR DRIVER +M: Tianshu Qiu <tian.shu.qiu@intel.com> +L: linux-media@vger.kernel.org +T: git git://linuxtv.org/media_tree.git +S: Maintained +F: drivers/media/i2c/imx355.c + SONY MEMORYSTICK CARD SUPPORT M: Alex Dubov <oakad@yahoo.com> W: http://tifmxx.berlios.de/ @@ -14038,7 +14058,7 @@ F: sound/soc/sti/ STI CEC DRIVER M: Benjamin Gaignard <benjamin.gaignard@linaro.org> S: Maintained -F: drivers/staging/media/st-cec/ +F: drivers/media/platform/sti/cec/ F: Documentation/devicetree/bindings/media/stih-cec.txt STK1160 USB VIDEO CAPTURE DRIVER @@ -15697,7 +15717,7 @@ M: Marek Szyprowski <m.szyprowski@samsung.com> M: Kyungmin Park <kyungmin.park@samsung.com> L: linux-media@vger.kernel.org S: Maintained -F: drivers/media/v4l2-core/videobuf2-* +F: drivers/media/common/videobuf2/* F: include/media/videobuf2-* VIMC VIRTUAL MEDIA CONTROLLER DRIVER diff --git a/arch/arm/boot/dts/gr-peach-audiocamerashield.dtsi b/arch/arm/boot/dts/gr-peach-audiocamerashield.dtsi index e31a9e3c18a2..8d77579807ec 100644 --- a/arch/arm/boot/dts/gr-peach-audiocamerashield.dtsi +++ b/arch/arm/boot/dts/gr-peach-audiocamerashield.dtsi @@ -69,10 +69,6 @@ port { ceu_in: endpoint { - hsync-active = <1>; - vsync-active = <1>; - bus-width = <8>; - pclk-sample = <1>; remote-endpoint = <&mt9v111_out>; }; }; diff --git a/drivers/gpu/ipu-v3/ipu-csi.c b/drivers/gpu/ipu-v3/ipu-csi.c index 954eefe144e2..aa0e30a2ba18 100644 --- a/drivers/gpu/ipu-v3/ipu-csi.c +++ b/drivers/gpu/ipu-v3/ipu-csi.c @@ -232,7 +232,7 @@ static int mbus_code_to_bus_cfg(struct ipu_csi_bus_config *cfg, u32 mbus_code, case MEDIA_BUS_FMT_BGR565_2X8_LE: case MEDIA_BUS_FMT_RGB565_2X8_BE: case MEDIA_BUS_FMT_RGB565_2X8_LE: - if (mbus_type == V4L2_MBUS_CSI2) + if (mbus_type == V4L2_MBUS_CSI2_DPHY) cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_RGB565; else cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER; @@ -359,7 +359,7 @@ static int fill_csi_bus_cfg(struct ipu_csi_bus_config *csicfg, else csicfg->clk_mode = IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE; break; - case V4L2_MBUS_CSI2: + case V4L2_MBUS_CSI2_DPHY: /* * MIPI CSI-2 requires non gated clock mode, all other * parameters are not applicable for MIPI CSI-2 bus. @@ -611,7 +611,7 @@ int ipu_csi_set_mipi_datatype(struct ipu_csi *csi, u32 vc, if (vc > 3) return -EINVAL; - ret = mbus_code_to_bus_cfg(&cfg, mbus_fmt->code, V4L2_MBUS_CSI2); + ret = mbus_code_to_bus_cfg(&cfg, mbus_fmt->code, V4L2_MBUS_CSI2_DPHY); if (ret < 0) return ret; diff --git a/drivers/hid/hid-picolcd_cir.c b/drivers/hid/hid-picolcd_cir.c index 32747b7f917e..bf6f29ca3315 100644 --- a/drivers/hid/hid-picolcd_cir.c +++ b/drivers/hid/hid-picolcd_cir.c @@ -45,7 +45,7 @@ int picolcd_raw_cir(struct picolcd_data *data, { unsigned long flags; int i, w, sz; - DEFINE_IR_RAW_EVENT(rawir); + struct ir_raw_event rawir = {}; /* ignore if rc_dev is NULL or status is shunned */ spin_lock_irqsave(&data->lock, flags); @@ -67,7 +67,6 @@ int picolcd_raw_cir(struct picolcd_data *data, */ sz = size > 0 ? min((int)raw_data[0], size-1) : 0; for (i = 0; i+1 < sz; i += 2) { - init_ir_raw_event(&rawir); w = (raw_data[i] << 8) | (raw_data[i+1]); rawir.pulse = !!(w & 0x8000); rawir.duration = US_TO_NS(rawir.pulse ? (65536 - w) : w); diff --git a/drivers/media/cec/Makefile b/drivers/media/cec/Makefile index 29a2ab9e77c5..ad8677d8c896 100644 --- a/drivers/media/cec/Makefile +++ b/drivers/media/cec/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -cec-objs := cec-core.o cec-adap.o cec-api.o cec-edid.o +cec-objs := cec-core.o cec-adap.o cec-api.o ifeq ($(CONFIG_CEC_NOTIFIER),y) cec-objs += cec-notifier.o diff --git a/drivers/media/cec/cec-adap.c b/drivers/media/cec/cec-adap.c index 030b2602faf0..31d1f4ab915e 100644 --- a/drivers/media/cec/cec-adap.c +++ b/drivers/media/cec/cec-adap.c @@ -62,6 +62,19 @@ static unsigned int cec_log_addr2dev(const struct cec_adapter *adap, u8 log_addr return adap->log_addrs.primary_device_type[i < 0 ? 0 : i]; } +u16 cec_get_edid_phys_addr(const u8 *edid, unsigned int size, + unsigned int *offset) +{ + unsigned int loc = cec_get_edid_spa_location(edid, size); + + if (offset) + *offset = loc; + if (loc == 0) + return CEC_PHYS_ADDR_INVALID; + return (edid[loc] << 8) | edid[loc + 1]; +} +EXPORT_SYMBOL_GPL(cec_get_edid_phys_addr); + /* * Queue a new event for this filehandle. If ts == 0, then set it * to the current time. @@ -341,7 +354,7 @@ static void cec_data_completed(struct cec_data *data) * * This function is called with adap->lock held. */ -static void cec_data_cancel(struct cec_data *data) +static void cec_data_cancel(struct cec_data *data, u8 tx_status) { /* * It's either the current transmit, or it is a pending @@ -356,13 +369,11 @@ static void cec_data_cancel(struct cec_data *data) } if (data->msg.tx_status & CEC_TX_STATUS_OK) { - /* Mark the canceled RX as a timeout */ data->msg.rx_ts = ktime_get_ns(); - data->msg.rx_status = CEC_RX_STATUS_TIMEOUT; + data->msg.rx_status = CEC_RX_STATUS_ABORTED; } else { - /* Mark the canceled TX as an error */ data->msg.tx_ts = ktime_get_ns(); - data->msg.tx_status |= CEC_TX_STATUS_ERROR | + data->msg.tx_status |= tx_status | CEC_TX_STATUS_MAX_RETRIES; data->msg.tx_error_cnt++; data->attempts = 0; @@ -390,15 +401,15 @@ static void cec_flush(struct cec_adapter *adap) while (!list_empty(&adap->transmit_queue)) { data = list_first_entry(&adap->transmit_queue, struct cec_data, list); - cec_data_cancel(data); + cec_data_cancel(data, CEC_TX_STATUS_ABORTED); } if (adap->transmitting) - cec_data_cancel(adap->transmitting); + cec_data_cancel(adap->transmitting, CEC_TX_STATUS_ABORTED); /* Cancel the pending timeout work. */ list_for_each_entry_safe(data, n, &adap->wait_queue, list) { if (cancel_delayed_work(&data->work)) - cec_data_cancel(data); + cec_data_cancel(data, CEC_TX_STATUS_OK); /* * If cancel_delayed_work returned false, then * the cec_wait_timeout function is running, @@ -474,12 +485,13 @@ int cec_thread_func(void *_adap) * so much traffic on the bus that the adapter was * unable to transmit for CEC_XFER_TIMEOUT_MS (2.1s). */ - dprintk(1, "%s: message %*ph timed out\n", __func__, + pr_warn("cec-%s: message %*ph timed out\n", adap->name, adap->transmitting->msg.len, adap->transmitting->msg.msg); adap->tx_timeouts++; /* Just give up on this. */ - cec_data_cancel(adap->transmitting); + cec_data_cancel(adap->transmitting, + CEC_TX_STATUS_TIMEOUT); goto unlock; } @@ -514,9 +526,11 @@ int cec_thread_func(void *_adap) if (data->attempts) { /* should be >= 3 data bit periods for a retry */ signal_free_time = CEC_SIGNAL_FREE_TIME_RETRY; - } else if (data->new_initiator) { + } else if (adap->last_initiator != + cec_msg_initiator(&data->msg)) { /* should be >= 5 data bit periods for new initiator */ signal_free_time = CEC_SIGNAL_FREE_TIME_NEW_INITIATOR; + adap->last_initiator = cec_msg_initiator(&data->msg); } else { /* * should be >= 7 data bit periods for sending another @@ -530,7 +544,7 @@ int cec_thread_func(void *_adap) /* Tell the adapter to transmit, cancel on error */ if (adap->ops->adap_transmit(adap, data->attempts, signal_free_time, &data->msg)) - cec_data_cancel(data); + cec_data_cancel(data, CEC_TX_STATUS_ABORTED); unlock: mutex_unlock(&adap->lock); @@ -701,9 +715,6 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg, struct cec_fh *fh, bool block) { struct cec_data *data; - u8 last_initiator = 0xff; - unsigned int timeout; - int res = 0; msg->rx_ts = 0; msg->tx_ts = 0; @@ -813,23 +824,6 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg, data->adap = adap; data->blocking = block; - /* - * Determine if this message follows a message from the same - * initiator. Needed to determine the free signal time later on. - */ - if (msg->len > 1) { - if (!(list_empty(&adap->transmit_queue))) { - const struct cec_data *last; - - last = list_last_entry(&adap->transmit_queue, - const struct cec_data, list); - last_initiator = cec_msg_initiator(&last->msg); - } else if (adap->transmitting) { - last_initiator = - cec_msg_initiator(&adap->transmitting->msg); - } - } - data->new_initiator = last_initiator != cec_msg_initiator(msg); init_completion(&data->c); INIT_DELAYED_WORK(&data->work, cec_wait_timeout); @@ -846,47 +840,22 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg, return 0; /* - * If we don't get a completion before this time something is really - * wrong and we time out. - */ - timeout = CEC_XFER_TIMEOUT_MS; - /* Add the requested timeout if we have to wait for a reply as well */ - if (msg->timeout) - timeout += msg->timeout; - - /* * Release the lock and wait, retake the lock afterwards. */ mutex_unlock(&adap->lock); - res = wait_for_completion_killable_timeout(&data->c, - msecs_to_jiffies(timeout)); + wait_for_completion_killable(&data->c); + if (!data->completed) + cancel_delayed_work_sync(&data->work); mutex_lock(&adap->lock); - if (data->completed) { - /* The transmit completed (possibly with an error) */ - *msg = data->msg; - kfree(data); - return 0; - } - /* - * The wait for completion timed out or was interrupted, so mark this - * as non-blocking and disconnect from the filehandle since it is - * still 'in flight'. When it finally completes it will just drop the - * result silently. - */ - data->blocking = false; - if (data->fh) - list_del(&data->xfer_list); - data->fh = NULL; + /* Cancel the transmit if it was interrupted */ + if (!data->completed) + cec_data_cancel(data, CEC_TX_STATUS_ABORTED); - if (res == 0) { /* timed out */ - /* Check if the reply or the transmit failed */ - if (msg->timeout && (msg->tx_status & CEC_TX_STATUS_OK)) - msg->rx_status = CEC_RX_STATUS_TIMEOUT; - else - msg->tx_status = CEC_TX_STATUS_MAX_RETRIES; - } - return res > 0 ? 0 : res; + /* The transmit completed (possibly with an error) */ + *msg = data->msg; + kfree(data); + return 0; } /* Helper function to be used by drivers and this framework. */ @@ -1044,6 +1013,8 @@ void cec_received_msg_ts(struct cec_adapter *adap, mutex_lock(&adap->lock); dprintk(2, "%s: %*ph\n", __func__, msg->len, msg->msg); + adap->last_initiator = 0xff; + /* Check if this message was for us (directed or broadcast). */ if (!cec_msg_is_broadcast(msg)) valid_la = cec_has_log_addr(adap, msg_dest); @@ -1506,6 +1477,8 @@ void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block) } mutex_lock(&adap->devnode.lock); + adap->last_initiator = 0xff; + if ((adap->needs_hpd || list_empty(&adap->devnode.fhs)) && adap->ops->adap_enable(adap, true)) { mutex_unlock(&adap->devnode.lock); diff --git a/drivers/media/cec/cec-api.c b/drivers/media/cec/cec-api.c index b6536bbad530..391b6fd483e1 100644 --- a/drivers/media/cec/cec-api.c +++ b/drivers/media/cec/cec-api.c @@ -77,9 +77,9 @@ static long cec_adap_g_caps(struct cec_adapter *adap, { struct cec_caps caps = {}; - strlcpy(caps.driver, adap->devnode.dev.parent->driver->name, + strscpy(caps.driver, adap->devnode.dev.parent->driver->name, sizeof(caps.driver)); - strlcpy(caps.name, adap->name, sizeof(caps.name)); + strscpy(caps.name, adap->name, sizeof(caps.name)); caps.available_log_addrs = adap->available_log_addrs; caps.capabilities = adap->capabilities; caps.version = LINUX_VERSION_CODE; @@ -101,6 +101,23 @@ static long cec_adap_g_phys_addr(struct cec_adapter *adap, return 0; } +static int cec_validate_phys_addr(u16 phys_addr) +{ + int i; + + if (phys_addr == CEC_PHYS_ADDR_INVALID) + return 0; + for (i = 0; i < 16; i += 4) + if (phys_addr & (0xf << i)) + break; + if (i == 16) + return 0; + for (i += 4; i < 16; i += 4) + if ((phys_addr & (0xf << i)) == 0) + return -EINVAL; + return 0; +} + static long cec_adap_s_phys_addr(struct cec_adapter *adap, struct cec_fh *fh, bool block, __u16 __user *parg) { @@ -112,7 +129,7 @@ static long cec_adap_s_phys_addr(struct cec_adapter *adap, struct cec_fh *fh, if (copy_from_user(&phys_addr, parg, sizeof(phys_addr))) return -EFAULT; - err = cec_phys_addr_validate(phys_addr, NULL, NULL); + err = cec_validate_phys_addr(phys_addr); if (err) return err; mutex_lock(&adap->lock); @@ -665,6 +682,7 @@ const struct file_operations cec_devnode_fops = { .owner = THIS_MODULE, .open = cec_open, .unlocked_ioctl = cec_ioctl, + .compat_ioctl = cec_ioctl, .release = cec_release, .poll = cec_poll, .llseek = no_llseek, diff --git a/drivers/media/cec/cec-core.c b/drivers/media/cec/cec-core.c index b278ab90b387..e4edc930d4ed 100644 --- a/drivers/media/cec/cec-core.c +++ b/drivers/media/cec/cec-core.c @@ -264,7 +264,7 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, adap = kzalloc(sizeof(*adap), GFP_KERNEL); if (!adap) return ERR_PTR(-ENOMEM); - strlcpy(adap->name, name, sizeof(adap->name)); + strscpy(adap->name, name, sizeof(adap->name)); adap->phys_addr = CEC_PHYS_ADDR_INVALID; adap->cec_pin_is_high = true; adap->log_addrs.cec_version = CEC_OP_CEC_VERSION_2_0; @@ -307,12 +307,10 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, return ERR_PTR(-ENOMEM); } - snprintf(adap->device_name, sizeof(adap->device_name), - "RC for %s", name); snprintf(adap->input_phys, sizeof(adap->input_phys), - "%s/input0", name); + "%s/input0", adap->name); - adap->rc->device_name = adap->device_name; + adap->rc->device_name = adap->name; adap->rc->input_phys = adap->input_phys; adap->rc->input_id.bustype = BUS_CEC; adap->rc->input_id.vendor = 0; diff --git a/drivers/media/cec/cec-edid.c b/drivers/media/cec/cec-edid.c deleted file mode 100644 index ec72ac1c0b91..000000000000 --- a/drivers/media/cec/cec-edid.c +++ /dev/null @@ -1,155 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * cec-edid - HDMI Consumer Electronics Control EDID & CEC helper functions - * - * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <media/cec.h> - -/* - * This EDID is expected to be a CEA-861 compliant, which means that there are - * at least two blocks and one or more of the extensions blocks are CEA-861 - * blocks. - * - * The returned location is guaranteed to be < size - 1. - */ -static unsigned int cec_get_edid_spa_location(const u8 *edid, unsigned int size) -{ - unsigned int blocks = size / 128; - unsigned int block; - u8 d; - - /* Sanity check: at least 2 blocks and a multiple of the block size */ - if (blocks < 2 || size % 128) - return 0; - - /* - * If there are fewer extension blocks than the size, then update - * 'blocks'. It is allowed to have more extension blocks than the size, - * since some hardware can only read e.g. 256 bytes of the EDID, even - * though more blocks are present. The first CEA-861 extension block - * should normally be in block 1 anyway. - */ - if (edid[0x7e] + 1 < blocks) - blocks = edid[0x7e] + 1; - - for (block = 1; block < blocks; block++) { - unsigned int offset = block * 128; - - /* Skip any non-CEA-861 extension blocks */ - if (edid[offset] != 0x02 || edid[offset + 1] != 0x03) - continue; - - /* search Vendor Specific Data Block (tag 3) */ - d = edid[offset + 2] & 0x7f; - /* Check if there are Data Blocks */ - if (d <= 4) - continue; - if (d > 4) { - unsigned int i = offset + 4; - unsigned int end = offset + d; - - /* Note: 'end' is always < 'size' */ - do { - u8 tag = edid[i] >> 5; - u8 len = edid[i] & 0x1f; - - if (tag == 3 && len >= 5 && i + len <= end && - edid[i + 1] == 0x03 && - edid[i + 2] == 0x0c && - edid[i + 3] == 0x00) - return i + 4; - i += len + 1; - } while (i < end); - } - } - return 0; -} - -u16 cec_get_edid_phys_addr(const u8 *edid, unsigned int size, - unsigned int *offset) -{ - unsigned int loc = cec_get_edid_spa_location(edid, size); - - if (offset) - *offset = loc; - if (loc == 0) - return CEC_PHYS_ADDR_INVALID; - return (edid[loc] << 8) | edid[loc + 1]; -} -EXPORT_SYMBOL_GPL(cec_get_edid_phys_addr); - -void cec_set_edid_phys_addr(u8 *edid, unsigned int size, u16 phys_addr) -{ - unsigned int loc = cec_get_edid_spa_location(edid, size); - u8 sum = 0; - unsigned int i; - - if (loc == 0) - return; - edid[loc] = phys_addr >> 8; - edid[loc + 1] = phys_addr & 0xff; - loc &= ~0x7f; - - /* update the checksum */ - for (i = loc; i < loc + 127; i++) - sum += edid[i]; - edid[i] = 256 - sum; -} -EXPORT_SYMBOL_GPL(cec_set_edid_phys_addr); - -u16 cec_phys_addr_for_input(u16 phys_addr, u8 input) -{ - /* Check if input is sane */ - if (WARN_ON(input == 0 || input > 0xf)) - return CEC_PHYS_ADDR_INVALID; - - if (phys_addr == 0) - return input << 12; - - if ((phys_addr & 0x0fff) == 0) - return phys_addr | (input << 8); - - if ((phys_addr & 0x00ff) == 0) - return phys_addr | (input << 4); - - if ((phys_addr & 0x000f) == 0) - return phys_addr | input; - - /* - * All nibbles are used so no valid physical addresses can be assigned - * to the input. - */ - return CEC_PHYS_ADDR_INVALID; -} -EXPORT_SYMBOL_GPL(cec_phys_addr_for_input); - -int cec_phys_addr_validate(u16 phys_addr, u16 *parent, u16 *port) -{ - int i; - - if (parent) - *parent = phys_addr; - if (port) - *port = 0; - if (phys_addr == CEC_PHYS_ADDR_INVALID) - return 0; - for (i = 0; i < 16; i += 4) - if (phys_addr & (0xf << i)) - break; - if (i == 16) - return 0; - if (parent) - *parent = phys_addr & (0xfff0 << i); - if (port) - *port = (phys_addr >> i) & 0xf; - for (i += 4; i < 16; i += 4) - if ((phys_addr & (0xf << i)) == 0) - return -EINVAL; - return 0; -} -EXPORT_SYMBOL_GPL(cec_phys_addr_validate); diff --git a/drivers/media/cec/cec-pin.c b/drivers/media/cec/cec-pin.c index 6e311424f0dc..635db8e70ead 100644 --- a/drivers/media/cec/cec-pin.c +++ b/drivers/media/cec/cec-pin.c @@ -935,6 +935,17 @@ static enum hrtimer_restart cec_pin_timer(struct hrtimer *timer) /* Start bit, switch to receive state */ pin->ts = ts; pin->state = CEC_ST_RX_START_BIT_LOW; + /* + * If a transmit is pending, then that transmit should + * use a signal free time of no more than + * CEC_SIGNAL_FREE_TIME_NEW_INITIATOR since it will + * have a new initiator due to the receive that is now + * starting. + */ + if (pin->tx_msg.len && pin->tx_signal_free_time > + CEC_SIGNAL_FREE_TIME_NEW_INITIATOR) + pin->tx_signal_free_time = + CEC_SIGNAL_FREE_TIME_NEW_INITIATOR; break; } if (ktime_to_ns(pin->ts) == 0) @@ -1157,6 +1168,15 @@ static int cec_pin_adap_transmit(struct cec_adapter *adap, u8 attempts, { struct cec_pin *pin = adap->pin; + /* + * If a receive is in progress, then this transmit should use + * a signal free time of max CEC_SIGNAL_FREE_TIME_NEW_INITIATOR + * since when it starts transmitting it will have a new initiator. + */ + if (pin->state != CEC_ST_IDLE && + signal_free_time > CEC_SIGNAL_FREE_TIME_NEW_INITIATOR) + signal_free_time = CEC_SIGNAL_FREE_TIME_NEW_INITIATOR; + pin->tx_signal_free_time = signal_free_time; pin->tx_extra_bytes = 0; pin->tx_msg = *msg; diff --git a/drivers/media/common/b2c2/flexcop-i2c.c b/drivers/media/common/b2c2/flexcop-i2c.c index 6675b605eb6f..1f1eaa807811 100644 --- a/drivers/media/common/b2c2/flexcop-i2c.c +++ b/drivers/media/common/b2c2/flexcop-i2c.c @@ -226,12 +226,12 @@ int flexcop_i2c_init(struct flexcop_device *fc) fc->fc_i2c_adap[1].port = FC_I2C_PORT_EEPROM; fc->fc_i2c_adap[2].port = FC_I2C_PORT_TUNER; - strlcpy(fc->fc_i2c_adap[0].i2c_adap.name, "B2C2 FlexCop I2C to demod", - sizeof(fc->fc_i2c_adap[0].i2c_adap.name)); - strlcpy(fc->fc_i2c_adap[1].i2c_adap.name, "B2C2 FlexCop I2C to eeprom", - sizeof(fc->fc_i2c_adap[1].i2c_adap.name)); - strlcpy(fc->fc_i2c_adap[2].i2c_adap.name, "B2C2 FlexCop I2C to tuner", - sizeof(fc->fc_i2c_adap[2].i2c_adap.name)); + strscpy(fc->fc_i2c_adap[0].i2c_adap.name, "B2C2 FlexCop I2C to demod", + sizeof(fc->fc_i2c_adap[0].i2c_adap.name)); + strscpy(fc->fc_i2c_adap[1].i2c_adap.name, "B2C2 FlexCop I2C to eeprom", + sizeof(fc->fc_i2c_adap[1].i2c_adap.name)); + strscpy(fc->fc_i2c_adap[2].i2c_adap.name, "B2C2 FlexCop I2C to tuner", + sizeof(fc->fc_i2c_adap[2].i2c_adap.name)); i2c_set_adapdata(&fc->fc_i2c_adap[0].i2c_adap, &fc->fc_i2c_adap[0]); i2c_set_adapdata(&fc->fc_i2c_adap[1].i2c_adap, &fc->fc_i2c_adap[1]); diff --git a/drivers/media/common/cx2341x.c b/drivers/media/common/cx2341x.c index 81dce9a81bd3..1dcc39b87bb7 100644 --- a/drivers/media/common/cx2341x.c +++ b/drivers/media/common/cx2341x.c @@ -569,7 +569,7 @@ static int cx2341x_ctrl_query_fill(struct v4l2_queryctrl *qctrl, qctrl->step = step; qctrl->default_value = def; qctrl->reserved[0] = qctrl->reserved[1] = 0; - strlcpy(qctrl->name, name, sizeof(qctrl->name)); + strscpy(qctrl->name, name, sizeof(qctrl->name)); return 0; default: diff --git a/drivers/media/common/saa7146/saa7146_fops.c b/drivers/media/common/saa7146/saa7146_fops.c index d4987fd05d05..c790ae264464 100644 --- a/drivers/media/common/saa7146/saa7146_fops.c +++ b/drivers/media/common/saa7146/saa7146_fops.c @@ -606,7 +606,7 @@ int saa7146_register_device(struct video_device *vfd, struct saa7146_dev *dev, vfd->tvnorms = 0; for (i = 0; i < dev->ext_vv_data->num_stds; i++) vfd->tvnorms |= dev->ext_vv_data->stds[i].id; - strlcpy(vfd->name, name, sizeof(vfd->name)); + strscpy(vfd->name, name, sizeof(vfd->name)); video_set_drvdata(vfd, dev); err = video_register_device(vfd, type, -1); diff --git a/drivers/media/common/saa7146/saa7146_video.c b/drivers/media/common/saa7146/saa7146_video.c index 0dfa0c09d646..f90aa8109663 100644 --- a/drivers/media/common/saa7146/saa7146_video.c +++ b/drivers/media/common/saa7146/saa7146_video.c @@ -451,8 +451,8 @@ static int vidioc_querycap(struct file *file, void *fh, struct v4l2_capability * struct video_device *vdev = video_devdata(file); struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; - strcpy((char *)cap->driver, "saa7146 v4l2"); - strlcpy((char *)cap->card, dev->ext->name, sizeof(cap->card)); + strscpy((char *)cap->driver, "saa7146 v4l2", sizeof(cap->driver)); + strscpy((char *)cap->card, dev->ext->name, sizeof(cap->card)); sprintf((char *)cap->bus_info, "PCI:%s", pci_name(dev->pci)); cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | @@ -525,8 +525,8 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtd { if (f->index >= ARRAY_SIZE(formats)) return -EINVAL; - strlcpy((char *)f->description, formats[f->index].name, - sizeof(f->description)); + strscpy((char *)f->description, formats[f->index].name, + sizeof(f->description)); f->pixelformat = formats[f->index].pixelformat; return 0; } diff --git a/drivers/media/common/siano/smscoreapi.c b/drivers/media/common/siano/smscoreapi.c index 3b02cb570a6e..add9d6361914 100644 --- a/drivers/media/common/siano/smscoreapi.c +++ b/drivers/media/common/siano/smscoreapi.c @@ -450,7 +450,7 @@ static struct smscore_registry_entry_t *smscore_find_registry(char *devpath) entry = kmalloc(sizeof(*entry), GFP_KERNEL); if (entry) { entry->mode = default_mode; - strlcpy(entry->devpath, devpath, sizeof(entry->devpath)); + strscpy(entry->devpath, devpath, sizeof(entry->devpath)); list_add(&entry->entry, &g_smscore_registry); } else pr_err("failed to create smscore_registry.\n"); @@ -735,7 +735,7 @@ int smscore_register_device(struct smsdevice_params_t *params, dev->postload_handler = params->postload_handler; dev->device_flags = params->flags; - strlcpy(dev->devpath, params->devpath, sizeof(dev->devpath)); + strscpy(dev->devpath, params->devpath, sizeof(dev->devpath)); smscore_registry_settype(dev->devpath, params->device_type); diff --git a/drivers/media/common/siano/smsir.c b/drivers/media/common/siano/smsir.c index 56db0a944421..79bd627f84b8 100644 --- a/drivers/media/common/siano/smsir.c +++ b/drivers/media/common/siano/smsir.c @@ -26,10 +26,10 @@ void sms_ir_event(struct smscore_device_t *coredev, const char *buf, int len) const s32 *samples = (const void *)buf; for (i = 0; i < len >> 2; i++) { - DEFINE_IR_RAW_EVENT(ev); - - ev.duration = abs(samples[i]) * 1000; /* Convert to ns */ - ev.pulse = (samples[i] > 0) ? false : true; + struct ir_raw_event ev = { + .duration = abs(samples[i]) * 1000, /* Convert to ns */ + .pulse = (samples[i] > 0) ? false : true + }; ir_raw_event_store(coredev->ir.dev, &ev); } @@ -55,7 +55,7 @@ int sms_ir_init(struct smscore_device_t *coredev) snprintf(coredev->ir.name, sizeof(coredev->ir.name), "SMS IR (%s)", sms_get_board(board_id)->name); - strlcpy(coredev->ir.phys, coredev->devpath, sizeof(coredev->ir.phys)); + strscpy(coredev->ir.phys, coredev->devpath, sizeof(coredev->ir.phys)); strlcat(coredev->ir.phys, "/ir0", sizeof(coredev->ir.phys)); dev->device_name = coredev->ir.name; diff --git a/drivers/media/common/v4l2-tpg/v4l2-tpg-colors.c b/drivers/media/common/v4l2-tpg/v4l2-tpg-colors.c index 3a3dc23c560c..a4341205c197 100644 --- a/drivers/media/common/v4l2-tpg/v4l2-tpg-colors.c +++ b/drivers/media/common/v4l2-tpg/v4l2-tpg-colors.c @@ -602,14 +602,14 @@ const struct tpg_rbg_color16 tpg_csc_colors[V4L2_COLORSPACE_DCI_P3 + 1][V4L2_XFE [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_SRGB][5] = { 3138, 657, 810 }, [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_SRGB][6] = { 731, 680, 3048 }, [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_SRGB][7] = { 800, 799, 800 }, - [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_ADOBERGB][0] = { 3033, 3033, 3033 }, - [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_ADOBERGB][1] = { 3046, 3054, 886 }, - [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_ADOBERGB][2] = { 0, 3058, 3031 }, - [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_ADOBERGB][3] = { 360, 3079, 877 }, - [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_ADOBERGB][4] = { 3103, 587, 3027 }, - [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_ADOBERGB][5] = { 3116, 723, 861 }, - [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_ADOBERGB][6] = { 789, 744, 3025 }, - [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_ADOBERGB][7] = { 851, 851, 851 }, + [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_OPRGB][0] = { 3033, 3033, 3033 }, + [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_OPRGB][1] = { 3046, 3054, 886 }, + [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_OPRGB][2] = { 0, 3058, 3031 }, + [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_OPRGB][3] = { 360, 3079, 877 }, + [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_OPRGB][4] = { 3103, 587, 3027 }, + [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_OPRGB][5] = { 3116, 723, 861 }, + [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_OPRGB][6] = { 789, 744, 3025 }, + [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_OPRGB][7] = { 851, 851, 851 }, [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_SMPTE240M][0] = { 2926, 2926, 2926 }, [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_SMPTE240M][1] = { 2941, 2950, 546 }, [V4L2_COLORSPACE_SMPTE170M][V4L2_XFER_FUNC_SMPTE240M][2] = { 0, 2954, 2924 }, @@ -658,14 +658,14 @@ const struct tpg_rbg_color16 tpg_csc_colors[V4L2_COLORSPACE_DCI_P3 + 1][V4L2_XFE [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_SRGB][5] = { 3138, 657, 810 }, [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_SRGB][6] = { 731, 680, 3048 }, [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_SRGB][7] = { 800, 799, 800 }, - [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_ADOBERGB][0] = { 3033, 3033, 3033 }, - [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_ADOBERGB][1] = { 3046, 3054, 886 }, - [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_ADOBERGB][2] = { 0, 3058, 3031 }, - [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_ADOBERGB][3] = { 360, 3079, 877 }, - [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_ADOBERGB][4] = { 3103, 587, 3027 }, - [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_ADOBERGB][5] = { 3116, 723, 861 }, - [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_ADOBERGB][6] = { 789, 744, 3025 }, - [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_ADOBERGB][7] = { 851, 851, 851 }, + [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_OPRGB][0] = { 3033, 3033, 3033 }, + [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_OPRGB][1] = { 3046, 3054, 886 }, + [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_OPRGB][2] = { 0, 3058, 3031 }, + [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_OPRGB][3] = { 360, 3079, 877 }, + [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_OPRGB][4] = { 3103, 587, 3027 }, + [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_OPRGB][5] = { 3116, 723, 861 }, + [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_OPRGB][6] = { 789, 744, 3025 }, + [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_OPRGB][7] = { 851, 851, 851 }, [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_SMPTE240M][0] = { 2926, 2926, 2926 }, [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_SMPTE240M][1] = { 2941, 2950, 546 }, [V4L2_COLORSPACE_SMPTE240M][V4L2_XFER_FUNC_SMPTE240M][2] = { 0, 2954, 2924 }, @@ -714,14 +714,14 @@ const struct tpg_rbg_color16 tpg_csc_colors[V4L2_COLORSPACE_DCI_P3 + 1][V4L2_XFE [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_SRGB][5] = { 3056, 800, 800 }, [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_SRGB][6] = { 800, 800, 3056 }, [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_SRGB][7] = { 800, 800, 800 }, - [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_ADOBERGB][0] = { 3033, 3033, 3033 }, - [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_ADOBERGB][1] = { 3033, 3033, 851 }, - [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_ADOBERGB][2] = { 851, 3033, 3033 }, - [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_ADOBERGB][3] = { 851, 3033, 851 }, - [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_ADOBERGB][4] = { 3033, 851, 3033 }, - [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_ADOBERGB][5] = { 3033, 851, 851 }, - [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_ADOBERGB][6] = { 851, 851, 3033 }, - [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_ADOBERGB][7] = { 851, 851, 851 }, + [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_OPRGB][0] = { 3033, 3033, 3033 }, + [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_OPRGB][1] = { 3033, 3033, 851 }, + [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_OPRGB][2] = { 851, 3033, 3033 }, + [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_OPRGB][3] = { 851, 3033, 851 }, + [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_OPRGB][4] = { 3033, 851, 3033 }, + [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_OPRGB][5] = { 3033, 851, 851 }, + [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_OPRGB][6] = { 851, 851, 3033 }, + [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_OPRGB][7] = { 851, 851, 851 }, [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_SMPTE240M][0] = { 2926, 2926, 2926 }, [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_SMPTE240M][1] = { 2926, 2926, 507 }, [V4L2_COLORSPACE_REC709][V4L2_XFER_FUNC_SMPTE240M][2] = { 507, 2926, 2926 }, @@ -770,14 +770,14 @@ const struct tpg_rbg_color16 tpg_csc_colors[V4L2_COLORSPACE_DCI_P3 + 1][V4L2_XFE [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][5] = { 2599, 901, 909 }, [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][6] = { 991, 0, 2966 }, [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SRGB][7] = { 800, 799, 800 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][0] = { 3033, 3033, 3033 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][1] = { 2989, 3120, 1180 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][2] = { 1913, 3011, 3009 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][3] = { 1836, 3099, 1105 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][4] = { 2627, 413, 2966 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][5] = { 2576, 943, 951 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][6] = { 1026, 0, 2942 }, - [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_ADOBERGB][7] = { 851, 851, 851 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_OPRGB][0] = { 3033, 3033, 3033 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_OPRGB][1] = { 2989, 3120, 1180 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_OPRGB][2] = { 1913, 3011, 3009 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_OPRGB][3] = { 1836, 3099, 1105 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_OPRGB][4] = { 2627, 413, 2966 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_OPRGB][5] = { 2576, 943, 951 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_OPRGB][6] = { 1026, 0, 2942 }, + [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_OPRGB][7] = { 851, 851, 851 }, [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][0] = { 2926, 2926, 2926 }, [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][1] = { 2879, 3022, 874 }, [V4L2_COLORSPACE_470_SYSTEM_M][V4L2_XFER_FUNC_SMPTE240M][2] = { 1688, 2903, 2901 }, @@ -826,14 +826,14 @@ const struct tpg_rbg_color16 tpg_csc_colors[V4L2_COLORSPACE_DCI_P3 + 1][V4L2_XFE [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_SRGB][5] = { 3001, 800, 799 }, [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_SRGB][6] = { 800, 800, 3071 }, [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_SRGB][7] = { 800, 800, 799 }, - [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_ADOBERGB][0] = { 3033, 3033, 3033 }, - [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_ADOBERGB][1] = { 3033, 3033, 776 }, - [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_ADOBERGB][2] = { 1068, 3033, 3033 }, - [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_ADOBERGB][3] = { 1068, 3033, 776 }, - [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_ADOBERGB][4] = { 2977, 851, 3048 }, - [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_ADOBERGB][5] = { 2977, 851, 851 }, - [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_ADOBERGB][6] = { 851, 851, 3048 }, - [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_ADOBERGB][7] = { 851, 851, 851 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_OPRGB][0] = { 3033, 3033, 3033 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_OPRGB][1] = { 3033, 3033, 776 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_OPRGB][2] = { 1068, 3033, 3033 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_OPRGB][3] = { 1068, 3033, 776 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_OPRGB][4] = { 2977, 851, 3048 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_OPRGB][5] = { 2977, 851, 851 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_OPRGB][6] = { 851, 851, 3048 }, + [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_OPRGB][7] = { 851, 851, 851 }, [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_SMPTE240M][0] = { 2926, 2926, 2926 }, [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_SMPTE240M][1] = { 2926, 2926, 423 }, [V4L2_COLORSPACE_470_SYSTEM_BG][V4L2_XFER_FUNC_SMPTE240M][2] = { 749, 2926, 2926 }, @@ -882,14 +882,14 @@ const struct tpg_rbg_color16 tpg_csc_colors[V4L2_COLORSPACE_DCI_P3 + 1][V4L2_XFE [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SRGB][5] = { 3056, 800, 800 }, [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SRGB][6] = { 800, 800, 3056 }, [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SRGB][7] = { 800, 800, 800 }, - [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_ADOBERGB][0] = { 3033, 3033, 3033 }, - [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_ADOBERGB][1] = { 3033, 3033, 851 }, - [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_ADOBERGB][2] = { 851, 3033, 3033 }, - [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_ADOBERGB][3] = { 851, 3033, 851 }, - [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_ADOBERGB][4] = { 3033, 851, 3033 }, - [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_ADOBERGB][5] = { 3033, 851, 851 }, - [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_ADOBERGB][6] = { 851, 851, 3033 }, - [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_ADOBERGB][7] = { 851, 851, 851 }, + [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_OPRGB][0] = { 3033, 3033, 3033 }, + [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_OPRGB][1] = { 3033, 3033, 851 }, + [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_OPRGB][2] = { 851, 3033, 3033 }, + [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_OPRGB][3] = { 851, 3033, 851 }, + [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_OPRGB][4] = { 3033, 851, 3033 }, + [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_OPRGB][5] = { 3033, 851, 851 }, + [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_OPRGB][6] = { 851, 851, 3033 }, + [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_OPRGB][7] = { 851, 851, 851 }, [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SMPTE240M][0] = { 2926, 2926, 2926 }, [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SMPTE240M][1] = { 2926, 2926, 507 }, [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SMPTE240M][2] = { 507, 2926, 2926 }, @@ -922,62 +922,62 @@ const struct tpg_rbg_color16 tpg_csc_colors[V4L2_COLORSPACE_DCI_P3 + 1][V4L2_XFE [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SMPTE2084][5] = { 1812, 886, 886 }, [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SMPTE2084][6] = { 886, 886, 1812 }, [V4L2_COLORSPACE_SRGB][V4L2_XFER_FUNC_SMPTE2084][7] = { 886, 886, 886 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_709][0] = { 2939, 2939, 2939 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_709][1] = { 2939, 2939, 781 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_709][2] = { 1622, 2939, 2939 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_709][3] = { 1622, 2939, 781 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_709][4] = { 2502, 547, 2881 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_709][5] = { 2502, 547, 547 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_709][6] = { 547, 547, 2881 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_709][7] = { 547, 547, 547 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SRGB][0] = { 3056, 3056, 3056 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SRGB][1] = { 3056, 3056, 1031 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SRGB][2] = { 1838, 3056, 3056 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SRGB][3] = { 1838, 3056, 1031 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SRGB][4] = { 2657, 800, 3002 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SRGB][5] = { 2657, 800, 800 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SRGB][6] = { 800, 800, 3002 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SRGB][7] = { 800, 800, 800 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_ADOBERGB][0] = { 3033, 3033, 3033 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_ADOBERGB][1] = { 3033, 3033, 1063 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_ADOBERGB][2] = { 1828, 3033, 3033 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_ADOBERGB][3] = { 1828, 3033, 1063 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_ADOBERGB][4] = { 2633, 851, 2979 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_ADOBERGB][5] = { 2633, 851, 851 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_ADOBERGB][6] = { 851, 851, 2979 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_ADOBERGB][7] = { 851, 851, 851 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE240M][0] = { 2926, 2926, 2926 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE240M][1] = { 2926, 2926, 744 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE240M][2] = { 1594, 2926, 2926 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE240M][3] = { 1594, 2926, 744 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE240M][4] = { 2484, 507, 2867 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE240M][5] = { 2484, 507, 507 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE240M][6] = { 507, 507, 2867 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE240M][7] = { 507, 507, 507 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_NONE][0] = { 2125, 2125, 2125 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_NONE][1] = { 2125, 2125, 212 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_NONE][2] = { 698, 2125, 2125 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_NONE][3] = { 698, 2125, 212 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_NONE][4] = { 1557, 130, 2043 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_NONE][5] = { 1557, 130, 130 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_NONE][6] = { 130, 130, 2043 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_NONE][7] = { 130, 130, 130 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][0] = { 3175, 3175, 3175 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][1] = { 3175, 3175, 1308 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][2] = { 2069, 3175, 3175 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][3] = { 2069, 3175, 1308 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][4] = { 2816, 1084, 3127 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][5] = { 2816, 1084, 1084 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][6] = { 1084, 1084, 3127 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_DCI_P3][7] = { 1084, 1084, 1084 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][0] = { 1812, 1812, 1812 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][1] = { 1812, 1812, 1022 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][2] = { 1402, 1812, 1812 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][3] = { 1402, 1812, 1022 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][4] = { 1692, 886, 1797 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][5] = { 1692, 886, 886 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][6] = { 886, 886, 1797 }, - [V4L2_COLORSPACE_ADOBERGB][V4L2_XFER_FUNC_SMPTE2084][7] = { 886, 886, 886 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_709][0] = { 2939, 2939, 2939 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_709][1] = { 2939, 2939, 781 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_709][2] = { 1622, 2939, 2939 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_709][3] = { 1622, 2939, 781 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_709][4] = { 2502, 547, 2881 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_709][5] = { 2502, 547, 547 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_709][6] = { 547, 547, 2881 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_709][7] = { 547, 547, 547 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SRGB][0] = { 3056, 3056, 3056 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SRGB][1] = { 3056, 3056, 1031 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SRGB][2] = { 1838, 3056, 3056 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SRGB][3] = { 1838, 3056, 1031 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SRGB][4] = { 2657, 800, 3002 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SRGB][5] = { 2657, 800, 800 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SRGB][6] = { 800, 800, 3002 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SRGB][7] = { 800, 800, 800 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_OPRGB][0] = { 3033, 3033, 3033 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_OPRGB][1] = { 3033, 3033, 1063 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_OPRGB][2] = { 1828, 3033, 3033 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_OPRGB][3] = { 1828, 3033, 1063 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_OPRGB][4] = { 2633, 851, 2979 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_OPRGB][5] = { 2633, 851, 851 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_OPRGB][6] = { 851, 851, 2979 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_OPRGB][7] = { 851, 851, 851 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE240M][0] = { 2926, 2926, 2926 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE240M][1] = { 2926, 2926, 744 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE240M][2] = { 1594, 2926, 2926 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE240M][3] = { 1594, 2926, 744 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE240M][4] = { 2484, 507, 2867 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE240M][5] = { 2484, 507, 507 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE240M][6] = { 507, 507, 2867 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE240M][7] = { 507, 507, 507 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_NONE][0] = { 2125, 2125, 2125 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_NONE][1] = { 2125, 2125, 212 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_NONE][2] = { 698, 2125, 2125 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_NONE][3] = { 698, 2125, 212 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_NONE][4] = { 1557, 130, 2043 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_NONE][5] = { 1557, 130, 130 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_NONE][6] = { 130, 130, 2043 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_NONE][7] = { 130, 130, 130 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_DCI_P3][0] = { 3175, 3175, 3175 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_DCI_P3][1] = { 3175, 3175, 1308 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_DCI_P3][2] = { 2069, 3175, 3175 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_DCI_P3][3] = { 2069, 3175, 1308 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_DCI_P3][4] = { 2816, 1084, 3127 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_DCI_P3][5] = { 2816, 1084, 1084 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_DCI_P3][6] = { 1084, 1084, 3127 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_DCI_P3][7] = { 1084, 1084, 1084 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE2084][0] = { 1812, 1812, 1812 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE2084][1] = { 1812, 1812, 1022 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE2084][2] = { 1402, 1812, 1812 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE2084][3] = { 1402, 1812, 1022 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE2084][4] = { 1692, 886, 1797 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE2084][5] = { 1692, 886, 886 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE2084][6] = { 886, 886, 1797 }, + [V4L2_COLORSPACE_OPRGB][V4L2_XFER_FUNC_SMPTE2084][7] = { 886, 886, 886 }, [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_709][0] = { 2939, 2939, 2939 }, [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_709][1] = { 2877, 2923, 1058 }, [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_709][2] = { 1837, 2840, 2916 }, @@ -994,14 +994,14 @@ const struct tpg_rbg_color16 tpg_csc_colors[V4L2_COLORSPACE_DCI_P3 + 1][V4L2_XFE [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_SRGB][5] = { 2517, 1159, 900 }, [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_SRGB][6] = { 1042, 870, 2917 }, [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_SRGB][7] = { 800, 800, 800 }, - [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_ADOBERGB][0] = { 3033, 3033, 3033 }, - [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_ADOBERGB][1] = { 2976, 3018, 1315 }, - [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_ADOBERGB][2] = { 2024, 2942, 3011 }, - [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_ADOBERGB][3] = { 1930, 2926, 1256 }, - [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_ADOBERGB][4] = { 2563, 1227, 2916 }, - [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_ADOBERGB][5] = { 2494, 1183, 943 }, - [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_ADOBERGB][6] = { 1073, 916, 2894 }, - [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_ADOBERGB][7] = { 851, 851, 851 }, + [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_OPRGB][0] = { 3033, 3033, 3033 }, + [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_OPRGB][1] = { 2976, 3018, 1315 }, + [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_OPRGB][2] = { 2024, 2942, 3011 }, + [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_OPRGB][3] = { 1930, 2926, 1256 }, + [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_OPRGB][4] = { 2563, 1227, 2916 }, + [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_OPRGB][5] = { 2494, 1183, 943 }, + [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_OPRGB][6] = { 1073, 916, 2894 }, + [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_OPRGB][7] = { 851, 851, 851 }, [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_SMPTE240M][0] = { 2926, 2926, 2926 }, [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_SMPTE240M][1] = { 2864, 2910, 1024 }, [V4L2_COLORSPACE_BT2020][V4L2_XFER_FUNC_SMPTE240M][2] = { 1811, 2826, 2903 }, @@ -1050,14 +1050,14 @@ const struct tpg_rbg_color16 tpg_csc_colors[V4L2_COLORSPACE_DCI_P3 + 1][V4L2_XFE [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SRGB][5] = { 2880, 998, 902 }, [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SRGB][6] = { 816, 823, 2940 }, [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SRGB][7] = { 800, 800, 799 }, - [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][0] = { 3033, 3033, 3033 }, - [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][1] = { 3029, 3028, 1255 }, - [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][2] = { 1406, 2988, 3011 }, - [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][3] = { 1398, 2983, 1190 }, - [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][4] = { 2860, 1050, 2939 }, - [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][5] = { 2857, 1033, 945 }, - [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][6] = { 866, 873, 2916 }, - [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_ADOBERGB][7] = { 851, 851, 851 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_OPRGB][0] = { 3033, 3033, 3033 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_OPRGB][1] = { 3029, 3028, 1255 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_OPRGB][2] = { 1406, 2988, 3011 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_OPRGB][3] = { 1398, 2983, 1190 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_OPRGB][4] = { 2860, 1050, 2939 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_OPRGB][5] = { 2857, 1033, 945 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_OPRGB][6] = { 866, 873, 2916 }, + [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_OPRGB][7] = { 851, 851, 851 }, [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE240M][0] = { 2926, 2926, 2926 }, [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE240M][1] = { 2923, 2921, 957 }, [V4L2_COLORSPACE_DCI_P3][V4L2_XFER_FUNC_SMPTE240M][2] = { 1125, 2877, 2902 }, @@ -1128,7 +1128,7 @@ static const double rec709_to_240m[3][3] = { { 0.0016327, 0.0044133, 0.9939540 }, }; -static const double rec709_to_adobergb[3][3] = { +static const double rec709_to_oprgb[3][3] = { { 0.7151627, 0.2848373, -0.0000000 }, { 0.0000000, 1.0000000, 0.0000000 }, { -0.0000000, 0.0411705, 0.9588295 }, @@ -1195,7 +1195,7 @@ static double transfer_rec709_to_rgb(double v) return (v < 0.081) ? v / 4.5 : pow((v + 0.099) / 1.099, 1.0 / 0.45); } -static double transfer_rgb_to_adobergb(double v) +static double transfer_rgb_to_oprgb(double v) { return pow(v, 1.0 / 2.19921875); } @@ -1251,8 +1251,8 @@ static void csc(enum v4l2_colorspace colorspace, enum v4l2_xfer_func xfer_func, case V4L2_COLORSPACE_470_SYSTEM_M: mult_matrix(r, g, b, rec709_to_ntsc1953); break; - case V4L2_COLORSPACE_ADOBERGB: - mult_matrix(r, g, b, rec709_to_adobergb); + case V4L2_COLORSPACE_OPRGB: + mult_matrix(r, g, b, rec709_to_oprgb); break; case V4L2_COLORSPACE_BT2020: mult_matrix(r, g, b, rec709_to_bt2020); @@ -1284,10 +1284,10 @@ static void csc(enum v4l2_colorspace colorspace, enum v4l2_xfer_func xfer_func, *g = transfer_rgb_to_srgb(*g); *b = transfer_rgb_to_srgb(*b); break; - case V4L2_XFER_FUNC_ADOBERGB: - *r = transfer_rgb_to_adobergb(*r); - *g = transfer_rgb_to_adobergb(*g); - *b = transfer_rgb_to_adobergb(*b); + case V4L2_XFER_FUNC_OPRGB: + *r = transfer_rgb_to_oprgb(*r); + *g = transfer_rgb_to_oprgb(*g); + *b = transfer_rgb_to_oprgb(*b); break; case V4L2_XFER_FUNC_DCI_P3: *r = transfer_rgb_to_dcip3(*r); @@ -1321,7 +1321,7 @@ int main(int argc, char **argv) V4L2_COLORSPACE_470_SYSTEM_BG, 0, V4L2_COLORSPACE_SRGB, - V4L2_COLORSPACE_ADOBERGB, + V4L2_COLORSPACE_OPRGB, V4L2_COLORSPACE_BT2020, 0, V4L2_COLORSPACE_DCI_P3, @@ -1336,7 +1336,7 @@ int main(int argc, char **argv) "V4L2_COLORSPACE_470_SYSTEM_BG", "", "V4L2_COLORSPACE_SRGB", - "V4L2_COLORSPACE_ADOBERGB", + "V4L2_COLORSPACE_OPRGB", "V4L2_COLORSPACE_BT2020", "", "V4L2_COLORSPACE_DCI_P3", @@ -1345,7 +1345,7 @@ int main(int argc, char **argv) "", "V4L2_XFER_FUNC_709", "V4L2_XFER_FUNC_SRGB", - "V4L2_XFER_FUNC_ADOBERGB", + "V4L2_XFER_FUNC_OPRGB", "V4L2_XFER_FUNC_SMPTE240M", "V4L2_XFER_FUNC_NONE", "V4L2_XFER_FUNC_DCI_P3", diff --git a/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c b/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c index abd4c788dffd..fa483b95bc5a 100644 --- a/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c +++ b/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c @@ -202,6 +202,10 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc) case V4L2_PIX_FMT_SGBRG12: case V4L2_PIX_FMT_SGRBG12: case V4L2_PIX_FMT_SRGGB12: + case V4L2_PIX_FMT_SBGGR16: + case V4L2_PIX_FMT_SGBRG16: + case V4L2_PIX_FMT_SGRBG16: + case V4L2_PIX_FMT_SRGGB16: tpg->interleaved = true; tpg->vdownsampling[1] = 1; tpg->hdownsampling[1] = 1; @@ -235,6 +239,7 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc) case V4L2_PIX_FMT_Y12: case V4L2_PIX_FMT_Y16: case V4L2_PIX_FMT_Y16_BE: + case V4L2_PIX_FMT_Z16: tpg->color_enc = TGP_COLOR_ENC_LUMA; break; case V4L2_PIX_FMT_YUV444: @@ -351,6 +356,7 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc) case V4L2_PIX_FMT_Y12: case V4L2_PIX_FMT_Y16: case V4L2_PIX_FMT_Y16_BE: + case V4L2_PIX_FMT_Z16: tpg->twopixelsize[0] = 2 * 2; break; case V4L2_PIX_FMT_RGB24: @@ -392,6 +398,10 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc) case V4L2_PIX_FMT_SGRBG12: case V4L2_PIX_FMT_SGBRG12: case V4L2_PIX_FMT_SBGGR12: + case V4L2_PIX_FMT_SRGGB16: + case V4L2_PIX_FMT_SGRBG16: + case V4L2_PIX_FMT_SGBRG16: + case V4L2_PIX_FMT_SBGGR16: tpg->twopixelsize[0] = 4; tpg->twopixelsize[1] = 4; break; @@ -1062,6 +1072,7 @@ static void gen_twopix(struct tpg_data *tpg, buf[0][offset+1] = r_y_h >> 4; break; case V4L2_PIX_FMT_Y16: + case V4L2_PIX_FMT_Z16: /* * Ideally both bytes should be set to r_y_h, but then you won't * be able to detect endian problems. So keep it 0 except for @@ -1355,6 +1366,22 @@ static void gen_twopix(struct tpg_data *tpg, buf[0][offset] |= (buf[0][offset] >> 4) & 0xf; buf[1][offset] |= (buf[1][offset] >> 4) & 0xf; break; + case V4L2_PIX_FMT_SBGGR16: + buf[0][offset] = buf[0][offset + 1] = odd ? g_u_s : b_v; + buf[1][offset] = buf[1][offset + 1] = odd ? r_y_h : g_u_s; + break; + case V4L2_PIX_FMT_SGBRG16: + buf[0][offset] = buf[0][offset + 1] = odd ? b_v : g_u_s; + buf[1][offset] = buf[1][offset + 1] = odd ? g_u_s : r_y_h; + break; + case V4L2_PIX_FMT_SGRBG16: + buf[0][offset] = buf[0][offset + 1] = odd ? r_y_h : g_u_s; + buf[1][offset] = buf[1][offset + 1] = odd ? g_u_s : b_v; + break; + case V4L2_PIX_FMT_SRGGB16: + buf[0][offset] = buf[0][offset + 1] = odd ? g_u_s : r_y_h; + buf[1][offset] = buf[1][offset + 1] = odd ? b_v : g_u_s; + break; } } @@ -1373,6 +1400,10 @@ unsigned tpg_g_interleaved_plane(const struct tpg_data *tpg, unsigned buf_line) case V4L2_PIX_FMT_SGBRG12: case V4L2_PIX_FMT_SGRBG12: case V4L2_PIX_FMT_SRGGB12: + case V4L2_PIX_FMT_SBGGR16: + case V4L2_PIX_FMT_SGBRG16: + case V4L2_PIX_FMT_SGRBG16: + case V4L2_PIX_FMT_SRGGB16: return buf_line & 1; default: return 0; @@ -1770,7 +1801,7 @@ typedef struct { u16 __; u8 _; } __packed x24; pos[7] = (chr & (0x01 << 0) ? fg : bg); \ } \ \ - pos += (tpg->hflip ? -8 : 8) / hdiv; \ + pos += (tpg->hflip ? -8 : 8) / (int)hdiv; \ } \ } \ } while (0) @@ -2038,8 +2069,12 @@ void tpg_log_status(struct tpg_data *tpg) tpg->compose.left, tpg->compose.top); pr_info("tpg colorspace: %d\n", tpg->colorspace); pr_info("tpg transfer function: %d/%d\n", tpg->xfer_func, tpg->real_xfer_func); - pr_info("tpg Y'CbCr encoding: %d/%d\n", tpg->ycbcr_enc, tpg->real_ycbcr_enc); - pr_info("tpg HSV encoding: %d/%d\n", tpg->hsv_enc, tpg->real_hsv_enc); + if (tpg->color_enc == TGP_COLOR_ENC_HSV) + pr_info("tpg HSV encoding: %d/%d\n", + tpg->hsv_enc, tpg->real_hsv_enc); + else if (tpg->color_enc == TGP_COLOR_ENC_YCBCR) + pr_info("tpg Y'CbCr encoding: %d/%d\n", + tpg->ycbcr_enc, tpg->real_ycbcr_enc); pr_info("tpg quantization: %d/%d\n", tpg->quantization, tpg->real_quantization); pr_info("tpg RGB range: %d/%d\n", tpg->rgb_range, tpg->real_rgb_range); } diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c index 5653e8eebe2b..d6d22cf77066 100644 --- a/drivers/media/common/videobuf2/videobuf2-core.c +++ b/drivers/media/common/videobuf2/videobuf2-core.c @@ -661,6 +661,7 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory, { unsigned int num_buffers, allocated_buffers, num_planes = 0; unsigned plane_sizes[VB2_MAX_PLANES] = { }; + unsigned int i; int ret; if (q->streaming) { @@ -718,6 +719,14 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory, if (ret) return ret; + /* Check that driver has set sane values */ + if (WARN_ON(!num_planes)) + return -EINVAL; + + for (i = 0; i < num_planes; i++) + if (WARN_ON(!plane_sizes[i])) + return -EINVAL; + /* Finally, allocate buffers and video memory */ allocated_buffers = __vb2_queue_alloc(q, memory, num_buffers, num_planes, plane_sizes); diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c index d548f98c7a67..1544e8cef564 100644 --- a/drivers/media/dvb-core/dmxdev.c +++ b/drivers/media/dvb-core/dmxdev.c @@ -1265,6 +1265,7 @@ static const struct file_operations dvb_demux_fops = { .owner = THIS_MODULE, .read = dvb_demux_read, .unlocked_ioctl = dvb_demux_ioctl, + .compat_ioctl = dvb_demux_ioctl, .open = dvb_demux_open, .release = dvb_demux_release, .poll = dvb_demux_poll, diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index c4e7ebfe4d29..961207cf09eb 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c @@ -2422,7 +2422,7 @@ static int dvb_frontend_handle_ioctl(struct file *file, struct dvb_frontend_info *info = parg; memset(info, 0, sizeof(*info)); - strcpy(info->name, fe->ops.info.name); + strscpy(info->name, fe->ops.info.name, sizeof(info->name)); info->symbol_rate_min = fe->ops.info.symbol_rate_min; info->symbol_rate_max = fe->ops.info.symbol_rate_max; info->symbol_rate_tolerance = fe->ops.info.symbol_rate_tolerance; diff --git a/drivers/media/dvb-core/dvb_vb2.c b/drivers/media/dvb-core/dvb_vb2.c index b811adf88afa..c90b1fd94735 100644 --- a/drivers/media/dvb-core/dvb_vb2.c +++ b/drivers/media/dvb-core/dvb_vb2.c @@ -194,7 +194,7 @@ int dvb_vb2_init(struct dvb_vb2_ctx *ctx, const char *name, int nonblocking) spin_lock_init(&ctx->slock); INIT_LIST_HEAD(&ctx->dvb_q); - strlcpy(ctx->name, name, DVB_VB2_NAME_MAX); + strscpy(ctx->name, name, DVB_VB2_NAME_MAX); ctx->nonblocking = nonblocking; ctx->state = DVB_VB2_STATE_INIT; diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c index 3c8778570331..b7171bf094fb 100644 --- a/drivers/media/dvb-core/dvbdev.c +++ b/drivers/media/dvb-core/dvbdev.c @@ -621,7 +621,7 @@ int dvb_create_media_graph(struct dvb_adapter *adap, unsigned demux_pad = 0; unsigned dvr_pad = 0; unsigned ntuner = 0, ndemod = 0; - int ret; + int ret, pad_source, pad_sink; static const char *connector_name = "Television"; if (!mdev) @@ -681,7 +681,7 @@ int dvb_create_media_graph(struct dvb_adapter *adap, if (ret) return ret; - if (!ntuner) + if (!ntuner) { ret = media_create_pad_links(mdev, MEDIA_ENT_F_CONN_RF, conn, 0, @@ -689,22 +689,31 @@ int dvb_create_media_graph(struct dvb_adapter *adap, demod, 0, MEDIA_LNK_FL_ENABLED, false); - else + } else { + pad_sink = media_get_pad_index(tuner, true, + PAD_SIGNAL_ANALOG); + if (pad_sink < 0) + return -EINVAL; ret = media_create_pad_links(mdev, MEDIA_ENT_F_CONN_RF, conn, 0, MEDIA_ENT_F_TUNER, - tuner, TUNER_PAD_RF_INPUT, + tuner, pad_sink, MEDIA_LNK_FL_ENABLED, false); + } if (ret) return ret; } if (ntuner && ndemod) { + pad_source = media_get_pad_index(tuner, true, + PAD_SIGNAL_ANALOG); + if (pad_source) + return -EINVAL; ret = media_create_pad_links(mdev, MEDIA_ENT_F_TUNER, - tuner, TUNER_PAD_OUTPUT, + tuner, pad_source, MEDIA_ENT_F_DTV_DEMOD, demod, 0, MEDIA_LNK_FL_ENABLED, false); @@ -967,9 +976,9 @@ struct i2c_client *dvb_module_probe(const char *module_name, return NULL; if (name) - strlcpy(board_info->type, name, I2C_NAME_SIZE); + strscpy(board_info->type, name, I2C_NAME_SIZE); else - strlcpy(board_info->type, module_name, I2C_NAME_SIZE); + strscpy(board_info->type, module_name, I2C_NAME_SIZE); board_info->addr = addr; board_info->platform_data = platform_data; diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig index 048285134cdf..847da72d1256 100644 --- a/drivers/media/dvb-frontends/Kconfig +++ b/drivers/media/dvb-frontends/Kconfig @@ -791,6 +791,16 @@ config DVB_LNBH25 An SEC control chip. Say Y when you want to support this chip. +config DVB_LNBH29 + tristate "LNBH29 SEC controller" + depends on DVB_CORE && I2C + default m if !MEDIA_SUBDRV_AUTOSELECT + help + LNB power supply and control voltage + regulator chip with step-up converter + and I2C interface for STMicroelectronics LNBH29. + Say Y when you want to support this chip. + config DVB_LNBP21 tristate "LNBP21/LNBH24 SEC controllers" depends on DVB_CORE && I2C diff --git a/drivers/media/dvb-frontends/Makefile b/drivers/media/dvb-frontends/Makefile index 779dfd027b24..e9179162658c 100644 --- a/drivers/media/dvb-frontends/Makefile +++ b/drivers/media/dvb-frontends/Makefile @@ -58,6 +58,7 @@ obj-$(CONFIG_DVB_LGDT3306A) += lgdt3306a.o obj-$(CONFIG_DVB_LG2160) += lg2160.o obj-$(CONFIG_DVB_CX24123) += cx24123.o obj-$(CONFIG_DVB_LNBH25) += lnbh25.o +obj-$(CONFIG_DVB_LNBH29) += lnbh29.o obj-$(CONFIG_DVB_LNBP21) += lnbp21.o obj-$(CONFIG_DVB_LNBP22) += lnbp22.o obj-$(CONFIG_DVB_ISL6405) += isl6405.o diff --git a/drivers/media/dvb-frontends/au8522_decoder.c b/drivers/media/dvb-frontends/au8522_decoder.c index f285096a48f0..b2dd20ffd002 100644 --- a/drivers/media/dvb-frontends/au8522_decoder.c +++ b/drivers/media/dvb-frontends/au8522_decoder.c @@ -718,10 +718,12 @@ static int au8522_probe(struct i2c_client *client, v4l2_i2c_subdev_init(sd, client, &au8522_ops); #if defined(CONFIG_MEDIA_CONTROLLER) - state->pads[DEMOD_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK; - state->pads[DEMOD_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE; - state->pads[DEMOD_PAD_VBI_OUT].flags = MEDIA_PAD_FL_SOURCE; - state->pads[DEMOD_PAD_AUDIO_OUT].flags = MEDIA_PAD_FL_SOURCE; + state->pads[AU8522_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK; + state->pads[AU8522_PAD_IF_INPUT].sig_type = PAD_SIGNAL_ANALOG; + state->pads[AU8522_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE; + state->pads[AU8522_PAD_VID_OUT].sig_type = PAD_SIGNAL_DV; + state->pads[AU8522_PAD_AUDIO_OUT].flags = MEDIA_PAD_FL_SOURCE; + state->pads[AU8522_PAD_AUDIO_OUT].sig_type = PAD_SIGNAL_AUDIO; sd->entity.function = MEDIA_ENT_F_ATV_DECODER; ret = media_entity_pads_init(&sd->entity, ARRAY_SIZE(state->pads), diff --git a/drivers/media/dvb-frontends/au8522_priv.h b/drivers/media/dvb-frontends/au8522_priv.h index 2043c1744753..68299d2705f7 100644 --- a/drivers/media/dvb-frontends/au8522_priv.h +++ b/drivers/media/dvb-frontends/au8522_priv.h @@ -40,6 +40,13 @@ #define AU8522_DIGITAL_MODE 1 #define AU8522_SUSPEND_MODE 2 +enum au8522_pads { + AU8522_PAD_IF_INPUT, + AU8522_PAD_VID_OUT, + AU8522_PAD_AUDIO_OUT, + AU8522_NUM_PADS +}; + struct au8522_state { struct i2c_client *c; struct i2c_adapter *i2c; @@ -71,7 +78,7 @@ struct au8522_state { struct v4l2_ctrl_handler hdl; #ifdef CONFIG_MEDIA_CONTROLLER - struct media_pad pads[DEMOD_NUM_PADS]; + struct media_pad pads[AU8522_NUM_PADS]; #endif }; diff --git a/drivers/media/dvb-frontends/cx24123.c b/drivers/media/dvb-frontends/cx24123.c index e49215020a93..83dfae78579d 100644 --- a/drivers/media/dvb-frontends/cx24123.c +++ b/drivers/media/dvb-frontends/cx24123.c @@ -1087,7 +1087,7 @@ struct dvb_frontend *cx24123_attach(const struct cx24123_config *config, if (config->dont_use_pll) cx24123_repeater_mode(state, 1, 0); - strlcpy(state->tuner_i2c_adapter.name, "CX24123 tuner I2C bus", + strscpy(state->tuner_i2c_adapter.name, "CX24123 tuner I2C bus", sizeof(state->tuner_i2c_adapter.name)); state->tuner_i2c_adapter.algo = &cx24123_tuner_i2c_algo; state->tuner_i2c_adapter.algo_data = NULL; diff --git a/drivers/media/dvb-frontends/cxd2099.c b/drivers/media/dvb-frontends/cxd2099.c index 4a0ce3037fd6..5264e873850e 100644 --- a/drivers/media/dvb-frontends/cxd2099.c +++ b/drivers/media/dvb-frontends/cxd2099.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * cxd2099.c: Driver for the Sony CXD2099AR Common Interface Controller * @@ -701,4 +702,4 @@ module_i2c_driver(cxd2099_driver); MODULE_DESCRIPTION("Sony CXD2099AR Common Interface controller driver"); MODULE_AUTHOR("Ralph Metzler"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/dvb-frontends/cxd2099.h b/drivers/media/dvb-frontends/cxd2099.h index ec1910dec3f3..0c101bdef01d 100644 --- a/drivers/media/dvb-frontends/cxd2099.h +++ b/drivers/media/dvb-frontends/cxd2099.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * cxd2099.h: Driver for the Sony CXD2099AR Common Interface Controller * diff --git a/drivers/media/dvb-frontends/cxd2820r_core.c b/drivers/media/dvb-frontends/cxd2820r_core.c index 3e0d8cbd76da..0f0acf98d226 100644 --- a/drivers/media/dvb-frontends/cxd2820r_core.c +++ b/drivers/media/dvb-frontends/cxd2820r_core.c @@ -540,7 +540,7 @@ struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *config, pdata.attach_in_use = true; memset(&board_info, 0, sizeof(board_info)); - strlcpy(board_info.type, "cxd2820r", I2C_NAME_SIZE); + strscpy(board_info.type, "cxd2820r", I2C_NAME_SIZE); board_info.addr = config->i2c_address; board_info.platform_data = &pdata; client = i2c_new_device(adapter, &board_info); diff --git a/drivers/media/dvb-frontends/dibx000_common.c b/drivers/media/dvb-frontends/dibx000_common.c index 70119c79ac2b..dc80a8442e7a 100644 --- a/drivers/media/dvb-frontends/dibx000_common.c +++ b/drivers/media/dvb-frontends/dibx000_common.c @@ -424,7 +424,7 @@ static int i2c_adapter_init(struct i2c_adapter *i2c_adap, struct i2c_algorithm *algo, const char *name, struct dibx000_i2c_master *mst) { - strlcpy(i2c_adap->name, name, sizeof(i2c_adap->name)); + strscpy(i2c_adap->name, name, sizeof(i2c_adap->name)); i2c_adap->algo = algo; i2c_adap->algo_data = NULL; i2c_set_adapdata(i2c_adap, mst); diff --git a/drivers/media/dvb-frontends/drx39xyj/drxj.c b/drivers/media/dvb-frontends/drx39xyj/drxj.c index 9628d4067fe1..551b7d65fa66 100644 --- a/drivers/media/dvb-frontends/drx39xyj/drxj.c +++ b/drivers/media/dvb-frontends/drx39xyj/drxj.c @@ -3555,8 +3555,8 @@ static int ctrl_set_uio_cfg(struct drx_demod_instance *demod, struct drxuio_cfg if (!ext_attr->has_smatx) return -EIO; switch (uio_cfg->mode) { - case DRX_UIO_MODE_FIRMWARE_SMA: /* falltrough */ - case DRX_UIO_MODE_FIRMWARE_SAW: /* falltrough */ + case DRX_UIO_MODE_FIRMWARE_SMA: /* fall through */ + case DRX_UIO_MODE_FIRMWARE_SAW: /* fall through */ case DRX_UIO_MODE_READWRITE: ext_attr->uio_sma_tx_mode = uio_cfg->mode; break; @@ -3579,7 +3579,7 @@ static int ctrl_set_uio_cfg(struct drx_demod_instance *demod, struct drxuio_cfg if (!ext_attr->has_smarx) return -EIO; switch (uio_cfg->mode) { - case DRX_UIO_MODE_FIRMWARE0: /* falltrough */ + case DRX_UIO_MODE_FIRMWARE0: /* fall through */ case DRX_UIO_MODE_READWRITE: ext_attr->uio_sma_rx_mode = uio_cfg->mode; break; @@ -3603,7 +3603,7 @@ static int ctrl_set_uio_cfg(struct drx_demod_instance *demod, struct drxuio_cfg if (!ext_attr->has_gpio) return -EIO; switch (uio_cfg->mode) { - case DRX_UIO_MODE_FIRMWARE0: /* falltrough */ + case DRX_UIO_MODE_FIRMWARE0: /* fall through */ case DRX_UIO_MODE_READWRITE: ext_attr->uio_gpio_mode = uio_cfg->mode; break; @@ -3639,7 +3639,7 @@ static int ctrl_set_uio_cfg(struct drx_demod_instance *demod, struct drxuio_cfg } ext_attr->uio_irqn_mode = uio_cfg->mode; break; - case DRX_UIO_MODE_FIRMWARE0: /* falltrough */ + case DRX_UIO_MODE_FIRMWARE0: /* fall through */ default: return -EINVAL; break; diff --git a/drivers/media/dvb-frontends/lgdt330x.c b/drivers/media/dvb-frontends/lgdt330x.c index 10d584ce538d..96807e134886 100644 --- a/drivers/media/dvb-frontends/lgdt330x.c +++ b/drivers/media/dvb-frontends/lgdt330x.c @@ -929,7 +929,7 @@ struct dvb_frontend *lgdt330x_attach(const struct lgdt330x_config *_config, struct i2c_board_info board_info = {}; struct lgdt330x_config config = *_config; - strlcpy(board_info.type, "lgdt330x", sizeof(board_info.type)); + strscpy(board_info.type, "lgdt330x", sizeof(board_info.type)); board_info.addr = demod_address; board_info.platform_data = &config; client = i2c_new_device(i2c, &board_info); diff --git a/drivers/media/dvb-frontends/lnbh29.c b/drivers/media/dvb-frontends/lnbh29.c new file mode 100644 index 000000000000..410bae099c32 --- /dev/null +++ b/drivers/media/dvb-frontends/lnbh29.c @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Driver for LNB supply and control IC STMicroelectronics LNBH29 +// +// Copyright (c) 2018 Socionext Inc. + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> + +#include <media/dvb_frontend.h> +#include "lnbh29.h" + +/** + * struct lnbh29_priv - LNBH29 driver private data + * @i2c: Pointer to the I2C adapter structure + * @i2c_address: I2C address of LNBH29 chip + * @config: Registers configuration + * offset 0: 1st register address, always 0x01 (DATA) + * offset 1: DATA register value + */ +struct lnbh29_priv { + struct i2c_adapter *i2c; + u8 i2c_address; + u8 config[2]; +}; + +#define LNBH29_STATUS_OLF BIT(0) +#define LNBH29_STATUS_OTF BIT(1) +#define LNBH29_STATUS_VMON BIT(2) +#define LNBH29_STATUS_PNG BIT(3) +#define LNBH29_STATUS_PDO BIT(4) +#define LNBH29_VSEL_MASK GENMASK(2, 0) +#define LNBH29_VSEL_0 0x00 +/* Min: 13.188V, Typ: 13.667V, Max:14V */ +#define LNBH29_VSEL_13 0x03 +/* Min: 18.158V, Typ: 18.817V, Max:19.475V */ +#define LNBH29_VSEL_18 0x07 + +static int lnbh29_read_vmon(struct lnbh29_priv *priv) +{ + u8 addr = 0x00; + u8 status[2]; + int ret; + struct i2c_msg msg[2] = { + { + .addr = priv->i2c_address, + .flags = 0, + .len = 1, + .buf = &addr + }, { + .addr = priv->i2c_address, + .flags = I2C_M_RD, + .len = sizeof(status), + .buf = status + } + }; + + ret = i2c_transfer(priv->i2c, msg, 2); + if (ret >= 0 && ret != 2) + ret = -EIO; + if (ret < 0) { + dev_dbg(&priv->i2c->dev, "LNBH29 I2C transfer failed (%d)\n", + ret); + return ret; + } + + if (status[0] & (LNBH29_STATUS_OLF | LNBH29_STATUS_VMON)) { + dev_err(&priv->i2c->dev, + "LNBH29 voltage in failure state, status reg 0x%x\n", + status[0]); + return -EIO; + } + + return 0; +} + +static int lnbh29_set_voltage(struct dvb_frontend *fe, + enum fe_sec_voltage voltage) +{ + struct lnbh29_priv *priv = fe->sec_priv; + u8 data_reg; + int ret; + struct i2c_msg msg = { + .addr = priv->i2c_address, + .flags = 0, + .len = sizeof(priv->config), + .buf = priv->config + }; + + switch (voltage) { + case SEC_VOLTAGE_OFF: + data_reg = LNBH29_VSEL_0; + break; + case SEC_VOLTAGE_13: + data_reg = LNBH29_VSEL_13; + break; + case SEC_VOLTAGE_18: + data_reg = LNBH29_VSEL_18; + break; + default: + return -EINVAL; + } + priv->config[1] &= ~LNBH29_VSEL_MASK; + priv->config[1] |= data_reg; + + ret = i2c_transfer(priv->i2c, &msg, 1); + if (ret >= 0 && ret != 1) + ret = -EIO; + if (ret < 0) { + dev_err(&priv->i2c->dev, "LNBH29 I2C transfer error (%d)\n", + ret); + return ret; + } + + /* Soft-start time (Vout 0V to 18V) is Typ. 6ms. */ + usleep_range(6000, 20000); + + if (voltage == SEC_VOLTAGE_OFF) + return 0; + + return lnbh29_read_vmon(priv); +} + +static void lnbh29_release(struct dvb_frontend *fe) +{ + lnbh29_set_voltage(fe, SEC_VOLTAGE_OFF); + kfree(fe->sec_priv); + fe->sec_priv = NULL; +} + +struct dvb_frontend *lnbh29_attach(struct dvb_frontend *fe, + struct lnbh29_config *cfg, + struct i2c_adapter *i2c) +{ + struct lnbh29_priv *priv; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return NULL; + + priv->i2c_address = (cfg->i2c_address >> 1); + priv->i2c = i2c; + priv->config[0] = 0x01; + priv->config[1] = cfg->data_config; + fe->sec_priv = priv; + + if (lnbh29_set_voltage(fe, SEC_VOLTAGE_OFF)) { + dev_err(&i2c->dev, "no LNBH29 found at I2C addr 0x%02x\n", + priv->i2c_address); + kfree(priv); + fe->sec_priv = NULL; + return NULL; + } + + fe->ops.release_sec = lnbh29_release; + fe->ops.set_voltage = lnbh29_set_voltage; + + dev_info(&i2c->dev, "LNBH29 attached at I2C addr 0x%02x\n", + priv->i2c_address); + + return fe; +} +EXPORT_SYMBOL(lnbh29_attach); + +MODULE_AUTHOR("Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>"); +MODULE_DESCRIPTION("STMicroelectronics LNBH29 driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/dvb-frontends/lnbh29.h b/drivers/media/dvb-frontends/lnbh29.h new file mode 100644 index 000000000000..6179921520d9 --- /dev/null +++ b/drivers/media/dvb-frontends/lnbh29.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Driver for LNB supply and control IC STMicroelectronics LNBH29 + * + * Copyright (c) 2018 Socionext Inc. + */ + +#ifndef LNBH29_H +#define LNBH29_H + +#include <linux/i2c.h> +#include <linux/dvb/frontend.h> + +/* Using very low E.S.R. capacitors or ceramic caps */ +#define LNBH29_DATA_COMP BIT(3) + +struct lnbh29_config { + u8 i2c_address; + u8 data_config; +}; + +#if IS_REACHABLE(CONFIG_DVB_LNBH29) +struct dvb_frontend *lnbh29_attach(struct dvb_frontend *fe, + struct lnbh29_config *cfg, + struct i2c_adapter *i2c); +#else +static inline struct dvb_frontend *lnbh29_attach(struct dvb_frontend *fe, + struct lnbh29_config *cfg, + struct i2c_adapter *i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif + +#endif diff --git a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c index dffd2d4bf1c8..123f2a33738b 100644 --- a/drivers/media/dvb-frontends/m88ds3103.c +++ b/drivers/media/dvb-frontends/m88ds3103.c @@ -1284,7 +1284,7 @@ struct dvb_frontend *m88ds3103_attach(const struct m88ds3103_config *cfg, pdata.attach_in_use = true; memset(&board_info, 0, sizeof(board_info)); - strlcpy(board_info.type, "m88ds3103", I2C_NAME_SIZE); + strscpy(board_info.type, "m88ds3103", I2C_NAME_SIZE); board_info.addr = cfg->i2c_addr; board_info.platform_data = &pdata; client = i2c_new_device(i2c, &board_info); diff --git a/drivers/media/dvb-frontends/mt312.c b/drivers/media/dvb-frontends/mt312.c index aad07adda37d..03e74a729168 100644 --- a/drivers/media/dvb-frontends/mt312.c +++ b/drivers/media/dvb-frontends/mt312.c @@ -815,17 +815,20 @@ struct dvb_frontend *mt312_attach(const struct mt312_config *config, switch (state->id) { case ID_VP310: - strcpy(state->frontend.ops.info.name, "Zarlink VP310 DVB-S"); + strscpy(state->frontend.ops.info.name, "Zarlink VP310 DVB-S", + sizeof(state->frontend.ops.info.name)); state->xtal = MT312_PLL_CLK; state->freq_mult = 9; break; case ID_MT312: - strcpy(state->frontend.ops.info.name, "Zarlink MT312 DVB-S"); + strscpy(state->frontend.ops.info.name, "Zarlink MT312 DVB-S", + sizeof(state->frontend.ops.info.name)); state->xtal = MT312_PLL_CLK; state->freq_mult = 6; break; case ID_ZL10313: - strcpy(state->frontend.ops.info.name, "Zarlink ZL10313 DVB-S"); + strscpy(state->frontend.ops.info.name, "Zarlink ZL10313 DVB-S", + sizeof(state->frontend.ops.info.name)); state->xtal = MT312_PLL_CLK_10_111; state->freq_mult = 9; break; diff --git a/drivers/media/dvb-frontends/mxl5xx.c b/drivers/media/dvb-frontends/mxl5xx.c index 295f37d5f10e..6191315f5970 100644 --- a/drivers/media/dvb-frontends/mxl5xx.c +++ b/drivers/media/dvb-frontends/mxl5xx.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Driver for the MaxLinear MxL5xx family of tuners/demods * @@ -17,7 +18,6 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * */ #include <linux/kernel.h> @@ -739,6 +739,7 @@ static int get_frontend(struct dvb_frontend *fe, default: break; } + /* Fall through */ case SYS_DVBS: switch ((enum MXL_HYDRA_MODULATION_E) reg_data[DMD_MODULATION_SCHEME_ADDR]) { @@ -1893,4 +1894,4 @@ EXPORT_SYMBOL_GPL(mxl5xx_attach); MODULE_DESCRIPTION("MaxLinear MxL5xx DVB-S/S2 tuner-demodulator driver"); MODULE_AUTHOR("Ralph and Marcus Metzler, Metzler Brothers Systementwicklung GbR"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/dvb-frontends/mxl5xx.h b/drivers/media/dvb-frontends/mxl5xx.h index ad4c21846800..706a2f5d8f97 100644 --- a/drivers/media/dvb-frontends/mxl5xx.h +++ b/drivers/media/dvb-frontends/mxl5xx.h @@ -1,3 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Driver for the MaxLinear MxL5xx family of tuners/demods + * + * Copyright (C) 2014-2015 Ralph Metzler <rjkm@metzlerbros.de> + * Marcus Metzler <mocm@metzlerbros.de> + * developed for Digital Devices GmbH + * + * based on code: + * Copyright (c) 2011-2013 MaxLinear, Inc. All rights reserved + * which was released under GPL V2 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + #ifndef _MXL5XX_H_ #define _MXL5XX_H_ diff --git a/drivers/media/dvb-frontends/mxl5xx_defs.h b/drivers/media/dvb-frontends/mxl5xx_defs.h index fd9e61e0188f..1442af8dc176 100644 --- a/drivers/media/dvb-frontends/mxl5xx_defs.h +++ b/drivers/media/dvb-frontends/mxl5xx_defs.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Defines for the Maxlinear MX58x family of tuners/demods * diff --git a/drivers/media/dvb-frontends/mxl5xx_regs.h b/drivers/media/dvb-frontends/mxl5xx_regs.h index 5001dafe1ba8..86d5317eba7a 100644 --- a/drivers/media/dvb-frontends/mxl5xx_regs.h +++ b/drivers/media/dvb-frontends/mxl5xx_regs.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (c) 2011-2013 MaxLinear, Inc. All rights reserved * diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.c b/drivers/media/dvb-frontends/rtl2832_sdr.c index d448d9d4879c..8ef91b1598e3 100644 --- a/drivers/media/dvb-frontends/rtl2832_sdr.c +++ b/drivers/media/dvb-frontends/rtl2832_sdr.c @@ -439,8 +439,8 @@ static int rtl2832_sdr_querycap(struct file *file, void *fh, dev_dbg(&pdev->dev, "\n"); - strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver)); - strlcpy(cap->card, dev->vdev.name, sizeof(cap->card)); + strscpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver)); + strscpy(cap->card, dev->vdev.name, sizeof(cap->card)); usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); cap->device_caps = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_STREAMING | V4L2_CAP_READWRITE | V4L2_CAP_TUNER; @@ -976,7 +976,7 @@ static int rtl2832_sdr_g_tuner(struct file *file, void *priv, dev_dbg(&pdev->dev, "index=%d type=%d\n", v->index, v->type); if (v->index == 0) { - strlcpy(v->name, "ADC: Realtek RTL2832", sizeof(v->name)); + strscpy(v->name, "ADC: Realtek RTL2832", sizeof(v->name)); v->type = V4L2_TUNER_ADC; v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS; v->rangelow = 300000; @@ -986,7 +986,7 @@ static int rtl2832_sdr_g_tuner(struct file *file, void *priv, V4L2_SUBDEV_HAS_OP(dev->v4l2_subdev, tuner, g_tuner)) { ret = v4l2_subdev_call(dev->v4l2_subdev, tuner, g_tuner, v); } else if (v->index == 1) { - strlcpy(v->name, "RF: <unknown>", sizeof(v->name)); + strscpy(v->name, "RF: <unknown>", sizeof(v->name)); v->type = V4L2_TUNER_RF; v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS; v->rangelow = 50000000; @@ -1133,7 +1133,7 @@ static int rtl2832_sdr_enum_fmt_sdr_cap(struct file *file, void *priv, if (f->index >= dev->num_formats) return -EINVAL; - strlcpy(f->description, formats[f->index].name, sizeof(f->description)); + strscpy(f->description, formats[f->index].name, sizeof(f->description)); f->pixelformat = formats[f->index].pixelformat; return 0; diff --git a/drivers/media/dvb-frontends/s5h1420.c b/drivers/media/dvb-frontends/s5h1420.c index a65cdf8e8cd9..c63b56f7fc14 100644 --- a/drivers/media/dvb-frontends/s5h1420.c +++ b/drivers/media/dvb-frontends/s5h1420.c @@ -912,7 +912,7 @@ struct dvb_frontend *s5h1420_attach(const struct s5h1420_config *config, state->frontend.demodulator_priv = state; /* create tuner i2c adapter */ - strlcpy(state->tuner_i2c_adapter.name, "S5H1420-PN1010 tuner I2C bus", + strscpy(state->tuner_i2c_adapter.name, "S5H1420-PN1010 tuner I2C bus", sizeof(state->tuner_i2c_adapter.name)); state->tuner_i2c_adapter.algo = &s5h1420_tuner_i2c_algo; state->tuner_i2c_adapter.algo_data = NULL; diff --git a/drivers/media/dvb-frontends/stv0910.c b/drivers/media/dvb-frontends/stv0910.c index 4c86073f1a8d..fc2440d8af36 100644 --- a/drivers/media/dvb-frontends/stv0910.c +++ b/drivers/media/dvb-frontends/stv0910.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Driver for the ST STV0910 DVB-S/S2 demodulator. * @@ -1839,4 +1840,4 @@ EXPORT_SYMBOL_GPL(stv0910_attach); MODULE_DESCRIPTION("ST STV0910 multistandard frontend driver"); MODULE_AUTHOR("Ralph and Marcus Metzler, Manfred Voelkel"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/dvb-frontends/stv0910.h b/drivers/media/dvb-frontends/stv0910.h index f37171b7a2de..24ecc6902235 100644 --- a/drivers/media/dvb-frontends/stv0910.h +++ b/drivers/media/dvb-frontends/stv0910.h @@ -1,3 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Driver for the ST STV0910 DVB-S/S2 demodulator. + * + * Copyright (C) 2014-2015 Ralph Metzler <rjkm@metzlerbros.de> + * Marcus Metzler <mocm@metzlerbros.de> + * developed for Digital Devices GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 only, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + #ifndef _STV0910_H_ #define _STV0910_H_ diff --git a/drivers/media/dvb-frontends/stv0910_regs.h b/drivers/media/dvb-frontends/stv0910_regs.h index f0eb915090bd..448c89b8cd7c 100644 --- a/drivers/media/dvb-frontends/stv0910_regs.h +++ b/drivers/media/dvb-frontends/stv0910_regs.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * @DVB-S/DVB-S2 STMicroelectronics STV0900 register definitions * Author Manfred Voelkel, August 2013 diff --git a/drivers/media/dvb-frontends/stv6111.c b/drivers/media/dvb-frontends/stv6111.c index 0cf460111acb..d5035dac4574 100644 --- a/drivers/media/dvb-frontends/stv6111.c +++ b/drivers/media/dvb-frontends/stv6111.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Driver for the ST STV6111 tuner * @@ -11,7 +12,6 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * */ #include <linux/kernel.h> @@ -687,4 +687,4 @@ EXPORT_SYMBOL_GPL(stv6111_attach); MODULE_DESCRIPTION("ST STV6111 satellite tuner driver"); MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/dvb-frontends/stv6111.h b/drivers/media/dvb-frontends/stv6111.h index 5bc1228dc9bd..49e821ac9954 100644 --- a/drivers/media/dvb-frontends/stv6111.h +++ b/drivers/media/dvb-frontends/stv6111.h @@ -1,3 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Driver for the ST STV6111 tuner + * + * Copyright (C) 2014 Digital Devices GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 only, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + #ifndef _STV6111_H_ #define _STV6111_H_ diff --git a/drivers/media/dvb-frontends/tc90522.c b/drivers/media/dvb-frontends/tc90522.c index 2ad81a438d6a..849d63dbc279 100644 --- a/drivers/media/dvb-frontends/tc90522.c +++ b/drivers/media/dvb-frontends/tc90522.c @@ -781,7 +781,7 @@ static int tc90522_probe(struct i2c_client *client, adap->owner = THIS_MODULE; adap->algo = &tc90522_tuner_i2c_algo; adap->dev.parent = &client->dev; - strlcpy(adap->name, "tc90522_sub", sizeof(adap->name)); + strscpy(adap->name, "tc90522_sub", sizeof(adap->name)); i2c_set_adapdata(adap, state); ret = i2c_add_adapter(adap); if (ret < 0) diff --git a/drivers/media/dvb-frontends/ts2020.c b/drivers/media/dvb-frontends/ts2020.c index 3e3e40878633..e5cd2cd414f4 100644 --- a/drivers/media/dvb-frontends/ts2020.c +++ b/drivers/media/dvb-frontends/ts2020.c @@ -525,7 +525,7 @@ struct dvb_frontend *ts2020_attach(struct dvb_frontend *fe, pdata.attach_in_use = true; memset(&board_info, 0, sizeof(board_info)); - strlcpy(board_info.type, "ts2020", I2C_NAME_SIZE); + strscpy(board_info.type, "ts2020", I2C_NAME_SIZE); board_info.addr = config->tuner_address; board_info.platform_data = &pdata; client = i2c_new_device(i2c, &board_info); diff --git a/drivers/media/dvb-frontends/zd1301_demod.c b/drivers/media/dvb-frontends/zd1301_demod.c index 84a2b25a574a..212f9328cea8 100644 --- a/drivers/media/dvb-frontends/zd1301_demod.c +++ b/drivers/media/dvb-frontends/zd1301_demod.c @@ -499,7 +499,8 @@ static int zd1301_demod_probe(struct platform_device *pdev) goto err_kfree; /* Create I2C adapter */ - strlcpy(dev->adapter.name, "ZyDAS ZD1301 demod", sizeof(dev->adapter.name)); + strscpy(dev->adapter.name, "ZyDAS ZD1301 demod", + sizeof(dev->adapter.name)); dev->adapter.algo = &zd1301_demod_i2c_algorithm; dev->adapter.algo_data = NULL; dev->adapter.dev.parent = pdev->dev.parent; diff --git a/drivers/media/dvb-frontends/zl10039.c b/drivers/media/dvb-frontends/zl10039.c index 6293bd920fa6..333e4a1da13b 100644 --- a/drivers/media/dvb-frontends/zl10039.c +++ b/drivers/media/dvb-frontends/zl10039.c @@ -288,8 +288,9 @@ struct dvb_frontend *zl10039_attach(struct dvb_frontend *fe, state->id = state->id & 0x0f; switch (state->id) { case ID_ZL10039: - strcpy(fe->ops.tuner_ops.info.name, - "Zarlink ZL10039 DVB-S tuner"); + strscpy(fe->ops.tuner_ops.info.name, + "Zarlink ZL10039 DVB-S tuner", + sizeof(fe->ops.tuner_ops.info.name)); break; default: dprintk("Chip ID=%x does not match a known type\n", state->id); diff --git a/drivers/media/firewire/firedtv-fe.c b/drivers/media/firewire/firedtv-fe.c index 69087ae6c1d0..683957885ac4 100644 --- a/drivers/media/firewire/firedtv-fe.c +++ b/drivers/media/firewire/firedtv-fe.c @@ -247,7 +247,7 @@ void fdtv_frontend_init(struct firedtv *fdtv, const char *name) dev_err(fdtv->device, "no frontend for model type %d\n", fdtv->type); } - strcpy(fi->name, name); + strscpy(fi->name, name, sizeof(fi->name)); fdtv->fe.dvb = &fdtv->adapter; fdtv->fe.sec_priv = fdtv; diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 82af97430e5b..704af210e270 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -614,6 +614,28 @@ config VIDEO_IMX274 This is a V4L2 sensor driver for the Sony IMX274 CMOS image sensor. +config VIDEO_IMX319 + tristate "Sony IMX319 sensor support" + depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API + depends on MEDIA_CAMERA_SUPPORT + help + This is a Video4Linux2 sensor driver for the Sony + IMX319 camera. + + To compile this driver as a module, choose M here: the + module will be called imx319. + +config VIDEO_IMX355 + tristate "Sony IMX355 sensor support" + depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API + depends on MEDIA_CAMERA_SUPPORT + help + This is a Video4Linux2 sensor driver for the Sony + IMX355 camera. + + To compile this driver as a module, choose M here: the + module will be called imx355. + config VIDEO_OV2640 tristate "OmniVision OV2640 sensor support" depends on VIDEO_V4L2 && I2C @@ -747,6 +769,7 @@ config VIDEO_OV772X tristate "OmniVision OV772x sensor support" depends on I2C && VIDEO_V4L2 depends on MEDIA_CAMERA_SUPPORT + select REGMAP_SCCB ---help--- This is a Video4Linux2 sensor driver for the OmniVision OV772x camera. @@ -786,6 +809,7 @@ config VIDEO_OV7740 config VIDEO_OV9650 tristate "OmniVision OV9650/OV9652 sensor support" depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API + select REGMAP_SCCB ---help--- This is a V4L2 sensor driver for the Omnivision OV9650 and OV9652 camera sensors. diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index a94eb03d10d4..260d4d9ec2a1 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -108,5 +108,7 @@ obj-$(CONFIG_VIDEO_OV2659) += ov2659.o obj-$(CONFIG_VIDEO_TC358743) += tc358743.o obj-$(CONFIG_VIDEO_IMX258) += imx258.o obj-$(CONFIG_VIDEO_IMX274) += imx274.o +obj-$(CONFIG_VIDEO_IMX319) += imx319.o +obj-$(CONFIG_VIDEO_IMX355) += imx355.o obj-$(CONFIG_SDR_MAX2175) += max2175.o diff --git a/drivers/media/i2c/ad5820.c b/drivers/media/i2c/ad5820.c index 034ebf754007..907323f0ca3b 100644 --- a/drivers/media/i2c/ad5820.c +++ b/drivers/media/i2c/ad5820.c @@ -317,7 +317,7 @@ static int ad5820_probe(struct i2c_client *client, v4l2_i2c_subdev_init(&coil->subdev, client, &ad5820_ops); coil->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; coil->subdev.internal_ops = &ad5820_internal_ops; - strcpy(coil->subdev.name, "ad5820 focus"); + strscpy(coil->subdev.name, "ad5820 focus", sizeof(coil->subdev.name)); ret = media_entity_pads_init(&coil->subdev.entity, 0, NULL); if (ret < 0) diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index de10367d550b..99697baad2ea 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0 /* * adv7180.c Analog Devices ADV7180 video decoder driver * Copyright (c) 2009 Intel Corporation * Copyright (C) 2013 Cogent Embedded, Inc. * Copyright (C) 2013 Renesas Solutions Corp. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ - #include <linux/module.h> #include <linux/init.h> #include <linux/errno.h> @@ -761,7 +752,7 @@ static int adv7180_g_mbus_config(struct v4l2_subdev *sd, struct adv7180_state *state = to_state(sd); if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) { - cfg->type = V4L2_MBUS_CSI2; + cfg->type = V4L2_MBUS_CSI2_DPHY; cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; diff --git a/drivers/media/i2c/adv748x/adv748x-afe.c b/drivers/media/i2c/adv748x/adv748x-afe.c index edd25e895e5d..71714634efb0 100644 --- a/drivers/media/i2c/adv748x/adv748x-afe.c +++ b/drivers/media/i2c/adv748x/adv748x-afe.c @@ -1,13 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Driver for Analog Devices ADV748X 8 channel analog front end (AFE) receiver * with standard definition processor (SDP) * * Copyright (C) 2017 Renesas Electronics Corp. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. */ #include <linux/delay.h> @@ -286,7 +282,7 @@ static int adv748x_afe_s_stream(struct v4l2_subdev *sd, int enable) goto unlock; } - ret = adv748x_txb_power(state, enable); + ret = adv748x_tx_power(&state->txb, enable); if (ret) goto unlock; diff --git a/drivers/media/i2c/adv748x/adv748x-core.c b/drivers/media/i2c/adv748x/adv748x-core.c index 6ca88daa0ecd..6854d898fdd1 100644 --- a/drivers/media/i2c/adv748x/adv748x-core.c +++ b/drivers/media/i2c/adv748x/adv748x-core.c @@ -1,13 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Driver for Analog Devices ADV748X HDMI receiver with AFE * * Copyright (C) 2017 Renesas Electronics Corp. * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * * Authors: * Koji Matsuoka <koji.matsuoka.xm@renesas.com> * Niklas Söderlund <niklas.soderlund@ragnatech.se> @@ -285,40 +281,23 @@ static const struct adv748x_reg_value adv748x_power_down_txb_1lane[] = { {ADV748X_PAGE_TXB, 0x31, 0x82}, /* ADI Required Write */ {ADV748X_PAGE_TXB, 0x1e, 0x00}, /* ADI Required Write */ - {ADV748X_PAGE_TXB, 0x00, 0x81}, /* Enable 4-lane MIPI */ + {ADV748X_PAGE_TXB, 0x00, 0x81}, /* Enable 1-lane MIPI */ {ADV748X_PAGE_TXB, 0xda, 0x01}, /* i2c_mipi_pll_en - 1'b1 */ {ADV748X_PAGE_TXB, 0xc1, 0x3b}, /* ADI Required Write */ {ADV748X_PAGE_EOR, 0xff, 0xff} /* End of register table */ }; -int adv748x_txa_power(struct adv748x_state *state, bool on) +int adv748x_tx_power(struct adv748x_csi2 *tx, bool on) { + struct adv748x_state *state = tx->state; + const struct adv748x_reg_value *reglist; int val; - val = txa_read(state, ADV748X_CSI_FS_AS_LS); - if (val < 0) - return val; - - /* - * This test against BIT(6) is not documented by the datasheet, but was - * specified in the downstream driver. - * Track with a WARN_ONCE to determine if it is ever set by HW. - */ - WARN_ONCE((on && val & ADV748X_CSI_FS_AS_LS_UNKNOWN), - "Enabling with unknown bit set"); + if (!is_tx_enabled(tx)) + return 0; - if (on) - return adv748x_write_regs(state, adv748x_power_up_txa_4lane); - - return adv748x_write_regs(state, adv748x_power_down_txa_4lane); -} - -int adv748x_txb_power(struct adv748x_state *state, bool on) -{ - int val; - - val = txb_read(state, ADV748X_CSI_FS_AS_LS); + val = tx_read(tx, ADV748X_CSI_FS_AS_LS); if (val < 0) return val; @@ -331,9 +310,13 @@ int adv748x_txb_power(struct adv748x_state *state, bool on) "Enabling with unknown bit set"); if (on) - return adv748x_write_regs(state, adv748x_power_up_txb_1lane); + reglist = is_txa(tx) ? adv748x_power_up_txa_4lane : + adv748x_power_up_txb_1lane; + else + reglist = is_txa(tx) ? adv748x_power_down_txa_4lane : + adv748x_power_down_txb_1lane; - return adv748x_write_regs(state, adv748x_power_down_txb_1lane); + return adv748x_write_regs(state, reglist); } /* ----------------------------------------------------------------------------- @@ -399,8 +382,6 @@ static const struct adv748x_reg_value adv748x_init_txa_4lane[] = { {ADV748X_PAGE_IO, 0x0c, 0xe0}, /* Enable LLC_DLL & Double LLC Timing */ {ADV748X_PAGE_IO, 0x0e, 0xdd}, /* LLC/PIX/SPI PINS TRISTATED AUD */ - /* Outputs Enabled */ - {ADV748X_PAGE_IO, 0x10, 0xa0}, /* Enable 4-lane CSI Tx & Pixel Port */ {ADV748X_PAGE_TXA, 0x00, 0x84}, /* Enable 4-lane MIPI */ {ADV748X_PAGE_TXA, 0x00, 0xa4}, /* Set Auto DPHY Timing */ @@ -454,10 +435,6 @@ static const struct adv748x_reg_value adv748x_init_txb_1lane[] = { {ADV748X_PAGE_SDP, 0x31, 0x12}, /* ADI Required Write */ {ADV748X_PAGE_SDP, 0xe6, 0x4f}, /* V bit end pos manually in NTSC */ - /* Enable 1-Lane MIPI Tx, */ - /* enable pixel output and route SD through Pixel port */ - {ADV748X_PAGE_IO, 0x10, 0x70}, - {ADV748X_PAGE_TXB, 0x00, 0x81}, /* Enable 1-lane MIPI */ {ADV748X_PAGE_TXB, 0x00, 0xa1}, /* Set Auto DPHY Timing */ {ADV748X_PAGE_TXB, 0xd2, 0x40}, /* ADI Required Write */ @@ -482,6 +459,7 @@ static const struct adv748x_reg_value adv748x_init_txb_1lane[] = { static int adv748x_reset(struct adv748x_state *state) { int ret; + u8 regval = 0; ret = adv748x_write_regs(state, adv748x_sw_reset); if (ret < 0) @@ -496,22 +474,24 @@ static int adv748x_reset(struct adv748x_state *state) if (ret) return ret; - adv748x_txa_power(state, 0); + adv748x_tx_power(&state->txa, 0); /* Init and power down TXB */ ret = adv748x_write_regs(state, adv748x_init_txb_1lane); if (ret) return ret; - adv748x_txb_power(state, 0); + adv748x_tx_power(&state->txb, 0); /* Disable chip powerdown & Enable HDMI Rx block */ io_write(state, ADV748X_IO_PD, ADV748X_IO_PD_RX_EN); - /* Enable 4-lane CSI Tx & Pixel Port */ - io_write(state, ADV748X_IO_10, ADV748X_IO_10_CSI4_EN | - ADV748X_IO_10_CSI1_EN | - ADV748X_IO_10_PIX_OUT_EN); + /* Conditionally enable TXa and TXb. */ + if (is_tx_enabled(&state->txa)) + regval |= ADV748X_IO_10_CSI4_EN; + if (is_tx_enabled(&state->txb)) + regval |= ADV748X_IO_10_CSI1_EN; + io_write(state, ADV748X_IO_10, regval); /* Use vid_std and v_freq as freerun resolution for CP */ cp_clrset(state, ADV748X_CP_CLMP_POS, ADV748X_CP_CLMP_POS_DIS_AUTO, @@ -569,7 +549,8 @@ static int adv748x_parse_dt(struct adv748x_state *state) { struct device_node *ep_np = NULL; struct of_endpoint ep; - bool found = false; + bool out_found = false; + bool in_found = false; for_each_endpoint_of_node(state->dev->of_node, ep_np) { of_graph_parse_endpoint(ep_np, &ep); @@ -592,10 +573,17 @@ static int adv748x_parse_dt(struct adv748x_state *state) of_node_get(ep_np); state->endpoints[ep.port] = ep_np; - found = true; + /* + * At least one input endpoint and one output endpoint shall + * be defined. + */ + if (ep.port < ADV748X_PORT_TXA) + in_found = true; + else + out_found = true; } - return found ? 0 : -ENODEV; + return in_found && out_found ? 0 : -ENODEV; } static void adv748x_dt_cleanup(struct adv748x_state *state) @@ -627,6 +615,17 @@ static int adv748x_probe(struct i2c_client *client, state->i2c_clients[ADV748X_PAGE_IO] = client; i2c_set_clientdata(client, state); + /* + * We can not use container_of to get back to the state with two TXs; + * Initialize the TXs's fields unconditionally on the endpoint + * presence to access them later. + */ + state->txa.state = state->txb.state = state; + state->txa.page = ADV748X_PAGE_TXA; + state->txb.page = ADV748X_PAGE_TXB; + state->txa.port = ADV748X_PORT_TXA; + state->txb.port = ADV748X_PORT_TXB; + /* Discover and process ports declared by the Device tree endpoints */ ret = adv748x_parse_dt(state); if (ret) { @@ -755,4 +754,4 @@ module_i2c_driver(adv748x_driver); MODULE_AUTHOR("Kieran Bingham <kieran.bingham@ideasonboard.com>"); MODULE_DESCRIPTION("ADV748X video decoder"); -MODULE_LICENSE("GPL v2"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/i2c/adv748x/adv748x-csi2.c b/drivers/media/i2c/adv748x/adv748x-csi2.c index 469be87a3761..6ce21542ed48 100644 --- a/drivers/media/i2c/adv748x/adv748x-csi2.c +++ b/drivers/media/i2c/adv748x/adv748x-csi2.c @@ -1,12 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Driver for Analog Devices ADV748X CSI-2 Transmitter * * Copyright (C) 2017 Renesas Electronics Corp. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. */ #include <linux/module.h> @@ -18,11 +14,6 @@ #include "adv748x.h" -static bool is_txa(struct adv748x_csi2 *tx) -{ - return tx == &tx->state->txa; -} - static int adv748x_csi2_set_virtual_channel(struct adv748x_csi2 *tx, unsigned int vc) { @@ -87,15 +78,15 @@ static int adv748x_csi2_registered(struct v4l2_subdev *sd) * * Link HDMI->TXA, and AFE->TXB directly. */ - if (is_txa(tx)) { + if (is_txa(tx) && is_hdmi_enabled(state)) return adv748x_csi2_register_link(tx, sd->v4l2_dev, &state->hdmi.sd, ADV748X_HDMI_SOURCE); - } else { + if (!is_txa(tx) && is_afe_enabled(state)) return adv748x_csi2_register_link(tx, sd->v4l2_dev, &state->afe.sd, ADV748X_AFE_SOURCE); - } + return 0; } static const struct v4l2_subdev_internal_ops adv748x_csi2_internal_ops = { @@ -266,19 +257,10 @@ static int adv748x_csi2_init_controls(struct adv748x_csi2 *tx) int adv748x_csi2_init(struct adv748x_state *state, struct adv748x_csi2 *tx) { - struct device_node *ep; int ret; - /* We can not use container_of to get back to the state with two TXs */ - tx->state = state; - tx->page = is_txa(tx) ? ADV748X_PAGE_TXA : ADV748X_PAGE_TXB; - - ep = state->endpoints[is_txa(tx) ? ADV748X_PORT_TXA : ADV748X_PORT_TXB]; - if (!ep) { - adv_err(state, "No endpoint found for %s\n", - is_txa(tx) ? "txa" : "txb"); - return -ENODEV; - } + if (!is_tx_enabled(tx)) + return 0; /* Initialise the virtual channel */ adv748x_csi2_set_virtual_channel(tx, 0); @@ -288,7 +270,7 @@ int adv748x_csi2_init(struct adv748x_state *state, struct adv748x_csi2 *tx) is_txa(tx) ? "txa" : "txb"); /* Ensure that matching is based upon the endpoint fwnodes */ - tx->sd.fwnode = of_fwnode_handle(ep); + tx->sd.fwnode = of_fwnode_handle(state->endpoints[tx->port]); /* Register internal ops for incremental subdev registration */ tx->sd.internal_ops = &adv748x_csi2_internal_ops; @@ -321,6 +303,9 @@ err_free_media: void adv748x_csi2_cleanup(struct adv748x_csi2 *tx) { + if (!is_tx_enabled(tx)) + return; + v4l2_async_unregister_subdev(&tx->sd); media_entity_cleanup(&tx->sd.entity); v4l2_ctrl_handler_free(&tx->ctrl_hdl); diff --git a/drivers/media/i2c/adv748x/adv748x-hdmi.c b/drivers/media/i2c/adv748x/adv748x-hdmi.c index aecc2a84dfec..35d027941482 100644 --- a/drivers/media/i2c/adv748x/adv748x-hdmi.c +++ b/drivers/media/i2c/adv748x/adv748x-hdmi.c @@ -1,12 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Driver for Analog Devices ADV748X HDMI receiver and Component Processor (CP) * * Copyright (C) 2017 Renesas Electronics Corp. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. */ #include <linux/module.h> @@ -362,7 +358,7 @@ static int adv748x_hdmi_s_stream(struct v4l2_subdev *sd, int enable) mutex_lock(&state->mutex); - ret = adv748x_txa_power(state, enable); + ret = adv748x_tx_power(&state->txa, enable); if (ret) goto done; diff --git a/drivers/media/i2c/adv748x/adv748x.h b/drivers/media/i2c/adv748x/adv748x.h index 65f83741277e..39c2fdc3b416 100644 --- a/drivers/media/i2c/adv748x/adv748x.h +++ b/drivers/media/i2c/adv748x/adv748x.h @@ -1,13 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Driver for Analog Devices ADV748X video decoder and HDMI receiver * * Copyright (C) 2017 Renesas Electronics Corp. * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * * Authors: * Koji Matsuoka <koji.matsuoka.xm@renesas.com> * Niklas Söderlund <niklas.soderlund@ragnatech.se> @@ -82,6 +78,7 @@ struct adv748x_csi2 { struct adv748x_state *state; struct v4l2_mbus_framefmt format; unsigned int page; + unsigned int port; struct media_pad pads[ADV748X_CSI2_NR_PADS]; struct v4l2_ctrl_handler ctrl_hdl; @@ -91,6 +88,18 @@ struct adv748x_csi2 { #define notifier_to_csi2(n) container_of(n, struct adv748x_csi2, notifier) #define adv748x_sd_to_csi2(sd) container_of(sd, struct adv748x_csi2, sd) +#define is_tx_enabled(_tx) ((_tx)->state->endpoints[(_tx)->port] != NULL) +#define is_txa(_tx) ((_tx) == &(_tx)->state->txa) +#define is_afe_enabled(_state) \ + ((_state)->endpoints[ADV748X_PORT_AIN0] != NULL || \ + (_state)->endpoints[ADV748X_PORT_AIN1] != NULL || \ + (_state)->endpoints[ADV748X_PORT_AIN2] != NULL || \ + (_state)->endpoints[ADV748X_PORT_AIN3] != NULL || \ + (_state)->endpoints[ADV748X_PORT_AIN4] != NULL || \ + (_state)->endpoints[ADV748X_PORT_AIN5] != NULL || \ + (_state)->endpoints[ADV748X_PORT_AIN6] != NULL || \ + (_state)->endpoints[ADV748X_PORT_AIN7] != NULL) +#define is_hdmi_enabled(_state) ((_state)->endpoints[ADV748X_PORT_HDMI] != NULL) enum adv748x_hdmi_pads { ADV748X_HDMI_SINK, @@ -376,9 +385,6 @@ int adv748x_write_block(struct adv748x_state *state, int client_page, #define cp_write(s, r, v) adv748x_write(s, ADV748X_PAGE_CP, r, v) #define cp_clrset(s, r, m, v) cp_write(s, r, (cp_read(s, r) & ~m) | v) -#define txa_read(s, r) adv748x_read(s, ADV748X_PAGE_TXA, r) -#define txb_read(s, r) adv748x_read(s, ADV748X_PAGE_TXB, r) - #define tx_read(t, r) adv748x_read(t->state, t->page, r) #define tx_write(t, r, v) adv748x_write(t->state, t->page, r, v) @@ -398,8 +404,7 @@ void adv748x_subdev_init(struct v4l2_subdev *sd, struct adv748x_state *state, int adv748x_register_subdevs(struct adv748x_state *state, struct v4l2_device *v4l2_dev); -int adv748x_txa_power(struct adv748x_state *state, bool on); -int adv748x_txb_power(struct adv748x_state *state, bool on); +int adv748x_tx_power(struct adv748x_csi2 *tx, bool on); int adv748x_afe_init(struct adv748x_afe *afe); void adv748x_afe_cleanup(struct adv748x_afe *afe); diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c index 55c2ea0720d9..f3899cc84e27 100644 --- a/drivers/media/i2c/adv7511.c +++ b/drivers/media/i2c/adv7511.c @@ -1355,10 +1355,10 @@ static int adv7511_set_fmt(struct v4l2_subdev *sd, state->xfer_func = format->format.xfer_func; switch (format->format.colorspace) { - case V4L2_COLORSPACE_ADOBERGB: + case V4L2_COLORSPACE_OPRGB: c = HDMI_COLORIMETRY_EXTENDED; - ec = y ? HDMI_EXTENDED_COLORIMETRY_ADOBE_YCC_601 : - HDMI_EXTENDED_COLORIMETRY_ADOBE_RGB; + ec = y ? HDMI_EXTENDED_COLORIMETRY_OPYCC_601 : + HDMI_EXTENDED_COLORIMETRY_OPRGB; break; case V4L2_COLORSPACE_SMPTE170M: c = y ? HDMI_COLORIMETRY_ITU_601 : HDMI_COLORIMETRY_NONE; diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index 668be2bca57a..9eb7c70a7712 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -2284,8 +2284,10 @@ static int adv76xx_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) state->aspect_ratio.numerator = 16; state->aspect_ratio.denominator = 9; - if (!state->edid.present) + if (!state->edid.present) { state->edid.blocks = 0; + cec_phys_addr_invalidate(state->cec_adap); + } v4l2_dbg(2, debug, sd, "%s: clear EDID pad %d, edid.present = 0x%x\n", __func__, edid->pad, state->edid.present); @@ -2295,8 +2297,8 @@ static int adv76xx_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) edid->blocks = 2; return -E2BIG; } - pa = cec_get_edid_phys_addr(edid->edid, edid->blocks * 128, &spa_loc); - err = cec_phys_addr_validate(pa, &pa, NULL); + pa = v4l2_get_edid_phys_addr(edid->edid, edid->blocks * 128, &spa_loc); + err = v4l2_phys_addr_validate(pa, &pa, NULL); if (err) return err; @@ -2474,7 +2476,7 @@ static int adv76xx_log_status(struct v4l2_subdev *sd) "YCbCr Bt.601 (16-235)", "YCbCr Bt.709 (16-235)", "xvYCC Bt.601", "xvYCC Bt.709", "YCbCr Bt.601 (0-255)", "YCbCr Bt.709 (0-255)", - "sYCC", "Adobe YCC 601", "AdobeRGB", "invalid", "invalid", + "sYCC", "opYCC 601", "opRGB", "invalid", "invalid", "invalid", "invalid", "invalid" }; static const char * const rgb_quantization_range_txt[] = { @@ -3093,7 +3095,7 @@ MODULE_DEVICE_TABLE(of, adv76xx_of_id); static int adv76xx_parse_dt(struct adv76xx_state *state) { - struct v4l2_fwnode_endpoint bus_cfg; + struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 }; struct device_node *endpoint; struct device_node *np; unsigned int flags; diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c index 4f8fbdd00e35..4721d49dcf0f 100644 --- a/drivers/media/i2c/adv7842.c +++ b/drivers/media/i2c/adv7842.c @@ -786,11 +786,13 @@ static int edid_write_hdmi_segment(struct v4l2_subdev *sd, u8 port) /* Disable I2C access to internal EDID ram from HDMI DDC ports */ rep_write_and_or(sd, 0x77, 0xf3, 0x00); - if (!state->hdmi_edid.present) + if (!state->hdmi_edid.present) { + cec_phys_addr_invalidate(state->cec_adap); return 0; + } - pa = cec_get_edid_phys_addr(edid, 256, &spa_loc); - err = cec_phys_addr_validate(pa, &pa, NULL); + pa = v4l2_get_edid_phys_addr(edid, 256, &spa_loc); + err = v4l2_phys_addr_validate(pa, &pa, NULL); if (err) return err; @@ -1525,6 +1527,7 @@ static void adv7842_fill_optional_dv_timings_fields(struct v4l2_subdev *sd, v4l2_find_dv_timings_cap(timings, adv7842_get_dv_timings_cap(sd), is_digital_input(sd) ? 250000 : 1000000, adv7842_check_dv_timings, NULL); + timings->bt.flags |= V4L2_DV_FL_CAN_DETECT_REDUCED_FPS; } static int adv7842_query_dv_timings(struct v4l2_subdev *sd, @@ -1596,6 +1599,14 @@ static int adv7842_query_dv_timings(struct v4l2_subdev *sd, bt->il_vbackporch = 0; } adv7842_fill_optional_dv_timings_fields(sd, timings); + if ((timings->bt.flags & V4L2_DV_FL_CAN_REDUCE_FPS) && + freq < bt->pixelclock) { + u32 reduced_freq = ((u32)bt->pixelclock / 1001) * 1000; + u32 delta_freq = abs(freq - reduced_freq); + + if (delta_freq < ((u32)bt->pixelclock - reduced_freq) / 2) + timings->bt.flags |= V4L2_DV_FL_REDUCED_FPS; + } } else { /* find format * Since LCVS values are inaccurate [REF_03, p. 339-340], diff --git a/drivers/media/i2c/ak881x.c b/drivers/media/i2c/ak881x.c index 16682c8477d1..30f9db1351b9 100644 --- a/drivers/media/i2c/ak881x.c +++ b/drivers/media/i2c/ak881x.c @@ -136,7 +136,6 @@ static int ak881x_get_selection(struct v4l2_subdev *sd, switch (sel->target) { case V4L2_SEL_TGT_CROP_BOUNDS: - case V4L2_SEL_TGT_CROP_DEFAULT: sel->r.left = 0; sel->r.top = 0; sel->r.width = 720; diff --git a/drivers/media/i2c/cs53l32a.c b/drivers/media/i2c/cs53l32a.c index fd70fe2130a1..ef4bdbae4531 100644 --- a/drivers/media/i2c/cs53l32a.c +++ b/drivers/media/i2c/cs53l32a.c @@ -149,7 +149,7 @@ static int cs53l32a_probe(struct i2c_client *client, return -EIO; if (!id) - strlcpy(client->name, "cs53l32a", sizeof(client->name)); + strscpy(client->name, "cs53l32a", sizeof(client->name)); v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); diff --git a/drivers/media/i2c/cx25840/cx25840-ir.c b/drivers/media/i2c/cx25840/cx25840-ir.c index ad7f66c7aac8..69cdc09981af 100644 --- a/drivers/media/i2c/cx25840/cx25840-ir.c +++ b/drivers/media/i2c/cx25840/cx25840-ir.c @@ -701,10 +701,8 @@ static int cx25840_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count, if (v > IR_MAX_DURATION) v = IR_MAX_DURATION; - init_ir_raw_event(&p->ir_core_data); - p->ir_core_data.pulse = u; - p->ir_core_data.duration = v; - p->ir_core_data.timeout = w; + p->ir_core_data = (struct ir_raw_event) + { .pulse = u, .duration = v, .timeout = w }; v4l2_dbg(2, ir_debug, sd, "rx read: %10u ns %s %s\n", v, u ? "mark" : "space", w ? "(timed out)" : ""); diff --git a/drivers/media/i2c/dw9714.c b/drivers/media/i2c/dw9714.c index 91fae01d052b..26d83693a681 100644 --- a/drivers/media/i2c/dw9714.c +++ b/drivers/media/i2c/dw9714.c @@ -169,8 +169,9 @@ static int dw9714_probe(struct i2c_client *client) return 0; err_cleanup: - dw9714_subdev_cleanup(dw9714_dev); - dev_err(&client->dev, "Probe failed: %d\n", rval); + v4l2_ctrl_handler_free(&dw9714_dev->ctrls_vcm); + media_entity_cleanup(&dw9714_dev->sd.entity); + return rval; } diff --git a/drivers/media/i2c/dw9807-vcm.c b/drivers/media/i2c/dw9807-vcm.c index 8ba3920b6e2f..b38a4e6d270d 100644 --- a/drivers/media/i2c/dw9807-vcm.c +++ b/drivers/media/i2c/dw9807-vcm.c @@ -218,7 +218,8 @@ static int dw9807_probe(struct i2c_client *client) return 0; err_cleanup: - dw9807_subdev_cleanup(dw9807_dev); + v4l2_ctrl_handler_free(&dw9807_dev->ctrls_vcm); + media_entity_cleanup(&dw9807_dev->sd.entity); return rval; } @@ -229,7 +230,6 @@ static int dw9807_remove(struct i2c_client *client) struct dw9807_device *dw9807_dev = sd_to_dw9807_vcm(sd); pm_runtime_disable(&client->dev); - pm_runtime_set_suspended(&client->dev); dw9807_subdev_cleanup(dw9807_dev); diff --git a/drivers/media/i2c/imx274.c b/drivers/media/i2c/imx274.c index f8c70f1a34fe..11c69281692e 100644 --- a/drivers/media/i2c/imx274.c +++ b/drivers/media/i2c/imx274.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * imx274.c - IMX274 CMOS Image Sensor driver * @@ -6,18 +7,6 @@ * Leon Luo <leonl@leopardimaging.com> * Edwin Zou <edwinz@leopardimaging.com> * Luca Ceresoli <luca@lucaceresoli.net> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <linux/clk.h> @@ -76,7 +65,7 @@ */ #define IMX274_MIN_EXPOSURE_TIME (4 * 260 / 72) -#define IMX274_DEFAULT_MODE IMX274_BINNING_OFF +#define IMX274_DEFAULT_BINNING IMX274_BINNING_OFF #define IMX274_MAX_WIDTH (3840) #define IMX274_MAX_HEIGHT (2160) #define IMX274_MAX_FRAME_RATE (120) @@ -178,7 +167,7 @@ enum imx274_binning { * @nocpiop: Number of clocks per internal offset period (see "Integration Time * in Each Readout Drive Mode (CSI-2)" in the datasheet) */ -struct imx274_frmfmt { +struct imx274_mode { const struct reg_8 *init_regs; unsigned int bin_ratio; int min_frame_len; @@ -349,20 +338,14 @@ static const struct reg_8 imx274_mode5_1280x720_raw10[] = { */ static const struct reg_8 imx274_start_1[] = { {IMX274_STANDBY_REG, 0x12}, - {IMX274_TABLE_END, 0x00} -}; -/* - * imx274 second step register configuration for - * starting stream - */ -static const struct reg_8 imx274_start_2[] = { - {0x3120, 0xF0}, /* clock settings */ - {0x3121, 0x00}, /* clock settings */ - {0x3122, 0x02}, /* clock settings */ - {0x3129, 0x9C}, /* clock settings */ - {0x312A, 0x02}, /* clock settings */ - {0x312D, 0x02}, /* clock settings */ + /* PLRD: clock settings */ + {0x3120, 0xF0}, + {0x3121, 0x00}, + {0x3122, 0x02}, + {0x3129, 0x9C}, + {0x312A, 0x02}, + {0x312D, 0x02}, {0x310B, 0x00}, @@ -407,20 +390,20 @@ static const struct reg_8 imx274_start_2[] = { }; /* - * imx274 third step register configuration for + * imx274 second step register configuration for * starting stream */ -static const struct reg_8 imx274_start_3[] = { +static const struct reg_8 imx274_start_2[] = { {IMX274_STANDBY_REG, 0x00}, {0x303E, 0x02}, /* SYS_MODE = 2 */ {IMX274_TABLE_END, 0x00} }; /* - * imx274 forth step register configuration for + * imx274 third step register configuration for * starting stream */ -static const struct reg_8 imx274_start_4[] = { +static const struct reg_8 imx274_start_3[] = { {0x30F4, 0x00}, {0x3018, 0xA2}, /* XHS VHS OUTUPT */ {IMX274_TABLE_END, 0x00} @@ -459,7 +442,7 @@ static const struct reg_8 imx274_tp_regs[] = { }; /* nocpiop happens to be the same number for the implemented modes */ -static const struct imx274_frmfmt imx274_formats[] = { +static const struct imx274_mode imx274_modes[] = { { /* mode 1, 4K */ .bin_ratio = 1, @@ -532,7 +515,7 @@ struct stimx274 { struct regmap *regmap; struct gpio_desc *reset_gpio; struct mutex lock; /* mutex lock for operations */ - const struct imx274_frmfmt *mode; + const struct imx274_mode *mode; }; #define IMX274_ROUND(dim, step, flags) \ @@ -666,6 +649,41 @@ static inline int imx274_write_reg(struct stimx274 *priv, u16 addr, u8 val) } /** + * Read a multibyte register. + * + * Uses a bulk read where possible. + * + * @priv: Pointer to device structure + * @addr: Address of the LSB register. Other registers must be + * consecutive, least-to-most significant. + * @val: Pointer to store the register value (cpu endianness) + * @nbytes: Number of bytes to read (range: [1..3]). + * Other bytes are zet to 0. + * + * Return: 0 on success, errors otherwise + */ +static int imx274_read_mbreg(struct stimx274 *priv, u16 addr, u32 *val, + size_t nbytes) +{ + __le32 val_le = 0; + int err; + + err = regmap_bulk_read(priv->regmap, addr, &val_le, nbytes); + if (err) { + dev_err(&priv->client->dev, + "%s : i2c bulk read failed, %x (%zu bytes)\n", + __func__, addr, nbytes); + } else { + *val = le32_to_cpu(val_le); + dev_dbg(&priv->client->dev, + "%s : addr 0x%x, val=0x%x (%zu bytes)\n", + __func__, addr, *val, nbytes); + } + + return err; +} + +/** * Write a multibyte register. * * Uses a bulk write where possible. @@ -674,7 +692,7 @@ static inline int imx274_write_reg(struct stimx274 *priv, u16 addr, u8 val) * @addr: Address of the LSB register. Other registers must be * consecutive, least-to-most significant. * @val: Value to be written to the register (cpu endianness) - * @nbytes: Number of bits to write (range: [1..3]) + * @nbytes: Number of bytes to write (range: [1..3]) */ static int imx274_write_mbreg(struct stimx274 *priv, u16 addr, u32 val, size_t nbytes) @@ -708,10 +726,6 @@ static int imx274_mode_regs(struct stimx274 *priv) if (err) return err; - err = imx274_write_table(priv, imx274_start_2); - if (err) - return err; - err = imx274_write_table(priv, priv->mode->init_regs); return err; @@ -733,7 +747,7 @@ static int imx274_start_stream(struct stimx274 *priv) * give it 1 extra ms for margin */ msleep_range(11); - err = imx274_write_table(priv, imx274_start_3); + err = imx274_write_table(priv, imx274_start_2); if (err) return err; @@ -743,7 +757,7 @@ static int imx274_start_stream(struct stimx274 *priv) * give it 1 extra ms for margin */ msleep_range(8); - err = imx274_write_table(priv, imx274_start_4); + err = imx274_write_table(priv, imx274_start_3); if (err) return err; @@ -881,7 +895,7 @@ static int __imx274_change_compose(struct stimx274 *imx274, const struct v4l2_rect *cur_crop; struct v4l2_mbus_framefmt *tgt_fmt; unsigned int i; - const struct imx274_frmfmt *best_mode = &imx274_formats[0]; + const struct imx274_mode *best_mode = &imx274_modes[0]; int best_goodness = INT_MIN; if (which == V4L2_SUBDEV_FORMAT_TRY) { @@ -892,8 +906,8 @@ static int __imx274_change_compose(struct stimx274 *imx274, tgt_fmt = &imx274->format; } - for (i = 0; i < ARRAY_SIZE(imx274_formats); i++) { - unsigned int ratio = imx274_formats[i].bin_ratio; + for (i = 0; i < ARRAY_SIZE(imx274_modes); i++) { + unsigned int ratio = imx274_modes[i].bin_ratio; int goodness = imx274_binning_goodness( imx274, @@ -903,7 +917,7 @@ static int __imx274_change_compose(struct stimx274 *imx274, if (goodness >= best_goodness) { best_goodness = goodness; - best_mode = &imx274_formats[i]; + best_mode = &imx274_modes[i]; } } @@ -1323,7 +1337,7 @@ static int imx274_s_stream(struct v4l2_subdev *sd, int on) dev_dbg(&imx274->client->dev, "%s : %s, mode index = %td\n", __func__, on ? "Stream Start" : "Stream Stop", - imx274->mode - &imx274_formats[0]); + imx274->mode - &imx274_modes[0]); mutex_lock(&imx274->lock); @@ -1387,37 +1401,17 @@ fail: static int imx274_get_frame_length(struct stimx274 *priv, u32 *val) { int err; - u16 svr; + u32 svr; u32 vmax; - u8 reg_val[3]; - - /* svr */ - err = imx274_read_reg(priv, IMX274_SVR_REG_LSB, ®_val[0]); - if (err) - goto fail; - err = imx274_read_reg(priv, IMX274_SVR_REG_MSB, ®_val[1]); + err = imx274_read_mbreg(priv, IMX274_SVR_REG_LSB, &svr, 2); if (err) goto fail; - svr = (reg_val[1] << IMX274_SHIFT_8_BITS) + reg_val[0]; - - /* vmax */ - err = imx274_read_reg(priv, IMX274_VMAX_REG_3, ®_val[0]); + err = imx274_read_mbreg(priv, IMX274_VMAX_REG_3, &vmax, 3); if (err) goto fail; - err = imx274_read_reg(priv, IMX274_VMAX_REG_2, ®_val[1]); - if (err) - goto fail; - - err = imx274_read_reg(priv, IMX274_VMAX_REG_1, ®_val[2]); - if (err) - goto fail; - - vmax = ((reg_val[2] & IMX274_MASK_LSB_3_BITS) << IMX274_SHIFT_16_BITS) - + (reg_val[1] << IMX274_SHIFT_8_BITS) + reg_val[0]; - *val = vmax * (svr + 1); return 0; @@ -1598,8 +1592,7 @@ fail: static int imx274_set_exposure(struct stimx274 *priv, int val) { int err; - u16 hmax; - u8 reg_val[2]; + u32 hmax; u32 coarse_time; /* exposure time in unit of line (HMAX)*/ dev_dbg(&priv->client->dev, @@ -1607,14 +1600,10 @@ static int imx274_set_exposure(struct stimx274 *priv, int val) /* step 1: convert input exposure_time (val) into number of 1[HMAX] */ - /* obtain HMAX value */ - err = imx274_read_reg(priv, IMX274_HMAX_REG_LSB, ®_val[0]); - if (err) - goto fail; - err = imx274_read_reg(priv, IMX274_HMAX_REG_MSB, ®_val[1]); + err = imx274_read_mbreg(priv, IMX274_HMAX_REG_LSB, &hmax, 2); if (err) goto fail; - hmax = (reg_val[1] << IMX274_SHIFT_8_BITS) + reg_val[0]; + if (hmax == 0) { err = -EINVAL; goto fail; @@ -1749,9 +1738,8 @@ static int imx274_set_frame_interval(struct stimx274 *priv, { int err; u32 frame_length, req_frame_rate; - u16 svr; - u16 hmax; - u8 reg_val[2]; + u32 svr; + u32 hmax; dev_dbg(&priv->client->dev, "%s: input frame interval = %d / %d", __func__, frame_interval.numerator, @@ -1779,25 +1767,17 @@ static int imx274_set_frame_interval(struct stimx274 *priv, * frame_length (i.e. VMAX) = (frame_interval) x 72M /(SVR+1) / HMAX */ - /* SVR */ - err = imx274_read_reg(priv, IMX274_SVR_REG_LSB, ®_val[0]); - if (err) - goto fail; - err = imx274_read_reg(priv, IMX274_SVR_REG_MSB, ®_val[1]); + err = imx274_read_mbreg(priv, IMX274_SVR_REG_LSB, &svr, 2); if (err) goto fail; - svr = (reg_val[1] << IMX274_SHIFT_8_BITS) + reg_val[0]; + dev_dbg(&priv->client->dev, "%s : register SVR = %d\n", __func__, svr); - /* HMAX */ - err = imx274_read_reg(priv, IMX274_HMAX_REG_LSB, ®_val[0]); - if (err) - goto fail; - err = imx274_read_reg(priv, IMX274_HMAX_REG_MSB, ®_val[1]); + err = imx274_read_mbreg(priv, IMX274_HMAX_REG_LSB, &hmax, 2); if (err) goto fail; - hmax = (reg_val[1] << IMX274_SHIFT_8_BITS) + reg_val[0]; + dev_dbg(&priv->client->dev, "%s : register HMAX = %d\n", __func__, hmax); @@ -1871,7 +1851,7 @@ static int imx274_probe(struct i2c_client *client, mutex_init(&imx274->lock); /* initialize format */ - imx274->mode = &imx274_formats[IMX274_DEFAULT_MODE]; + imx274->mode = &imx274_modes[IMX274_DEFAULT_BINNING]; imx274->crop.width = IMX274_MAX_WIDTH; imx274->crop.height = IMX274_MAX_HEIGHT; imx274->format.width = imx274->crop.width / imx274->mode->bin_ratio; @@ -1895,7 +1875,6 @@ static int imx274_probe(struct i2c_client *client, imx274->client = client; sd = &imx274->sd; v4l2_i2c_subdev_init(sd, client, &imx274_subdev_ops); - strlcpy(sd->name, DRIVER_NAME, sizeof(sd->name)); sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; /* initialize subdev media pad */ diff --git a/drivers/media/i2c/imx319.c b/drivers/media/i2c/imx319.c new file mode 100644 index 000000000000..0d3e27812b93 --- /dev/null +++ b/drivers/media/i2c/imx319.c @@ -0,0 +1,2560 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Intel Corporation + +#include <asm/unaligned.h> +#include <linux/acpi.h> +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/pm_runtime.h> +#include <media/v4l2-ctrls.h> +#include <media/v4l2-device.h> +#include <media/v4l2-event.h> +#include <media/v4l2-fwnode.h> + +#define IMX319_REG_MODE_SELECT 0x0100 +#define IMX319_MODE_STANDBY 0x00 +#define IMX319_MODE_STREAMING 0x01 + +/* Chip ID */ +#define IMX319_REG_CHIP_ID 0x0016 +#define IMX319_CHIP_ID 0x0319 + +/* V_TIMING internal */ +#define IMX319_REG_FLL 0x0340 +#define IMX319_FLL_MAX 0xffff + +/* Exposure control */ +#define IMX319_REG_EXPOSURE 0x0202 +#define IMX319_EXPOSURE_MIN 1 +#define IMX319_EXPOSURE_STEP 1 +#define IMX319_EXPOSURE_DEFAULT 0x04f6 + +/* + * the digital control register for all color control looks like: + * +-----------------+------------------+ + * | [7:0] | [15:8] | + * +-----------------+------------------+ + * | 0x020f | 0x020e | + * -------------------------------------- + * it is used to calculate the digital gain times value(integral + fractional) + * the [15:8] bits is the fractional part and [7:0] bits is the integral + * calculation equation is: + * gain value (unit: times) = REG[15:8] + REG[7:0]/0x100 + * Only value in 0x0100 ~ 0x0FFF range is allowed. + * Analog gain use 10 bits in the registers and allowed range is 0 ~ 960 + */ +/* Analog gain control */ +#define IMX319_REG_ANALOG_GAIN 0x0204 +#define IMX319_ANA_GAIN_MIN 0 +#define IMX319_ANA_GAIN_MAX 960 +#define IMX319_ANA_GAIN_STEP 1 +#define IMX319_ANA_GAIN_DEFAULT 0 + +/* Digital gain control */ +#define IMX319_REG_DPGA_USE_GLOBAL_GAIN 0x3ff9 +#define IMX319_REG_DIG_GAIN_GLOBAL 0x020e +#define IMX319_DGTL_GAIN_MIN 256 +#define IMX319_DGTL_GAIN_MAX 4095 +#define IMX319_DGTL_GAIN_STEP 1 +#define IMX319_DGTL_GAIN_DEFAULT 256 + +/* Test Pattern Control */ +#define IMX319_REG_TEST_PATTERN 0x0600 +#define IMX319_TEST_PATTERN_DISABLED 0 +#define IMX319_TEST_PATTERN_SOLID_COLOR 1 +#define IMX319_TEST_PATTERN_COLOR_BARS 2 +#define IMX319_TEST_PATTERN_GRAY_COLOR_BARS 3 +#define IMX319_TEST_PATTERN_PN9 4 + +/* Flip Control */ +#define IMX319_REG_ORIENTATION 0x0101 + +/* default link frequency and external clock */ +#define IMX319_LINK_FREQ_DEFAULT 482400000 +#define IMX319_EXT_CLK 19200000 +#define IMX319_LINK_FREQ_INDEX 0 + +struct imx319_reg { + u16 address; + u8 val; +}; + +struct imx319_reg_list { + u32 num_of_regs; + const struct imx319_reg *regs; +}; + +/* Mode : resolution and related config&values */ +struct imx319_mode { + /* Frame width */ + u32 width; + /* Frame height */ + u32 height; + + /* V-timing */ + u32 fll_def; + u32 fll_min; + + /* H-timing */ + u32 llp; + + /* index of link frequency */ + u32 link_freq_index; + + /* Default register values */ + struct imx319_reg_list reg_list; +}; + +struct imx319_hwcfg { + u32 ext_clk; /* sensor external clk */ + s64 *link_freqs; /* CSI-2 link frequencies */ + unsigned int nr_of_link_freqs; +}; + +struct imx319 { + struct v4l2_subdev sd; + struct media_pad pad; + + struct v4l2_ctrl_handler ctrl_handler; + /* V4L2 Controls */ + struct v4l2_ctrl *link_freq; + struct v4l2_ctrl *pixel_rate; + struct v4l2_ctrl *vblank; + struct v4l2_ctrl *hblank; + struct v4l2_ctrl *exposure; + struct v4l2_ctrl *vflip; + struct v4l2_ctrl *hflip; + + /* Current mode */ + const struct imx319_mode *cur_mode; + + struct imx319_hwcfg *hwcfg; + s64 link_def_freq; /* CSI-2 link default frequency */ + + /* + * Mutex for serialized access: + * Protect sensor set pad format and start/stop streaming safely. + * Protect access to sensor v4l2 controls. + */ + struct mutex mutex; + + /* Streaming on/off */ + bool streaming; +}; + +static const struct imx319_reg imx319_global_regs[] = { + { 0x0136, 0x13 }, + { 0x0137, 0x33 }, + { 0x3c7e, 0x05 }, + { 0x3c7f, 0x07 }, + { 0x4d39, 0x0b }, + { 0x4d41, 0x33 }, + { 0x4d43, 0x0c }, + { 0x4d49, 0x89 }, + { 0x4e05, 0x0b }, + { 0x4e0d, 0x33 }, + { 0x4e0f, 0x0c }, + { 0x4e15, 0x89 }, + { 0x4e49, 0x2a }, + { 0x4e51, 0x33 }, + { 0x4e53, 0x0c }, + { 0x4e59, 0x89 }, + { 0x5601, 0x4f }, + { 0x560b, 0x45 }, + { 0x562f, 0x0a }, + { 0x5643, 0x0a }, + { 0x5645, 0x0c }, + { 0x56ef, 0x51 }, + { 0x586f, 0x33 }, + { 0x5873, 0x89 }, + { 0x5905, 0x33 }, + { 0x5907, 0x89 }, + { 0x590d, 0x33 }, + { 0x590f, 0x89 }, + { 0x5915, 0x33 }, + { 0x5917, 0x89 }, + { 0x5969, 0x1c }, + { 0x596b, 0x72 }, + { 0x5971, 0x33 }, + { 0x5973, 0x89 }, + { 0x5975, 0x33 }, + { 0x5977, 0x89 }, + { 0x5979, 0x1c }, + { 0x597b, 0x72 }, + { 0x5985, 0x33 }, + { 0x5987, 0x89 }, + { 0x5999, 0x1c }, + { 0x599b, 0x72 }, + { 0x59a5, 0x33 }, + { 0x59a7, 0x89 }, + { 0x7485, 0x08 }, + { 0x7487, 0x0c }, + { 0x7489, 0xc7 }, + { 0x748b, 0x8b }, + { 0x9004, 0x09 }, + { 0x9200, 0x6a }, + { 0x9201, 0x22 }, + { 0x9202, 0x6a }, + { 0x9203, 0x23 }, + { 0x9204, 0x5f }, + { 0x9205, 0x23 }, + { 0x9206, 0x5f }, + { 0x9207, 0x24 }, + { 0x9208, 0x5f }, + { 0x9209, 0x26 }, + { 0x920a, 0x5f }, + { 0x920b, 0x27 }, + { 0x920c, 0x5f }, + { 0x920d, 0x29 }, + { 0x920e, 0x5f }, + { 0x920f, 0x2a }, + { 0x9210, 0x5f }, + { 0x9211, 0x2c }, + { 0xbc22, 0x1a }, + { 0xf01f, 0x04 }, + { 0xf021, 0x03 }, + { 0xf023, 0x02 }, + { 0xf03d, 0x05 }, + { 0xf03f, 0x03 }, + { 0xf041, 0x02 }, + { 0xf0af, 0x04 }, + { 0xf0b1, 0x03 }, + { 0xf0b3, 0x02 }, + { 0xf0cd, 0x05 }, + { 0xf0cf, 0x03 }, + { 0xf0d1, 0x02 }, + { 0xf13f, 0x04 }, + { 0xf141, 0x03 }, + { 0xf143, 0x02 }, + { 0xf15d, 0x05 }, + { 0xf15f, 0x03 }, + { 0xf161, 0x02 }, + { 0xf1cf, 0x04 }, + { 0xf1d1, 0x03 }, + { 0xf1d3, 0x02 }, + { 0xf1ed, 0x05 }, + { 0xf1ef, 0x03 }, + { 0xf1f1, 0x02 }, + { 0xf287, 0x04 }, + { 0xf289, 0x03 }, + { 0xf28b, 0x02 }, + { 0xf2a5, 0x05 }, + { 0xf2a7, 0x03 }, + { 0xf2a9, 0x02 }, + { 0xf2b7, 0x04 }, + { 0xf2b9, 0x03 }, + { 0xf2bb, 0x02 }, + { 0xf2d5, 0x05 }, + { 0xf2d7, 0x03 }, + { 0xf2d9, 0x02 }, +}; + +static const struct imx319_reg_list imx319_global_setting = { + .num_of_regs = ARRAY_SIZE(imx319_global_regs), + .regs = imx319_global_regs, +}; + +static const struct imx319_reg mode_3264x2448_regs[] = { + { 0x0112, 0x0a }, + { 0x0113, 0x0a }, + { 0x0114, 0x03 }, + { 0x0342, 0x0f }, + { 0x0343, 0x80 }, + { 0x0340, 0x0c }, + { 0x0341, 0xaa }, + { 0x0344, 0x00 }, + { 0x0345, 0x00 }, + { 0x0346, 0x00 }, + { 0x0347, 0x00 }, + { 0x0348, 0x0c }, + { 0x0349, 0xcf }, + { 0x034a, 0x09 }, + { 0x034b, 0x9f }, + { 0x0220, 0x00 }, + { 0x0221, 0x11 }, + { 0x0381, 0x01 }, + { 0x0383, 0x01 }, + { 0x0385, 0x01 }, + { 0x0387, 0x01 }, + { 0x0900, 0x00 }, + { 0x0901, 0x11 }, + { 0x0902, 0x0a }, + { 0x3140, 0x02 }, + { 0x3141, 0x00 }, + { 0x3f0d, 0x0a }, + { 0x3f14, 0x01 }, + { 0x3f3c, 0x01 }, + { 0x3f4d, 0x01 }, + { 0x3f4c, 0x01 }, + { 0x4254, 0x7f }, + { 0x0401, 0x00 }, + { 0x0404, 0x00 }, + { 0x0405, 0x10 }, + { 0x0408, 0x00 }, + { 0x0409, 0x08 }, + { 0x040a, 0x00 }, + { 0x040b, 0x08 }, + { 0x040c, 0x0c }, + { 0x040d, 0xc0 }, + { 0x040e, 0x09 }, + { 0x040f, 0x90 }, + { 0x034c, 0x0c }, + { 0x034d, 0xc0 }, + { 0x034e, 0x09 }, + { 0x034f, 0x90 }, + { 0x3261, 0x00 }, + { 0x3264, 0x00 }, + { 0x3265, 0x10 }, + { 0x0301, 0x05 }, + { 0x0303, 0x04 }, + { 0x0305, 0x04 }, + { 0x0306, 0x01 }, + { 0x0307, 0x92 }, + { 0x0309, 0x0a }, + { 0x030b, 0x02 }, + { 0x030d, 0x02 }, + { 0x030e, 0x00 }, + { 0x030f, 0xfa }, + { 0x0310, 0x00 }, + { 0x0820, 0x0f }, + { 0x0821, 0x13 }, + { 0x0822, 0x33 }, + { 0x0823, 0x33 }, + { 0x3e20, 0x01 }, + { 0x3e37, 0x00 }, + { 0x3e3b, 0x01 }, + { 0x38a3, 0x01 }, + { 0x38a8, 0x00 }, + { 0x38a9, 0x00 }, + { 0x38aa, 0x00 }, + { 0x38ab, 0x00 }, + { 0x3234, 0x00 }, + { 0x3fc1, 0x00 }, + { 0x3235, 0x00 }, + { 0x3802, 0x00 }, + { 0x3143, 0x04 }, + { 0x360a, 0x00 }, + { 0x0b00, 0x00 }, + { 0x0106, 0x00 }, + { 0x0b05, 0x01 }, + { 0x0b06, 0x01 }, + { 0x3230, 0x00 }, + { 0x3602, 0x01 }, + { 0x3607, 0x01 }, + { 0x3c00, 0x00 }, + { 0x3c01, 0x48 }, + { 0x3c02, 0xc8 }, + { 0x3c03, 0xaa }, + { 0x3c04, 0x91 }, + { 0x3c05, 0x54 }, + { 0x3c06, 0x26 }, + { 0x3c07, 0x20 }, + { 0x3c08, 0x51 }, + { 0x3d80, 0x00 }, + { 0x3f50, 0x00 }, + { 0x3f56, 0x00 }, + { 0x3f57, 0x30 }, + { 0x3f78, 0x01 }, + { 0x3f79, 0x18 }, + { 0x3f7c, 0x00 }, + { 0x3f7d, 0x00 }, + { 0x3fba, 0x00 }, + { 0x3fbb, 0x00 }, + { 0xa081, 0x00 }, + { 0xe014, 0x00 }, + { 0x0202, 0x0a }, + { 0x0203, 0x7a }, + { 0x0224, 0x01 }, + { 0x0225, 0xf4 }, + { 0x0204, 0x00 }, + { 0x0205, 0x00 }, + { 0x0216, 0x00 }, + { 0x0217, 0x00 }, + { 0x020e, 0x01 }, + { 0x020f, 0x00 }, + { 0x0210, 0x01 }, + { 0x0211, 0x00 }, + { 0x0212, 0x01 }, + { 0x0213, 0x00 }, + { 0x0214, 0x01 }, + { 0x0215, 0x00 }, + { 0x0218, 0x01 }, + { 0x0219, 0x00 }, + { 0x3614, 0x00 }, + { 0x3616, 0x0d }, + { 0x3617, 0x56 }, + { 0xb612, 0x20 }, + { 0xb613, 0x20 }, + { 0xb614, 0x20 }, + { 0xb615, 0x20 }, + { 0xb616, 0x0a }, + { 0xb617, 0x0a }, + { 0xb618, 0x20 }, + { 0xb619, 0x20 }, + { 0xb61a, 0x20 }, + { 0xb61b, 0x20 }, + { 0xb61c, 0x0a }, + { 0xb61d, 0x0a }, + { 0xb666, 0x30 }, + { 0xb667, 0x30 }, + { 0xb668, 0x30 }, + { 0xb669, 0x30 }, + { 0xb66a, 0x14 }, + { 0xb66b, 0x14 }, + { 0xb66c, 0x20 }, + { 0xb66d, 0x20 }, + { 0xb66e, 0x20 }, + { 0xb66f, 0x20 }, + { 0xb670, 0x10 }, + { 0xb671, 0x10 }, + { 0x3237, 0x00 }, + { 0x3900, 0x00 }, + { 0x3901, 0x00 }, + { 0x3902, 0x00 }, + { 0x3904, 0x00 }, + { 0x3905, 0x00 }, + { 0x3906, 0x00 }, + { 0x3907, 0x00 }, + { 0x3908, 0x00 }, + { 0x3909, 0x00 }, + { 0x3912, 0x00 }, + { 0x3930, 0x00 }, + { 0x3931, 0x00 }, + { 0x3933, 0x00 }, + { 0x3934, 0x00 }, + { 0x3935, 0x00 }, + { 0x3936, 0x00 }, + { 0x3937, 0x00 }, + { 0x30ac, 0x00 }, +}; + +static const struct imx319_reg mode_3280x2464_regs[] = { + { 0x0112, 0x0a }, + { 0x0113, 0x0a }, + { 0x0114, 0x03 }, + { 0x0342, 0x0f }, + { 0x0343, 0x80 }, + { 0x0340, 0x0c }, + { 0x0341, 0xaa }, + { 0x0344, 0x00 }, + { 0x0345, 0x00 }, + { 0x0346, 0x00 }, + { 0x0347, 0x00 }, + { 0x0348, 0x0c }, + { 0x0349, 0xcf }, + { 0x034a, 0x09 }, + { 0x034b, 0x9f }, + { 0x0220, 0x00 }, + { 0x0221, 0x11 }, + { 0x0381, 0x01 }, + { 0x0383, 0x01 }, + { 0x0385, 0x01 }, + { 0x0387, 0x01 }, + { 0x0900, 0x00 }, + { 0x0901, 0x11 }, + { 0x0902, 0x0a }, + { 0x3140, 0x02 }, + { 0x3141, 0x00 }, + { 0x3f0d, 0x0a }, + { 0x3f14, 0x01 }, + { 0x3f3c, 0x01 }, + { 0x3f4d, 0x01 }, + { 0x3f4c, 0x01 }, + { 0x4254, 0x7f }, + { 0x0401, 0x00 }, + { 0x0404, 0x00 }, + { 0x0405, 0x10 }, + { 0x0408, 0x00 }, + { 0x0409, 0x00 }, + { 0x040a, 0x00 }, + { 0x040b, 0x00 }, + { 0x040c, 0x0c }, + { 0x040d, 0xd0 }, + { 0x040e, 0x09 }, + { 0x040f, 0xa0 }, + { 0x034c, 0x0c }, + { 0x034d, 0xd0 }, + { 0x034e, 0x09 }, + { 0x034f, 0xa0 }, + { 0x3261, 0x00 }, + { 0x3264, 0x00 }, + { 0x3265, 0x10 }, + { 0x0301, 0x05 }, + { 0x0303, 0x04 }, + { 0x0305, 0x04 }, + { 0x0306, 0x01 }, + { 0x0307, 0x92 }, + { 0x0309, 0x0a }, + { 0x030b, 0x02 }, + { 0x030d, 0x02 }, + { 0x030e, 0x00 }, + { 0x030f, 0xfa }, + { 0x0310, 0x00 }, + { 0x0820, 0x0f }, + { 0x0821, 0x13 }, + { 0x0822, 0x33 }, + { 0x0823, 0x33 }, + { 0x3e20, 0x01 }, + { 0x3e37, 0x00 }, + { 0x3e3b, 0x01 }, + { 0x38a3, 0x01 }, + { 0x38a8, 0x00 }, + { 0x38a9, 0x00 }, + { 0x38aa, 0x00 }, + { 0x38ab, 0x00 }, + { 0x3234, 0x00 }, + { 0x3fc1, 0x00 }, + { 0x3235, 0x00 }, + { 0x3802, 0x00 }, + { 0x3143, 0x04 }, + { 0x360a, 0x00 }, + { 0x0b00, 0x00 }, + { 0x0106, 0x00 }, + { 0x0b05, 0x01 }, + { 0x0b06, 0x01 }, + { 0x3230, 0x00 }, + { 0x3602, 0x01 }, + { 0x3607, 0x01 }, + { 0x3c00, 0x00 }, + { 0x3c01, 0x48 }, + { 0x3c02, 0xc8 }, + { 0x3c03, 0xaa }, + { 0x3c04, 0x91 }, + { 0x3c05, 0x54 }, + { 0x3c06, 0x26 }, + { 0x3c07, 0x20 }, + { 0x3c08, 0x51 }, + { 0x3d80, 0x00 }, + { 0x3f50, 0x00 }, + { 0x3f56, 0x00 }, + { 0x3f57, 0x30 }, + { 0x3f78, 0x01 }, + { 0x3f79, 0x18 }, + { 0x3f7c, 0x00 }, + { 0x3f7d, 0x00 }, + { 0x3fba, 0x00 }, + { 0x3fbb, 0x00 }, + { 0xa081, 0x00 }, + { 0xe014, 0x00 }, + { 0x0202, 0x0a }, + { 0x0203, 0x7a }, + { 0x0224, 0x01 }, + { 0x0225, 0xf4 }, + { 0x0204, 0x00 }, + { 0x0205, 0x00 }, + { 0x0216, 0x00 }, + { 0x0217, 0x00 }, + { 0x020e, 0x01 }, + { 0x020f, 0x00 }, + { 0x0210, 0x01 }, + { 0x0211, 0x00 }, + { 0x0212, 0x01 }, + { 0x0213, 0x00 }, + { 0x0214, 0x01 }, + { 0x0215, 0x00 }, + { 0x0218, 0x01 }, + { 0x0219, 0x00 }, + { 0x3614, 0x00 }, + { 0x3616, 0x0d }, + { 0x3617, 0x56 }, + { 0xb612, 0x20 }, + { 0xb613, 0x20 }, + { 0xb614, 0x20 }, + { 0xb615, 0x20 }, + { 0xb616, 0x0a }, + { 0xb617, 0x0a }, + { 0xb618, 0x20 }, + { 0xb619, 0x20 }, + { 0xb61a, 0x20 }, + { 0xb61b, 0x20 }, + { 0xb61c, 0x0a }, + { 0xb61d, 0x0a }, + { 0xb666, 0x30 }, + { 0xb667, 0x30 }, + { 0xb668, 0x30 }, + { 0xb669, 0x30 }, + { 0xb66a, 0x14 }, + { 0xb66b, 0x14 }, + { 0xb66c, 0x20 }, + { 0xb66d, 0x20 }, + { 0xb66e, 0x20 }, + { 0xb66f, 0x20 }, + { 0xb670, 0x10 }, + { 0xb671, 0x10 }, + { 0x3237, 0x00 }, + { 0x3900, 0x00 }, + { 0x3901, 0x00 }, + { 0x3902, 0x00 }, + { 0x3904, 0x00 }, + { 0x3905, 0x00 }, + { 0x3906, 0x00 }, + { 0x3907, 0x00 }, + { 0x3908, 0x00 }, + { 0x3909, 0x00 }, + { 0x3912, 0x00 }, + { 0x3930, 0x00 }, + { 0x3931, 0x00 }, + { 0x3933, 0x00 }, + { 0x3934, 0x00 }, + { 0x3935, 0x00 }, + { 0x3936, 0x00 }, + { 0x3937, 0x00 }, + { 0x30ac, 0x00 }, +}; + +static const struct imx319_reg mode_1936x1096_regs[] = { + { 0x0112, 0x0a }, + { 0x0113, 0x0a }, + { 0x0114, 0x03 }, + { 0x0342, 0x0f }, + { 0x0343, 0x80 }, + { 0x0340, 0x0c }, + { 0x0341, 0xaa }, + { 0x0344, 0x00 }, + { 0x0345, 0x00 }, + { 0x0346, 0x02 }, + { 0x0347, 0xac }, + { 0x0348, 0x0c }, + { 0x0349, 0xcf }, + { 0x034a, 0x06 }, + { 0x034b, 0xf3 }, + { 0x0220, 0x00 }, + { 0x0221, 0x11 }, + { 0x0381, 0x01 }, + { 0x0383, 0x01 }, + { 0x0385, 0x01 }, + { 0x0387, 0x01 }, + { 0x0900, 0x00 }, + { 0x0901, 0x11 }, + { 0x0902, 0x0a }, + { 0x3140, 0x02 }, + { 0x3141, 0x00 }, + { 0x3f0d, 0x0a }, + { 0x3f14, 0x01 }, + { 0x3f3c, 0x01 }, + { 0x3f4d, 0x01 }, + { 0x3f4c, 0x01 }, + { 0x4254, 0x7f }, + { 0x0401, 0x00 }, + { 0x0404, 0x00 }, + { 0x0405, 0x10 }, + { 0x0408, 0x02 }, + { 0x0409, 0xa0 }, + { 0x040a, 0x00 }, + { 0x040b, 0x00 }, + { 0x040c, 0x07 }, + { 0x040d, 0x90 }, + { 0x040e, 0x04 }, + { 0x040f, 0x48 }, + { 0x034c, 0x07 }, + { 0x034d, 0x90 }, + { 0x034e, 0x04 }, + { 0x034f, 0x48 }, + { 0x3261, 0x00 }, + { 0x3264, 0x00 }, + { 0x3265, 0x10 }, + { 0x0301, 0x05 }, + { 0x0303, 0x04 }, + { 0x0305, 0x04 }, + { 0x0306, 0x01 }, + { 0x0307, 0x92 }, + { 0x0309, 0x0a }, + { 0x030b, 0x02 }, + { 0x030d, 0x02 }, + { 0x030e, 0x00 }, + { 0x030f, 0xfa }, + { 0x0310, 0x00 }, + { 0x0820, 0x0f }, + { 0x0821, 0x13 }, + { 0x0822, 0x33 }, + { 0x0823, 0x33 }, + { 0x3e20, 0x01 }, + { 0x3e37, 0x00 }, + { 0x3e3b, 0x01 }, + { 0x38a3, 0x01 }, + { 0x38a8, 0x00 }, + { 0x38a9, 0x00 }, + { 0x38aa, 0x00 }, + { 0x38ab, 0x00 }, + { 0x3234, 0x00 }, + { 0x3fc1, 0x00 }, + { 0x3235, 0x00 }, + { 0x3802, 0x00 }, + { 0x3143, 0x04 }, + { 0x360a, 0x00 }, + { 0x0b00, 0x00 }, + { 0x0106, 0x00 }, + { 0x0b05, 0x01 }, + { 0x0b06, 0x01 }, + { 0x3230, 0x00 }, + { 0x3602, 0x01 }, + { 0x3607, 0x01 }, + { 0x3c00, 0x00 }, + { 0x3c01, 0x48 }, + { 0x3c02, 0xc8 }, + { 0x3c03, 0xaa }, + { 0x3c04, 0x91 }, + { 0x3c05, 0x54 }, + { 0x3c06, 0x26 }, + { 0x3c07, 0x20 }, + { 0x3c08, 0x51 }, + { 0x3d80, 0x00 }, + { 0x3f50, 0x00 }, + { 0x3f56, 0x00 }, + { 0x3f57, 0x30 }, + { 0x3f78, 0x01 }, + { 0x3f79, 0x18 }, + { 0x3f7c, 0x00 }, + { 0x3f7d, 0x00 }, + { 0x3fba, 0x00 }, + { 0x3fbb, 0x00 }, + { 0xa081, 0x00 }, + { 0xe014, 0x00 }, + { 0x0202, 0x05 }, + { 0x0203, 0x34 }, + { 0x0224, 0x01 }, + { 0x0225, 0xf4 }, + { 0x0204, 0x00 }, + { 0x0205, 0x00 }, + { 0x0216, 0x00 }, + { 0x0217, 0x00 }, + { 0x020e, 0x01 }, + { 0x020f, 0x00 }, + { 0x0210, 0x01 }, + { 0x0211, 0x00 }, + { 0x0212, 0x01 }, + { 0x0213, 0x00 }, + { 0x0214, 0x01 }, + { 0x0215, 0x00 }, + { 0x0218, 0x01 }, + { 0x0219, 0x00 }, + { 0x3614, 0x00 }, + { 0x3616, 0x0d }, + { 0x3617, 0x56 }, + { 0xb612, 0x20 }, + { 0xb613, 0x20 }, + { 0xb614, 0x20 }, + { 0xb615, 0x20 }, + { 0xb616, 0x0a }, + { 0xb617, 0x0a }, + { 0xb618, 0x20 }, + { 0xb619, 0x20 }, + { 0xb61a, 0x20 }, + { 0xb61b, 0x20 }, + { 0xb61c, 0x0a }, + { 0xb61d, 0x0a }, + { 0xb666, 0x30 }, + { 0xb667, 0x30 }, + { 0xb668, 0x30 }, + { 0xb669, 0x30 }, + { 0xb66a, 0x14 }, + { 0xb66b, 0x14 }, + { 0xb66c, 0x20 }, + { 0xb66d, 0x20 }, + { 0xb66e, 0x20 }, + { 0xb66f, 0x20 }, + { 0xb670, 0x10 }, + { 0xb671, 0x10 }, + { 0x3237, 0x00 }, + { 0x3900, 0x00 }, + { 0x3901, 0x00 }, + { 0x3902, 0x00 }, + { 0x3904, 0x00 }, + { 0x3905, 0x00 }, + { 0x3906, 0x00 }, + { 0x3907, 0x00 }, + { 0x3908, 0x00 }, + { 0x3909, 0x00 }, + { 0x3912, 0x00 }, + { 0x3930, 0x00 }, + { 0x3931, 0x00 }, + { 0x3933, 0x00 }, + { 0x3934, 0x00 }, + { 0x3935, 0x00 }, + { 0x3936, 0x00 }, + { 0x3937, 0x00 }, + { 0x30ac, 0x00 }, +}; + +static const struct imx319_reg mode_1920x1080_regs[] = { + { 0x0112, 0x0a }, + { 0x0113, 0x0a }, + { 0x0114, 0x03 }, + { 0x0342, 0x0f }, + { 0x0343, 0x80 }, + { 0x0340, 0x0c }, + { 0x0341, 0xaa }, + { 0x0344, 0x00 }, + { 0x0345, 0x00 }, + { 0x0346, 0x02 }, + { 0x0347, 0xb4 }, + { 0x0348, 0x0c }, + { 0x0349, 0xcf }, + { 0x034a, 0x06 }, + { 0x034b, 0xeb }, + { 0x0220, 0x00 }, + { 0x0221, 0x11 }, + { 0x0381, 0x01 }, + { 0x0383, 0x01 }, + { 0x0385, 0x01 }, + { 0x0387, 0x01 }, + { 0x0900, 0x00 }, + { 0x0901, 0x11 }, + { 0x0902, 0x0a }, + { 0x3140, 0x02 }, + { 0x3141, 0x00 }, + { 0x3f0d, 0x0a }, + { 0x3f14, 0x01 }, + { 0x3f3c, 0x01 }, + { 0x3f4d, 0x01 }, + { 0x3f4c, 0x01 }, + { 0x4254, 0x7f }, + { 0x0401, 0x00 }, + { 0x0404, 0x00 }, + { 0x0405, 0x10 }, + { 0x0408, 0x02 }, + { 0x0409, 0xa8 }, + { 0x040a, 0x00 }, + { 0x040b, 0x00 }, + { 0x040c, 0x07 }, + { 0x040d, 0x80 }, + { 0x040e, 0x04 }, + { 0x040f, 0x38 }, + { 0x034c, 0x07 }, + { 0x034d, 0x80 }, + { 0x034e, 0x04 }, + { 0x034f, 0x38 }, + { 0x3261, 0x00 }, + { 0x3264, 0x00 }, + { 0x3265, 0x10 }, + { 0x0301, 0x05 }, + { 0x0303, 0x04 }, + { 0x0305, 0x04 }, + { 0x0306, 0x01 }, + { 0x0307, 0x92 }, + { 0x0309, 0x0a }, + { 0x030b, 0x02 }, + { 0x030d, 0x02 }, + { 0x030e, 0x00 }, + { 0x030f, 0xfa }, + { 0x0310, 0x00 }, + { 0x0820, 0x0f }, + { 0x0821, 0x13 }, + { 0x0822, 0x33 }, + { 0x0823, 0x33 }, + { 0x3e20, 0x01 }, + { 0x3e37, 0x00 }, + { 0x3e3b, 0x01 }, + { 0x38a3, 0x01 }, + { 0x38a8, 0x00 }, + { 0x38a9, 0x00 }, + { 0x38aa, 0x00 }, + { 0x38ab, 0x00 }, + { 0x3234, 0x00 }, + { 0x3fc1, 0x00 }, + { 0x3235, 0x00 }, + { 0x3802, 0x00 }, + { 0x3143, 0x04 }, + { 0x360a, 0x00 }, + { 0x0b00, 0x00 }, + { 0x0106, 0x00 }, + { 0x0b05, 0x01 }, + { 0x0b06, 0x01 }, + { 0x3230, 0x00 }, + { 0x3602, 0x01 }, + { 0x3607, 0x01 }, + { 0x3c00, 0x00 }, + { 0x3c01, 0x48 }, + { 0x3c02, 0xc8 }, + { 0x3c03, 0xaa }, + { 0x3c04, 0x91 }, + { 0x3c05, 0x54 }, + { 0x3c06, 0x26 }, + { 0x3c07, 0x20 }, + { 0x3c08, 0x51 }, + { 0x3d80, 0x00 }, + { 0x3f50, 0x00 }, + { 0x3f56, 0x00 }, + { 0x3f57, 0x30 }, + { 0x3f78, 0x01 }, + { 0x3f79, 0x18 }, + { 0x3f7c, 0x00 }, + { 0x3f7d, 0x00 }, + { 0x3fba, 0x00 }, + { 0x3fbb, 0x00 }, + { 0xa081, 0x00 }, + { 0xe014, 0x00 }, + { 0x0202, 0x05 }, + { 0x0203, 0x34 }, + { 0x0224, 0x01 }, + { 0x0225, 0xf4 }, + { 0x0204, 0x00 }, + { 0x0205, 0x00 }, + { 0x0216, 0x00 }, + { 0x0217, 0x00 }, + { 0x020e, 0x01 }, + { 0x020f, 0x00 }, + { 0x0210, 0x01 }, + { 0x0211, 0x00 }, + { 0x0212, 0x01 }, + { 0x0213, 0x00 }, + { 0x0214, 0x01 }, + { 0x0215, 0x00 }, + { 0x0218, 0x01 }, + { 0x0219, 0x00 }, + { 0x3614, 0x00 }, + { 0x3616, 0x0d }, + { 0x3617, 0x56 }, + { 0xb612, 0x20 }, + { 0xb613, 0x20 }, + { 0xb614, 0x20 }, + { 0xb615, 0x20 }, + { 0xb616, 0x0a }, + { 0xb617, 0x0a }, + { 0xb618, 0x20 }, + { 0xb619, 0x20 }, + { 0xb61a, 0x20 }, + { 0xb61b, 0x20 }, + { 0xb61c, 0x0a }, + { 0xb61d, 0x0a }, + { 0xb666, 0x30 }, + { 0xb667, 0x30 }, + { 0xb668, 0x30 }, + { 0xb669, 0x30 }, + { 0xb66a, 0x14 }, + { 0xb66b, 0x14 }, + { 0xb66c, 0x20 }, + { 0xb66d, 0x20 }, + { 0xb66e, 0x20 }, + { 0xb66f, 0x20 }, + { 0xb670, 0x10 }, + { 0xb671, 0x10 }, + { 0x3237, 0x00 }, + { 0x3900, 0x00 }, + { 0x3901, 0x00 }, + { 0x3902, 0x00 }, + { 0x3904, 0x00 }, + { 0x3905, 0x00 }, + { 0x3906, 0x00 }, + { 0x3907, 0x00 }, + { 0x3908, 0x00 }, + { 0x3909, 0x00 }, + { 0x3912, 0x00 }, + { 0x3930, 0x00 }, + { 0x3931, 0x00 }, + { 0x3933, 0x00 }, + { 0x3934, 0x00 }, + { 0x3935, 0x00 }, + { 0x3936, 0x00 }, + { 0x3937, 0x00 }, + { 0x30ac, 0x00 }, +}; + +static const struct imx319_reg mode_1640x1232_regs[] = { + { 0x0112, 0x0a }, + { 0x0113, 0x0a }, + { 0x0114, 0x03 }, + { 0x0342, 0x08 }, + { 0x0343, 0x20 }, + { 0x0340, 0x18 }, + { 0x0341, 0x2a }, + { 0x0344, 0x00 }, + { 0x0345, 0x00 }, + { 0x0346, 0x00 }, + { 0x0347, 0x00 }, + { 0x0348, 0x0c }, + { 0x0349, 0xcf }, + { 0x034a, 0x09 }, + { 0x034b, 0x9f }, + { 0x0220, 0x00 }, + { 0x0221, 0x11 }, + { 0x0381, 0x01 }, + { 0x0383, 0x01 }, + { 0x0385, 0x01 }, + { 0x0387, 0x01 }, + { 0x0900, 0x01 }, + { 0x0901, 0x22 }, + { 0x0902, 0x0a }, + { 0x3140, 0x02 }, + { 0x3141, 0x00 }, + { 0x3f0d, 0x0a }, + { 0x3f14, 0x01 }, + { 0x3f3c, 0x02 }, + { 0x3f4d, 0x01 }, + { 0x3f4c, 0x01 }, + { 0x4254, 0x7f }, + { 0x0401, 0x00 }, + { 0x0404, 0x00 }, + { 0x0405, 0x10 }, + { 0x0408, 0x00 }, + { 0x0409, 0x00 }, + { 0x040a, 0x00 }, + { 0x040b, 0x00 }, + { 0x040c, 0x06 }, + { 0x040d, 0x68 }, + { 0x040e, 0x04 }, + { 0x040f, 0xd0 }, + { 0x034c, 0x06 }, + { 0x034d, 0x68 }, + { 0x034e, 0x04 }, + { 0x034f, 0xd0 }, + { 0x3261, 0x00 }, + { 0x3264, 0x00 }, + { 0x3265, 0x10 }, + { 0x0301, 0x05 }, + { 0x0303, 0x04 }, + { 0x0305, 0x04 }, + { 0x0306, 0x01 }, + { 0x0307, 0x92 }, + { 0x0309, 0x0a }, + { 0x030b, 0x02 }, + { 0x030d, 0x02 }, + { 0x030e, 0x00 }, + { 0x030f, 0xfa }, + { 0x0310, 0x00 }, + { 0x0820, 0x0f }, + { 0x0821, 0x13 }, + { 0x0822, 0x33 }, + { 0x0823, 0x33 }, + { 0x3e20, 0x01 }, + { 0x3e37, 0x00 }, + { 0x3e3b, 0x01 }, + { 0x38a3, 0x01 }, + { 0x38a8, 0x00 }, + { 0x38a9, 0x00 }, + { 0x38aa, 0x00 }, + { 0x38ab, 0x00 }, + { 0x3234, 0x00 }, + { 0x3fc1, 0x00 }, + { 0x3235, 0x00 }, + { 0x3802, 0x00 }, + { 0x3143, 0x04 }, + { 0x360a, 0x00 }, + { 0x0b00, 0x00 }, + { 0x0106, 0x00 }, + { 0x0b05, 0x01 }, + { 0x0b06, 0x01 }, + { 0x3230, 0x00 }, + { 0x3602, 0x01 }, + { 0x3607, 0x01 }, + { 0x3c00, 0x00 }, + { 0x3c01, 0xba }, + { 0x3c02, 0xc8 }, + { 0x3c03, 0xaa }, + { 0x3c04, 0x91 }, + { 0x3c05, 0x54 }, + { 0x3c06, 0x26 }, + { 0x3c07, 0x20 }, + { 0x3c08, 0x51 }, + { 0x3d80, 0x00 }, + { 0x3f50, 0x00 }, + { 0x3f56, 0x00 }, + { 0x3f57, 0x30 }, + { 0x3f78, 0x00 }, + { 0x3f79, 0x34 }, + { 0x3f7c, 0x00 }, + { 0x3f7d, 0x00 }, + { 0x3fba, 0x00 }, + { 0x3fbb, 0x00 }, + { 0xa081, 0x04 }, + { 0xe014, 0x00 }, + { 0x0202, 0x04 }, + { 0x0203, 0xf6 }, + { 0x0224, 0x01 }, + { 0x0225, 0xf4 }, + { 0x0204, 0x00 }, + { 0x0205, 0x00 }, + { 0x0216, 0x00 }, + { 0x0217, 0x00 }, + { 0x020e, 0x01 }, + { 0x020f, 0x00 }, + { 0x0210, 0x01 }, + { 0x0211, 0x00 }, + { 0x0212, 0x01 }, + { 0x0213, 0x00 }, + { 0x0214, 0x01 }, + { 0x0215, 0x00 }, + { 0x0218, 0x01 }, + { 0x0219, 0x00 }, + { 0x3614, 0x00 }, + { 0x3616, 0x0d }, + { 0x3617, 0x56 }, + { 0xb612, 0x20 }, + { 0xb613, 0x20 }, + { 0xb614, 0x20 }, + { 0xb615, 0x20 }, + { 0xb616, 0x0a }, + { 0xb617, 0x0a }, + { 0xb618, 0x20 }, + { 0xb619, 0x20 }, + { 0xb61a, 0x20 }, + { 0xb61b, 0x20 }, + { 0xb61c, 0x0a }, + { 0xb61d, 0x0a }, + { 0xb666, 0x30 }, + { 0xb667, 0x30 }, + { 0xb668, 0x30 }, + { 0xb669, 0x30 }, + { 0xb66a, 0x14 }, + { 0xb66b, 0x14 }, + { 0xb66c, 0x20 }, + { 0xb66d, 0x20 }, + { 0xb66e, 0x20 }, + { 0xb66f, 0x20 }, + { 0xb670, 0x10 }, + { 0xb671, 0x10 }, + { 0x3237, 0x00 }, + { 0x3900, 0x00 }, + { 0x3901, 0x00 }, + { 0x3902, 0x00 }, + { 0x3904, 0x00 }, + { 0x3905, 0x00 }, + { 0x3906, 0x00 }, + { 0x3907, 0x00 }, + { 0x3908, 0x00 }, + { 0x3909, 0x00 }, + { 0x3912, 0x00 }, + { 0x3930, 0x00 }, + { 0x3931, 0x00 }, + { 0x3933, 0x00 }, + { 0x3934, 0x00 }, + { 0x3935, 0x00 }, + { 0x3936, 0x00 }, + { 0x3937, 0x00 }, + { 0x30ac, 0x00 }, +}; + +static const struct imx319_reg mode_1640x922_regs[] = { + { 0x0112, 0x0a }, + { 0x0113, 0x0a }, + { 0x0114, 0x03 }, + { 0x0342, 0x08 }, + { 0x0343, 0x20 }, + { 0x0340, 0x18 }, + { 0x0341, 0x2a }, + { 0x0344, 0x00 }, + { 0x0345, 0x00 }, + { 0x0346, 0x01 }, + { 0x0347, 0x30 }, + { 0x0348, 0x0c }, + { 0x0349, 0xcf }, + { 0x034a, 0x08 }, + { 0x034b, 0x6f }, + { 0x0220, 0x00 }, + { 0x0221, 0x11 }, + { 0x0381, 0x01 }, + { 0x0383, 0x01 }, + { 0x0385, 0x01 }, + { 0x0387, 0x01 }, + { 0x0900, 0x01 }, + { 0x0901, 0x22 }, + { 0x0902, 0x0a }, + { 0x3140, 0x02 }, + { 0x3141, 0x00 }, + { 0x3f0d, 0x0a }, + { 0x3f14, 0x01 }, + { 0x3f3c, 0x02 }, + { 0x3f4d, 0x01 }, + { 0x3f4c, 0x01 }, + { 0x4254, 0x7f }, + { 0x0401, 0x00 }, + { 0x0404, 0x00 }, + { 0x0405, 0x10 }, + { 0x0408, 0x00 }, + { 0x0409, 0x00 }, + { 0x040a, 0x00 }, + { 0x040b, 0x02 }, + { 0x040c, 0x06 }, + { 0x040d, 0x68 }, + { 0x040e, 0x03 }, + { 0x040f, 0x9a }, + { 0x034c, 0x06 }, + { 0x034d, 0x68 }, + { 0x034e, 0x03 }, + { 0x034f, 0x9a }, + { 0x3261, 0x00 }, + { 0x3264, 0x00 }, + { 0x3265, 0x10 }, + { 0x0301, 0x05 }, + { 0x0303, 0x04 }, + { 0x0305, 0x04 }, + { 0x0306, 0x01 }, + { 0x0307, 0x92 }, + { 0x0309, 0x0a }, + { 0x030b, 0x02 }, + { 0x030d, 0x02 }, + { 0x030e, 0x00 }, + { 0x030f, 0xfa }, + { 0x0310, 0x00 }, + { 0x0820, 0x0f }, + { 0x0821, 0x13 }, + { 0x0822, 0x33 }, + { 0x0823, 0x33 }, + { 0x3e20, 0x01 }, + { 0x3e37, 0x00 }, + { 0x3e3b, 0x01 }, + { 0x38a3, 0x01 }, + { 0x38a8, 0x00 }, + { 0x38a9, 0x00 }, + { 0x38aa, 0x00 }, + { 0x38ab, 0x00 }, + { 0x3234, 0x00 }, + { 0x3fc1, 0x00 }, + { 0x3235, 0x00 }, + { 0x3802, 0x00 }, + { 0x3143, 0x04 }, + { 0x360a, 0x00 }, + { 0x0b00, 0x00 }, + { 0x0106, 0x00 }, + { 0x0b05, 0x01 }, + { 0x0b06, 0x01 }, + { 0x3230, 0x00 }, + { 0x3602, 0x01 }, + { 0x3607, 0x01 }, + { 0x3c00, 0x00 }, + { 0x3c01, 0xba }, + { 0x3c02, 0xc8 }, + { 0x3c03, 0xaa }, + { 0x3c04, 0x91 }, + { 0x3c05, 0x54 }, + { 0x3c06, 0x26 }, + { 0x3c07, 0x20 }, + { 0x3c08, 0x51 }, + { 0x3d80, 0x00 }, + { 0x3f50, 0x00 }, + { 0x3f56, 0x00 }, + { 0x3f57, 0x30 }, + { 0x3f78, 0x00 }, + { 0x3f79, 0x34 }, + { 0x3f7c, 0x00 }, + { 0x3f7d, 0x00 }, + { 0x3fba, 0x00 }, + { 0x3fbb, 0x00 }, + { 0xa081, 0x04 }, + { 0xe014, 0x00 }, + { 0x0202, 0x04 }, + { 0x0203, 0xf6 }, + { 0x0224, 0x01 }, + { 0x0225, 0xf4 }, + { 0x0204, 0x00 }, + { 0x0205, 0x00 }, + { 0x0216, 0x00 }, + { 0x0217, 0x00 }, + { 0x020e, 0x01 }, + { 0x020f, 0x00 }, + { 0x0210, 0x01 }, + { 0x0211, 0x00 }, + { 0x0212, 0x01 }, + { 0x0213, 0x00 }, + { 0x0214, 0x01 }, + { 0x0215, 0x00 }, + { 0x0218, 0x01 }, + { 0x0219, 0x00 }, + { 0x3614, 0x00 }, + { 0x3616, 0x0d }, + { 0x3617, 0x56 }, + { 0xb612, 0x20 }, + { 0xb613, 0x20 }, + { 0xb614, 0x20 }, + { 0xb615, 0x20 }, + { 0xb616, 0x0a }, + { 0xb617, 0x0a }, + { 0xb618, 0x20 }, + { 0xb619, 0x20 }, + { 0xb61a, 0x20 }, + { 0xb61b, 0x20 }, + { 0xb61c, 0x0a }, + { 0xb61d, 0x0a }, + { 0xb666, 0x30 }, + { 0xb667, 0x30 }, + { 0xb668, 0x30 }, + { 0xb669, 0x30 }, + { 0xb66a, 0x14 }, + { 0xb66b, 0x14 }, + { 0xb66c, 0x20 }, + { 0xb66d, 0x20 }, + { 0xb66e, 0x20 }, + { 0xb66f, 0x20 }, + { 0xb670, 0x10 }, + { 0xb671, 0x10 }, + { 0x3237, 0x00 }, + { 0x3900, 0x00 }, + { 0x3901, 0x00 }, + { 0x3902, 0x00 }, + { 0x3904, 0x00 }, + { 0x3905, 0x00 }, + { 0x3906, 0x00 }, + { 0x3907, 0x00 }, + { 0x3908, 0x00 }, + { 0x3909, 0x00 }, + { 0x3912, 0x00 }, + { 0x3930, 0x00 }, + { 0x3931, 0x00 }, + { 0x3933, 0x00 }, + { 0x3934, 0x00 }, + { 0x3935, 0x00 }, + { 0x3936, 0x00 }, + { 0x3937, 0x00 }, + { 0x30ac, 0x00 }, +}; + +static const struct imx319_reg mode_1296x736_regs[] = { + { 0x0112, 0x0a }, + { 0x0113, 0x0a }, + { 0x0114, 0x03 }, + { 0x0342, 0x08 }, + { 0x0343, 0x20 }, + { 0x0340, 0x18 }, + { 0x0341, 0x2a }, + { 0x0344, 0x00 }, + { 0x0345, 0x00 }, + { 0x0346, 0x01 }, + { 0x0347, 0xf0 }, + { 0x0348, 0x0c }, + { 0x0349, 0xcf }, + { 0x034a, 0x07 }, + { 0x034b, 0xaf }, + { 0x0220, 0x00 }, + { 0x0221, 0x11 }, + { 0x0381, 0x01 }, + { 0x0383, 0x01 }, + { 0x0385, 0x01 }, + { 0x0387, 0x01 }, + { 0x0900, 0x01 }, + { 0x0901, 0x22 }, + { 0x0902, 0x0a }, + { 0x3140, 0x02 }, + { 0x3141, 0x00 }, + { 0x3f0d, 0x0a }, + { 0x3f14, 0x01 }, + { 0x3f3c, 0x02 }, + { 0x3f4d, 0x01 }, + { 0x3f4c, 0x01 }, + { 0x4254, 0x7f }, + { 0x0401, 0x00 }, + { 0x0404, 0x00 }, + { 0x0405, 0x10 }, + { 0x0408, 0x00 }, + { 0x0409, 0xac }, + { 0x040a, 0x00 }, + { 0x040b, 0x00 }, + { 0x040c, 0x05 }, + { 0x040d, 0x10 }, + { 0x040e, 0x02 }, + { 0x040f, 0xe0 }, + { 0x034c, 0x05 }, + { 0x034d, 0x10 }, + { 0x034e, 0x02 }, + { 0x034f, 0xe0 }, + { 0x3261, 0x00 }, + { 0x3264, 0x00 }, + { 0x3265, 0x10 }, + { 0x0301, 0x05 }, + { 0x0303, 0x04 }, + { 0x0305, 0x04 }, + { 0x0306, 0x01 }, + { 0x0307, 0x92 }, + { 0x0309, 0x0a }, + { 0x030b, 0x02 }, + { 0x030d, 0x02 }, + { 0x030e, 0x00 }, + { 0x030f, 0xfa }, + { 0x0310, 0x00 }, + { 0x0820, 0x0f }, + { 0x0821, 0x13 }, + { 0x0822, 0x33 }, + { 0x0823, 0x33 }, + { 0x3e20, 0x01 }, + { 0x3e37, 0x00 }, + { 0x3e3b, 0x01 }, + { 0x38a3, 0x01 }, + { 0x38a8, 0x00 }, + { 0x38a9, 0x00 }, + { 0x38aa, 0x00 }, + { 0x38ab, 0x00 }, + { 0x3234, 0x00 }, + { 0x3fc1, 0x00 }, + { 0x3235, 0x00 }, + { 0x3802, 0x00 }, + { 0x3143, 0x04 }, + { 0x360a, 0x00 }, + { 0x0b00, 0x00 }, + { 0x0106, 0x00 }, + { 0x0b05, 0x01 }, + { 0x0b06, 0x01 }, + { 0x3230, 0x00 }, + { 0x3602, 0x01 }, + { 0x3607, 0x01 }, + { 0x3c00, 0x00 }, + { 0x3c01, 0xba }, + { 0x3c02, 0xc8 }, + { 0x3c03, 0xaa }, + { 0x3c04, 0x91 }, + { 0x3c05, 0x54 }, + { 0x3c06, 0x26 }, + { 0x3c07, 0x20 }, + { 0x3c08, 0x51 }, + { 0x3d80, 0x00 }, + { 0x3f50, 0x00 }, + { 0x3f56, 0x00 }, + { 0x3f57, 0x30 }, + { 0x3f78, 0x00 }, + { 0x3f79, 0x34 }, + { 0x3f7c, 0x00 }, + { 0x3f7d, 0x00 }, + { 0x3fba, 0x00 }, + { 0x3fbb, 0x00 }, + { 0xa081, 0x04 }, + { 0xe014, 0x00 }, + { 0x0202, 0x04 }, + { 0x0203, 0xf6 }, + { 0x0224, 0x01 }, + { 0x0225, 0xf4 }, + { 0x0204, 0x00 }, + { 0x0205, 0x00 }, + { 0x0216, 0x00 }, + { 0x0217, 0x00 }, + { 0x020e, 0x01 }, + { 0x020f, 0x00 }, + { 0x0210, 0x01 }, + { 0x0211, 0x00 }, + { 0x0212, 0x01 }, + { 0x0213, 0x00 }, + { 0x0214, 0x01 }, + { 0x0215, 0x00 }, + { 0x0218, 0x01 }, + { 0x0219, 0x00 }, + { 0x3614, 0x00 }, + { 0x3616, 0x0d }, + { 0x3617, 0x56 }, + { 0xb612, 0x20 }, + { 0xb613, 0x20 }, + { 0xb614, 0x20 }, + { 0xb615, 0x20 }, + { 0xb616, 0x0a }, + { 0xb617, 0x0a }, + { 0xb618, 0x20 }, + { 0xb619, 0x20 }, + { 0xb61a, 0x20 }, + { 0xb61b, 0x20 }, + { 0xb61c, 0x0a }, + { 0xb61d, 0x0a }, + { 0xb666, 0x30 }, + { 0xb667, 0x30 }, + { 0xb668, 0x30 }, + { 0xb669, 0x30 }, + { 0xb66a, 0x14 }, + { 0xb66b, 0x14 }, + { 0xb66c, 0x20 }, + { 0xb66d, 0x20 }, + { 0xb66e, 0x20 }, + { 0xb66f, 0x20 }, + { 0xb670, 0x10 }, + { 0xb671, 0x10 }, + { 0x3237, 0x00 }, + { 0x3900, 0x00 }, + { 0x3901, 0x00 }, + { 0x3902, 0x00 }, + { 0x3904, 0x00 }, + { 0x3905, 0x00 }, + { 0x3906, 0x00 }, + { 0x3907, 0x00 }, + { 0x3908, 0x00 }, + { 0x3909, 0x00 }, + { 0x3912, 0x00 }, + { 0x3930, 0x00 }, + { 0x3931, 0x00 }, + { 0x3933, 0x00 }, + { 0x3934, 0x00 }, + { 0x3935, 0x00 }, + { 0x3936, 0x00 }, + { 0x3937, 0x00 }, + { 0x30ac, 0x00 }, +}; + +static const struct imx319_reg mode_1280x720_regs[] = { + { 0x0112, 0x0a }, + { 0x0113, 0x0a }, + { 0x0114, 0x03 }, + { 0x0342, 0x08 }, + { 0x0343, 0x20 }, + { 0x0340, 0x18 }, + { 0x0341, 0x2a }, + { 0x0344, 0x00 }, + { 0x0345, 0x00 }, + { 0x0346, 0x02 }, + { 0x0347, 0x00 }, + { 0x0348, 0x0c }, + { 0x0349, 0xcf }, + { 0x034a, 0x07 }, + { 0x034b, 0x9f }, + { 0x0220, 0x00 }, + { 0x0221, 0x11 }, + { 0x0381, 0x01 }, + { 0x0383, 0x01 }, + { 0x0385, 0x01 }, + { 0x0387, 0x01 }, + { 0x0900, 0x01 }, + { 0x0901, 0x22 }, + { 0x0902, 0x0a }, + { 0x3140, 0x02 }, + { 0x3141, 0x00 }, + { 0x3f0d, 0x0a }, + { 0x3f14, 0x01 }, + { 0x3f3c, 0x02 }, + { 0x3f4d, 0x01 }, + { 0x3f4c, 0x01 }, + { 0x4254, 0x7f }, + { 0x0401, 0x00 }, + { 0x0404, 0x00 }, + { 0x0405, 0x10 }, + { 0x0408, 0x00 }, + { 0x0409, 0xb4 }, + { 0x040a, 0x00 }, + { 0x040b, 0x00 }, + { 0x040c, 0x05 }, + { 0x040d, 0x00 }, + { 0x040e, 0x02 }, + { 0x040f, 0xd0 }, + { 0x034c, 0x05 }, + { 0x034d, 0x00 }, + { 0x034e, 0x02 }, + { 0x034f, 0xd0 }, + { 0x3261, 0x00 }, + { 0x3264, 0x00 }, + { 0x3265, 0x10 }, + { 0x0301, 0x05 }, + { 0x0303, 0x04 }, + { 0x0305, 0x04 }, + { 0x0306, 0x01 }, + { 0x0307, 0x92 }, + { 0x0309, 0x0a }, + { 0x030b, 0x02 }, + { 0x030d, 0x02 }, + { 0x030e, 0x00 }, + { 0x030f, 0xfa }, + { 0x0310, 0x00 }, + { 0x0820, 0x0f }, + { 0x0821, 0x13 }, + { 0x0822, 0x33 }, + { 0x0823, 0x33 }, + { 0x3e20, 0x01 }, + { 0x3e37, 0x00 }, + { 0x3e3b, 0x01 }, + { 0x38a3, 0x01 }, + { 0x38a8, 0x00 }, + { 0x38a9, 0x00 }, + { 0x38aa, 0x00 }, + { 0x38ab, 0x00 }, + { 0x3234, 0x00 }, + { 0x3fc1, 0x00 }, + { 0x3235, 0x00 }, + { 0x3802, 0x00 }, + { 0x3143, 0x04 }, + { 0x360a, 0x00 }, + { 0x0b00, 0x00 }, + { 0x0106, 0x00 }, + { 0x0b05, 0x01 }, + { 0x0b06, 0x01 }, + { 0x3230, 0x00 }, + { 0x3602, 0x01 }, + { 0x3607, 0x01 }, + { 0x3c00, 0x00 }, + { 0x3c01, 0xba }, + { 0x3c02, 0xc8 }, + { 0x3c03, 0xaa }, + { 0x3c04, 0x91 }, + { 0x3c05, 0x54 }, + { 0x3c06, 0x26 }, + { 0x3c07, 0x20 }, + { 0x3c08, 0x51 }, + { 0x3d80, 0x00 }, + { 0x3f50, 0x00 }, + { 0x3f56, 0x00 }, + { 0x3f57, 0x30 }, + { 0x3f78, 0x00 }, + { 0x3f79, 0x34 }, + { 0x3f7c, 0x00 }, + { 0x3f7d, 0x00 }, + { 0x3fba, 0x00 }, + { 0x3fbb, 0x00 }, + { 0xa081, 0x04 }, + { 0xe014, 0x00 }, + { 0x0202, 0x04 }, + { 0x0203, 0xf6 }, + { 0x0224, 0x01 }, + { 0x0225, 0xf4 }, + { 0x0204, 0x00 }, + { 0x0205, 0x00 }, + { 0x0216, 0x00 }, + { 0x0217, 0x00 }, + { 0x020e, 0x01 }, + { 0x020f, 0x00 }, + { 0x0210, 0x01 }, + { 0x0211, 0x00 }, + { 0x0212, 0x01 }, + { 0x0213, 0x00 }, + { 0x0214, 0x01 }, + { 0x0215, 0x00 }, + { 0x0218, 0x01 }, + { 0x0219, 0x00 }, + { 0x3614, 0x00 }, + { 0x3616, 0x0d }, + { 0x3617, 0x56 }, + { 0xb612, 0x20 }, + { 0xb613, 0x20 }, + { 0xb614, 0x20 }, + { 0xb615, 0x20 }, + { 0xb616, 0x0a }, + { 0xb617, 0x0a }, + { 0xb618, 0x20 }, + { 0xb619, 0x20 }, + { 0xb61a, 0x20 }, + { 0xb61b, 0x20 }, + { 0xb61c, 0x0a }, + { 0xb61d, 0x0a }, + { 0xb666, 0x30 }, + { 0xb667, 0x30 }, + { 0xb668, 0x30 }, + { 0xb669, 0x30 }, + { 0xb66a, 0x14 }, + { 0xb66b, 0x14 }, + { 0xb66c, 0x20 }, + { 0xb66d, 0x20 }, + { 0xb66e, 0x20 }, + { 0xb66f, 0x20 }, + { 0xb670, 0x10 }, + { 0xb671, 0x10 }, + { 0x3237, 0x00 }, + { 0x3900, 0x00 }, + { 0x3901, 0x00 }, + { 0x3902, 0x00 }, + { 0x3904, 0x00 }, + { 0x3905, 0x00 }, + { 0x3906, 0x00 }, + { 0x3907, 0x00 }, + { 0x3908, 0x00 }, + { 0x3909, 0x00 }, + { 0x3912, 0x00 }, + { 0x3930, 0x00 }, + { 0x3931, 0x00 }, + { 0x3933, 0x00 }, + { 0x3934, 0x00 }, + { 0x3935, 0x00 }, + { 0x3936, 0x00 }, + { 0x3937, 0x00 }, + { 0x30ac, 0x00 }, +}; + +static const char * const imx319_test_pattern_menu[] = { + "Disabled", + "100% color bars", + "Solid color", + "Fade to gray color bars", + "PN9" +}; + +/* supported link frequencies */ +static const s64 link_freq_menu_items[] = { + IMX319_LINK_FREQ_DEFAULT, +}; + +/* Mode configs */ +static const struct imx319_mode supported_modes[] = { + { + .width = 3280, + .height = 2464, + .fll_def = 3242, + .fll_min = 3242, + .llp = 3968, + .link_freq_index = IMX319_LINK_FREQ_INDEX, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_3280x2464_regs), + .regs = mode_3280x2464_regs, + }, + }, + { + .width = 3264, + .height = 2448, + .fll_def = 3242, + .fll_min = 3242, + .llp = 3968, + .link_freq_index = IMX319_LINK_FREQ_INDEX, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_3264x2448_regs), + .regs = mode_3264x2448_regs, + }, + }, + { + .width = 1936, + .height = 1096, + .fll_def = 3242, + .fll_min = 3242, + .llp = 3968, + .link_freq_index = IMX319_LINK_FREQ_INDEX, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_1936x1096_regs), + .regs = mode_1936x1096_regs, + }, + }, + { + .width = 1920, + .height = 1080, + .fll_def = 3242, + .fll_min = 3242, + .llp = 3968, + .link_freq_index = IMX319_LINK_FREQ_INDEX, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_1920x1080_regs), + .regs = mode_1920x1080_regs, + }, + }, + { + .width = 1640, + .height = 1232, + .fll_def = 5146, + .fll_min = 5146, + .llp = 2500, + .link_freq_index = IMX319_LINK_FREQ_INDEX, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_1640x1232_regs), + .regs = mode_1640x1232_regs, + }, + }, + { + .width = 1640, + .height = 922, + .fll_def = 5146, + .fll_min = 5146, + .llp = 2500, + .link_freq_index = IMX319_LINK_FREQ_INDEX, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_1640x922_regs), + .regs = mode_1640x922_regs, + }, + }, + { + .width = 1296, + .height = 736, + .fll_def = 5146, + .fll_min = 5146, + .llp = 2500, + .link_freq_index = IMX319_LINK_FREQ_INDEX, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_1296x736_regs), + .regs = mode_1296x736_regs, + }, + }, + { + .width = 1280, + .height = 720, + .fll_def = 5146, + .fll_min = 5146, + .llp = 2500, + .link_freq_index = IMX319_LINK_FREQ_INDEX, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_1280x720_regs), + .regs = mode_1280x720_regs, + }, + }, +}; + +static inline struct imx319 *to_imx319(struct v4l2_subdev *_sd) +{ + return container_of(_sd, struct imx319, sd); +} + +/* Get bayer order based on flip setting. */ +static u32 imx319_get_format_code(struct imx319 *imx319) +{ + /* + * Only one bayer order is supported. + * It depends on the flip settings. + */ + u32 code; + static const u32 codes[2][2] = { + { MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SGRBG10_1X10, }, + { MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SBGGR10_1X10, }, + }; + + lockdep_assert_held(&imx319->mutex); + code = codes[imx319->vflip->val][imx319->hflip->val]; + + return code; +} + +/* Read registers up to 4 at a time */ +static int imx319_read_reg(struct imx319 *imx319, u16 reg, u32 len, u32 *val) +{ + struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd); + struct i2c_msg msgs[2]; + u8 addr_buf[2]; + u8 data_buf[4] = { 0 }; + int ret; + + if (len > 4) + return -EINVAL; + + put_unaligned_be16(reg, addr_buf); + /* Write register address */ + msgs[0].addr = client->addr; + msgs[0].flags = 0; + msgs[0].len = ARRAY_SIZE(addr_buf); + msgs[0].buf = addr_buf; + + /* Read data from register */ + msgs[1].addr = client->addr; + msgs[1].flags = I2C_M_RD; + msgs[1].len = len; + msgs[1].buf = &data_buf[4 - len]; + + ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + if (ret != ARRAY_SIZE(msgs)) + return -EIO; + + *val = get_unaligned_be32(data_buf); + + return 0; +} + +/* Write registers up to 4 at a time */ +static int imx319_write_reg(struct imx319 *imx319, u16 reg, u32 len, u32 val) +{ + struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd); + u8 buf[6]; + + if (len > 4) + return -EINVAL; + + put_unaligned_be16(reg, buf); + put_unaligned_be32(val << (8 * (4 - len)), buf + 2); + if (i2c_master_send(client, buf, len + 2) != len + 2) + return -EIO; + + return 0; +} + +/* Write a list of registers */ +static int imx319_write_regs(struct imx319 *imx319, + const struct imx319_reg *regs, u32 len) +{ + struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd); + int ret; + u32 i; + + for (i = 0; i < len; i++) { + ret = imx319_write_reg(imx319, regs[i].address, 1, regs[i].val); + if (ret) { + dev_err_ratelimited(&client->dev, + "write reg 0x%4.4x return err %d", + regs[i].address, ret); + return ret; + } + } + + return 0; +} + +/* Open sub-device */ +static int imx319_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + struct imx319 *imx319 = to_imx319(sd); + struct v4l2_mbus_framefmt *try_fmt = + v4l2_subdev_get_try_format(sd, fh->pad, 0); + + mutex_lock(&imx319->mutex); + + /* Initialize try_fmt */ + try_fmt->width = imx319->cur_mode->width; + try_fmt->height = imx319->cur_mode->height; + try_fmt->code = imx319_get_format_code(imx319); + try_fmt->field = V4L2_FIELD_NONE; + + mutex_unlock(&imx319->mutex); + + return 0; +} + +static int imx319_set_ctrl(struct v4l2_ctrl *ctrl) +{ + struct imx319 *imx319 = container_of(ctrl->handler, + struct imx319, ctrl_handler); + struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd); + s64 max; + int ret; + + /* Propagate change of current control to all related controls */ + switch (ctrl->id) { + case V4L2_CID_VBLANK: + /* Update max exposure while meeting expected vblanking */ + max = imx319->cur_mode->height + ctrl->val - 18; + __v4l2_ctrl_modify_range(imx319->exposure, + imx319->exposure->minimum, + max, imx319->exposure->step, max); + break; + } + + /* + * Applying V4L2 control value only happens + * when power is up for streaming + */ + if (!pm_runtime_get_if_in_use(&client->dev)) + return 0; + + switch (ctrl->id) { + case V4L2_CID_ANALOGUE_GAIN: + /* Analog gain = 1024/(1024 - ctrl->val) times */ + ret = imx319_write_reg(imx319, IMX319_REG_ANALOG_GAIN, 2, + ctrl->val); + break; + case V4L2_CID_DIGITAL_GAIN: + ret = imx319_write_reg(imx319, IMX319_REG_DIG_GAIN_GLOBAL, 2, + ctrl->val); + break; + case V4L2_CID_EXPOSURE: + ret = imx319_write_reg(imx319, IMX319_REG_EXPOSURE, 2, + ctrl->val); + break; + case V4L2_CID_VBLANK: + /* Update FLL that meets expected vertical blanking */ + ret = imx319_write_reg(imx319, IMX319_REG_FLL, 2, + imx319->cur_mode->height + ctrl->val); + break; + case V4L2_CID_TEST_PATTERN: + ret = imx319_write_reg(imx319, IMX319_REG_TEST_PATTERN, + 2, ctrl->val); + break; + case V4L2_CID_HFLIP: + case V4L2_CID_VFLIP: + ret = imx319_write_reg(imx319, IMX319_REG_ORIENTATION, 1, + imx319->hflip->val | + imx319->vflip->val << 1); + break; + default: + ret = -EINVAL; + dev_info(&client->dev, "ctrl(id:0x%x,val:0x%x) is not handled", + ctrl->id, ctrl->val); + break; + } + + pm_runtime_put(&client->dev); + + return ret; +} + +static const struct v4l2_ctrl_ops imx319_ctrl_ops = { + .s_ctrl = imx319_set_ctrl, +}; + +static int imx319_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_mbus_code_enum *code) +{ + struct imx319 *imx319 = to_imx319(sd); + + if (code->index > 0) + return -EINVAL; + + mutex_lock(&imx319->mutex); + code->code = imx319_get_format_code(imx319); + mutex_unlock(&imx319->mutex); + + return 0; +} + +static int imx319_enum_frame_size(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_size_enum *fse) +{ + struct imx319 *imx319 = to_imx319(sd); + + if (fse->index >= ARRAY_SIZE(supported_modes)) + return -EINVAL; + + mutex_lock(&imx319->mutex); + if (fse->code != imx319_get_format_code(imx319)) { + mutex_unlock(&imx319->mutex); + return -EINVAL; + } + mutex_unlock(&imx319->mutex); + + fse->min_width = supported_modes[fse->index].width; + fse->max_width = fse->min_width; + fse->min_height = supported_modes[fse->index].height; + fse->max_height = fse->min_height; + + return 0; +} + +static void imx319_update_pad_format(struct imx319 *imx319, + const struct imx319_mode *mode, + struct v4l2_subdev_format *fmt) +{ + fmt->format.width = mode->width; + fmt->format.height = mode->height; + fmt->format.code = imx319_get_format_code(imx319); + fmt->format.field = V4L2_FIELD_NONE; +} + +static int imx319_do_get_pad_format(struct imx319 *imx319, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *fmt) +{ + struct v4l2_mbus_framefmt *framefmt; + struct v4l2_subdev *sd = &imx319->sd; + + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { + framefmt = v4l2_subdev_get_try_format(sd, cfg, fmt->pad); + fmt->format = *framefmt; + } else { + imx319_update_pad_format(imx319, imx319->cur_mode, fmt); + } + + return 0; +} + +static int imx319_get_pad_format(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *fmt) +{ + struct imx319 *imx319 = to_imx319(sd); + int ret; + + mutex_lock(&imx319->mutex); + ret = imx319_do_get_pad_format(imx319, cfg, fmt); + mutex_unlock(&imx319->mutex); + + return ret; +} + +static int +imx319_set_pad_format(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *fmt) +{ + struct imx319 *imx319 = to_imx319(sd); + const struct imx319_mode *mode; + struct v4l2_mbus_framefmt *framefmt; + s32 vblank_def; + s32 vblank_min; + s64 h_blank; + u64 pixel_rate; + u32 height; + + mutex_lock(&imx319->mutex); + + /* + * Only one bayer order is supported. + * It depends on the flip settings. + */ + fmt->format.code = imx319_get_format_code(imx319); + + mode = v4l2_find_nearest_size(supported_modes, + ARRAY_SIZE(supported_modes), + width, height, + fmt->format.width, fmt->format.height); + imx319_update_pad_format(imx319, mode, fmt); + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { + framefmt = v4l2_subdev_get_try_format(sd, cfg, fmt->pad); + *framefmt = fmt->format; + } else { + imx319->cur_mode = mode; + pixel_rate = imx319->link_def_freq * 2 * 4; + do_div(pixel_rate, 10); + __v4l2_ctrl_s_ctrl_int64(imx319->pixel_rate, pixel_rate); + /* Update limits and set FPS to default */ + height = imx319->cur_mode->height; + vblank_def = imx319->cur_mode->fll_def - height; + vblank_min = imx319->cur_mode->fll_min - height; + height = IMX319_FLL_MAX - height; + __v4l2_ctrl_modify_range(imx319->vblank, vblank_min, height, 1, + vblank_def); + __v4l2_ctrl_s_ctrl(imx319->vblank, vblank_def); + h_blank = mode->llp - imx319->cur_mode->width; + /* + * Currently hblank is not changeable. + * So FPS control is done only by vblank. + */ + __v4l2_ctrl_modify_range(imx319->hblank, h_blank, + h_blank, 1, h_blank); + } + + mutex_unlock(&imx319->mutex); + + return 0; +} + +/* Start streaming */ +static int imx319_start_streaming(struct imx319 *imx319) +{ + struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd); + const struct imx319_reg_list *reg_list; + int ret; + + /* Global Setting */ + reg_list = &imx319_global_setting; + ret = imx319_write_regs(imx319, reg_list->regs, reg_list->num_of_regs); + if (ret) { + dev_err(&client->dev, "failed to set global settings"); + return ret; + } + + /* Apply default values of current mode */ + reg_list = &imx319->cur_mode->reg_list; + ret = imx319_write_regs(imx319, reg_list->regs, reg_list->num_of_regs); + if (ret) { + dev_err(&client->dev, "failed to set mode"); + return ret; + } + + /* set digital gain control to all color mode */ + ret = imx319_write_reg(imx319, IMX319_REG_DPGA_USE_GLOBAL_GAIN, 1, 1); + if (ret) + return ret; + + /* Apply customized values from user */ + ret = __v4l2_ctrl_handler_setup(imx319->sd.ctrl_handler); + if (ret) + return ret; + + return imx319_write_reg(imx319, IMX319_REG_MODE_SELECT, + 1, IMX319_MODE_STREAMING); +} + +/* Stop streaming */ +static int imx319_stop_streaming(struct imx319 *imx319) +{ + return imx319_write_reg(imx319, IMX319_REG_MODE_SELECT, + 1, IMX319_MODE_STANDBY); +} + +static int imx319_set_stream(struct v4l2_subdev *sd, int enable) +{ + struct imx319 *imx319 = to_imx319(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + int ret = 0; + + mutex_lock(&imx319->mutex); + if (imx319->streaming == enable) { + mutex_unlock(&imx319->mutex); + return 0; + } + + if (enable) { + ret = pm_runtime_get_sync(&client->dev); + if (ret < 0) { + pm_runtime_put_noidle(&client->dev); + goto err_unlock; + } + + /* + * Apply default & customized values + * and then start streaming. + */ + ret = imx319_start_streaming(imx319); + if (ret) + goto err_rpm_put; + } else { + imx319_stop_streaming(imx319); + pm_runtime_put(&client->dev); + } + + imx319->streaming = enable; + + /* vflip and hflip cannot change during streaming */ + __v4l2_ctrl_grab(imx319->vflip, enable); + __v4l2_ctrl_grab(imx319->hflip, enable); + + mutex_unlock(&imx319->mutex); + + return ret; + +err_rpm_put: + pm_runtime_put(&client->dev); +err_unlock: + mutex_unlock(&imx319->mutex); + + return ret; +} + +static int __maybe_unused imx319_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct imx319 *imx319 = to_imx319(sd); + + if (imx319->streaming) + imx319_stop_streaming(imx319); + + return 0; +} + +static int __maybe_unused imx319_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct imx319 *imx319 = to_imx319(sd); + int ret; + + if (imx319->streaming) { + ret = imx319_start_streaming(imx319); + if (ret) + goto error; + } + + return 0; + +error: + imx319_stop_streaming(imx319); + imx319->streaming = 0; + return ret; +} + +/* Verify chip ID */ +static int imx319_identify_module(struct imx319 *imx319) +{ + struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd); + int ret; + u32 val; + + ret = imx319_read_reg(imx319, IMX319_REG_CHIP_ID, 2, &val); + if (ret) + return ret; + + if (val != IMX319_CHIP_ID) { + dev_err(&client->dev, "chip id mismatch: %x!=%x", + IMX319_CHIP_ID, val); + return -EIO; + } + + return 0; +} + +static const struct v4l2_subdev_core_ops imx319_subdev_core_ops = { + .subscribe_event = v4l2_ctrl_subdev_subscribe_event, + .unsubscribe_event = v4l2_event_subdev_unsubscribe, +}; + +static const struct v4l2_subdev_video_ops imx319_video_ops = { + .s_stream = imx319_set_stream, +}; + +static const struct v4l2_subdev_pad_ops imx319_pad_ops = { + .enum_mbus_code = imx319_enum_mbus_code, + .get_fmt = imx319_get_pad_format, + .set_fmt = imx319_set_pad_format, + .enum_frame_size = imx319_enum_frame_size, +}; + +static const struct v4l2_subdev_ops imx319_subdev_ops = { + .core = &imx319_subdev_core_ops, + .video = &imx319_video_ops, + .pad = &imx319_pad_ops, +}; + +static const struct media_entity_operations imx319_subdev_entity_ops = { + .link_validate = v4l2_subdev_link_validate, +}; + +static const struct v4l2_subdev_internal_ops imx319_internal_ops = { + .open = imx319_open, +}; + +/* Initialize control handlers */ +static int imx319_init_controls(struct imx319 *imx319) +{ + struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd); + struct v4l2_ctrl_handler *ctrl_hdlr; + s64 exposure_max; + s64 vblank_def; + s64 vblank_min; + s64 hblank; + u64 pixel_rate; + const struct imx319_mode *mode; + u32 max; + int ret; + + ctrl_hdlr = &imx319->ctrl_handler; + ret = v4l2_ctrl_handler_init(ctrl_hdlr, 10); + if (ret) + return ret; + + ctrl_hdlr->lock = &imx319->mutex; + max = ARRAY_SIZE(link_freq_menu_items) - 1; + imx319->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx319_ctrl_ops, + V4L2_CID_LINK_FREQ, max, 0, + link_freq_menu_items); + if (imx319->link_freq) + imx319->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; + + /* pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample */ + pixel_rate = imx319->link_def_freq * 2 * 4; + do_div(pixel_rate, 10); + /* By default, PIXEL_RATE is read only */ + imx319->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops, + V4L2_CID_PIXEL_RATE, pixel_rate, + pixel_rate, 1, pixel_rate); + + /* Initial vblank/hblank/exposure parameters based on current mode */ + mode = imx319->cur_mode; + vblank_def = mode->fll_def - mode->height; + vblank_min = mode->fll_min - mode->height; + imx319->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops, + V4L2_CID_VBLANK, vblank_min, + IMX319_FLL_MAX - mode->height, + 1, vblank_def); + + hblank = mode->llp - mode->width; + imx319->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops, + V4L2_CID_HBLANK, hblank, hblank, + 1, hblank); + if (imx319->hblank) + imx319->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; + + /* fll >= exposure time + adjust parameter (default value is 18) */ + exposure_max = mode->fll_def - 18; + imx319->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops, + V4L2_CID_EXPOSURE, + IMX319_EXPOSURE_MIN, exposure_max, + IMX319_EXPOSURE_STEP, + IMX319_EXPOSURE_DEFAULT); + + imx319->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops, + V4L2_CID_HFLIP, 0, 1, 1, 0); + imx319->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops, + V4L2_CID_VFLIP, 0, 1, 1, 0); + + v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops, V4L2_CID_ANALOGUE_GAIN, + IMX319_ANA_GAIN_MIN, IMX319_ANA_GAIN_MAX, + IMX319_ANA_GAIN_STEP, IMX319_ANA_GAIN_DEFAULT); + + /* Digital gain */ + v4l2_ctrl_new_std(ctrl_hdlr, &imx319_ctrl_ops, V4L2_CID_DIGITAL_GAIN, + IMX319_DGTL_GAIN_MIN, IMX319_DGTL_GAIN_MAX, + IMX319_DGTL_GAIN_STEP, IMX319_DGTL_GAIN_DEFAULT); + + v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx319_ctrl_ops, + V4L2_CID_TEST_PATTERN, + ARRAY_SIZE(imx319_test_pattern_menu) - 1, + 0, 0, imx319_test_pattern_menu); + if (ctrl_hdlr->error) { + ret = ctrl_hdlr->error; + dev_err(&client->dev, "control init failed: %d", ret); + goto error; + } + + imx319->sd.ctrl_handler = ctrl_hdlr; + + return 0; + +error: + v4l2_ctrl_handler_free(ctrl_hdlr); + + return ret; +} + +static struct imx319_hwcfg *imx319_get_hwcfg(struct device *dev) +{ + struct imx319_hwcfg *cfg; + struct v4l2_fwnode_endpoint bus_cfg = { + .bus_type = V4L2_MBUS_CSI2_DPHY + }; + struct fwnode_handle *ep; + struct fwnode_handle *fwnode = dev_fwnode(dev); + unsigned int i; + int ret; + + if (!fwnode) + return NULL; + + ep = fwnode_graph_get_next_endpoint(fwnode, NULL); + if (!ep) + return NULL; + + ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg); + if (ret) + goto out_err; + + cfg = devm_kzalloc(dev, sizeof(*cfg), GFP_KERNEL); + if (!cfg) + goto out_err; + + ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency", + &cfg->ext_clk); + if (ret) { + dev_err(dev, "can't get clock frequency"); + goto out_err; + } + + dev_dbg(dev, "ext clk: %d", cfg->ext_clk); + if (cfg->ext_clk != IMX319_EXT_CLK) { + dev_err(dev, "external clock %d is not supported", + cfg->ext_clk); + goto out_err; + } + + dev_dbg(dev, "num of link freqs: %d", bus_cfg.nr_of_link_frequencies); + if (!bus_cfg.nr_of_link_frequencies) { + dev_warn(dev, "no link frequencies defined"); + goto out_err; + } + + cfg->nr_of_link_freqs = bus_cfg.nr_of_link_frequencies; + cfg->link_freqs = devm_kcalloc(dev, + bus_cfg.nr_of_link_frequencies + 1, + sizeof(*cfg->link_freqs), GFP_KERNEL); + if (!cfg->link_freqs) + goto out_err; + + for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) { + cfg->link_freqs[i] = bus_cfg.link_frequencies[i]; + dev_dbg(dev, "link_freq[%d] = %lld", i, cfg->link_freqs[i]); + } + + v4l2_fwnode_endpoint_free(&bus_cfg); + fwnode_handle_put(ep); + return cfg; + +out_err: + v4l2_fwnode_endpoint_free(&bus_cfg); + fwnode_handle_put(ep); + return NULL; +} + +static int imx319_probe(struct i2c_client *client) +{ + struct imx319 *imx319; + int ret; + u32 i; + + imx319 = devm_kzalloc(&client->dev, sizeof(*imx319), GFP_KERNEL); + if (!imx319) + return -ENOMEM; + + mutex_init(&imx319->mutex); + + /* Initialize subdev */ + v4l2_i2c_subdev_init(&imx319->sd, client, &imx319_subdev_ops); + + /* Check module identity */ + ret = imx319_identify_module(imx319); + if (ret) { + dev_err(&client->dev, "failed to find sensor: %d", ret); + goto error_probe; + } + + imx319->hwcfg = imx319_get_hwcfg(&client->dev); + if (!imx319->hwcfg) { + dev_err(&client->dev, "failed to get hwcfg"); + ret = -ENODEV; + goto error_probe; + } + + imx319->link_def_freq = link_freq_menu_items[IMX319_LINK_FREQ_INDEX]; + for (i = 0; i < imx319->hwcfg->nr_of_link_freqs; i++) { + if (imx319->hwcfg->link_freqs[i] == imx319->link_def_freq) { + dev_dbg(&client->dev, "link freq index %d matched", i); + break; + } + } + + if (i == imx319->hwcfg->nr_of_link_freqs) { + dev_err(&client->dev, "no link frequency supported"); + ret = -EINVAL; + goto error_probe; + } + + /* Set default mode to max resolution */ + imx319->cur_mode = &supported_modes[0]; + + ret = imx319_init_controls(imx319); + if (ret) { + dev_err(&client->dev, "failed to init controls: %d", ret); + goto error_probe; + } + + /* Initialize subdev */ + imx319->sd.internal_ops = &imx319_internal_ops; + imx319->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | + V4L2_SUBDEV_FL_HAS_EVENTS; + imx319->sd.entity.ops = &imx319_subdev_entity_ops; + imx319->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; + + /* Initialize source pad */ + imx319->pad.flags = MEDIA_PAD_FL_SOURCE; + ret = media_entity_pads_init(&imx319->sd.entity, 1, &imx319->pad); + if (ret) { + dev_err(&client->dev, "failed to init entity pads: %d", ret); + goto error_handler_free; + } + + ret = v4l2_async_register_subdev_sensor_common(&imx319->sd); + if (ret < 0) + goto error_media_entity; + + /* + * Device is already turned on by i2c-core with ACPI domain PM. + * Enable runtime PM and turn off the device. + */ + pm_runtime_set_active(&client->dev); + pm_runtime_enable(&client->dev); + pm_runtime_idle(&client->dev); + + return 0; + +error_media_entity: + media_entity_cleanup(&imx319->sd.entity); + +error_handler_free: + v4l2_ctrl_handler_free(imx319->sd.ctrl_handler); + +error_probe: + mutex_destroy(&imx319->mutex); + + return ret; +} + +static int imx319_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct imx319 *imx319 = to_imx319(sd); + + v4l2_async_unregister_subdev(sd); + media_entity_cleanup(&sd->entity); + v4l2_ctrl_handler_free(sd->ctrl_handler); + + pm_runtime_disable(&client->dev); + pm_runtime_set_suspended(&client->dev); + + mutex_destroy(&imx319->mutex); + + return 0; +} + +static const struct dev_pm_ops imx319_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(imx319_suspend, imx319_resume) +}; + +static const struct acpi_device_id imx319_acpi_ids[] = { + { "SONY319A" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(acpi, imx319_acpi_ids); + +static struct i2c_driver imx319_i2c_driver = { + .driver = { + .name = "imx319", + .pm = &imx319_pm_ops, + .acpi_match_table = ACPI_PTR(imx319_acpi_ids), + }, + .probe_new = imx319_probe, + .remove = imx319_remove, +}; +module_i2c_driver(imx319_i2c_driver); + +MODULE_AUTHOR("Qiu, Tianshu <tian.shu.qiu@intel.com>"); +MODULE_AUTHOR("Rapolu, Chiranjeevi <chiranjeevi.rapolu@intel.com>"); +MODULE_AUTHOR("Bingbu Cao <bingbu.cao@intel.com>"); +MODULE_AUTHOR("Yang, Hyungwoo <hyungwoo.yang@intel.com>"); +MODULE_DESCRIPTION("Sony imx319 sensor driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/i2c/imx355.c b/drivers/media/i2c/imx355.c new file mode 100644 index 000000000000..20c8eea5db4b --- /dev/null +++ b/drivers/media/i2c/imx355.c @@ -0,0 +1,1860 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Intel Corporation + +#include <asm/unaligned.h> +#include <linux/acpi.h> +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/pm_runtime.h> +#include <media/v4l2-ctrls.h> +#include <media/v4l2-device.h> +#include <media/v4l2-event.h> +#include <media/v4l2-fwnode.h> + +#define IMX355_REG_MODE_SELECT 0x0100 +#define IMX355_MODE_STANDBY 0x00 +#define IMX355_MODE_STREAMING 0x01 + +/* Chip ID */ +#define IMX355_REG_CHIP_ID 0x0016 +#define IMX355_CHIP_ID 0x0355 + +/* V_TIMING internal */ +#define IMX355_REG_FLL 0x0340 +#define IMX355_FLL_MAX 0xffff + +/* Exposure control */ +#define IMX355_REG_EXPOSURE 0x0202 +#define IMX355_EXPOSURE_MIN 1 +#define IMX355_EXPOSURE_STEP 1 +#define IMX355_EXPOSURE_DEFAULT 0x0282 + +/* Analog gain control */ +#define IMX355_REG_ANALOG_GAIN 0x0204 +#define IMX355_ANA_GAIN_MIN 0 +#define IMX355_ANA_GAIN_MAX 960 +#define IMX355_ANA_GAIN_STEP 1 +#define IMX355_ANA_GAIN_DEFAULT 0 + +/* Digital gain control */ +#define IMX355_REG_DPGA_USE_GLOBAL_GAIN 0x3070 +#define IMX355_REG_DIG_GAIN_GLOBAL 0x020e +#define IMX355_DGTL_GAIN_MIN 256 +#define IMX355_DGTL_GAIN_MAX 4095 +#define IMX355_DGTL_GAIN_STEP 1 +#define IMX355_DGTL_GAIN_DEFAULT 256 + +/* Test Pattern Control */ +#define IMX355_REG_TEST_PATTERN 0x0600 +#define IMX355_TEST_PATTERN_DISABLED 0 +#define IMX355_TEST_PATTERN_SOLID_COLOR 1 +#define IMX355_TEST_PATTERN_COLOR_BARS 2 +#define IMX355_TEST_PATTERN_GRAY_COLOR_BARS 3 +#define IMX355_TEST_PATTERN_PN9 4 + +/* Flip Control */ +#define IMX355_REG_ORIENTATION 0x0101 + +/* default link frequency and external clock */ +#define IMX355_LINK_FREQ_DEFAULT 360000000 +#define IMX355_EXT_CLK 19200000 +#define IMX355_LINK_FREQ_INDEX 0 + +struct imx355_reg { + u16 address; + u8 val; +}; + +struct imx355_reg_list { + u32 num_of_regs; + const struct imx355_reg *regs; +}; + +/* Mode : resolution and related config&values */ +struct imx355_mode { + /* Frame width */ + u32 width; + /* Frame height */ + u32 height; + + /* V-timing */ + u32 fll_def; + u32 fll_min; + + /* H-timing */ + u32 llp; + + /* index of link frequency */ + u32 link_freq_index; + + /* Default register values */ + struct imx355_reg_list reg_list; +}; + +struct imx355_hwcfg { + u32 ext_clk; /* sensor external clk */ + s64 *link_freqs; /* CSI-2 link frequencies */ + unsigned int nr_of_link_freqs; +}; + +struct imx355 { + struct v4l2_subdev sd; + struct media_pad pad; + + struct v4l2_ctrl_handler ctrl_handler; + /* V4L2 Controls */ + struct v4l2_ctrl *link_freq; + struct v4l2_ctrl *pixel_rate; + struct v4l2_ctrl *vblank; + struct v4l2_ctrl *hblank; + struct v4l2_ctrl *exposure; + struct v4l2_ctrl *vflip; + struct v4l2_ctrl *hflip; + + /* Current mode */ + const struct imx355_mode *cur_mode; + + struct imx355_hwcfg *hwcfg; + s64 link_def_freq; /* CSI-2 link default frequency */ + + /* + * Mutex for serialized access: + * Protect sensor set pad format and start/stop streaming safely. + * Protect access to sensor v4l2 controls. + */ + struct mutex mutex; + + /* Streaming on/off */ + bool streaming; +}; + +static const struct imx355_reg imx355_global_regs[] = { + { 0x0136, 0x13 }, + { 0x0137, 0x33 }, + { 0x304e, 0x03 }, + { 0x4348, 0x16 }, + { 0x4350, 0x19 }, + { 0x4408, 0x0a }, + { 0x440c, 0x0b }, + { 0x4411, 0x5f }, + { 0x4412, 0x2c }, + { 0x4623, 0x00 }, + { 0x462c, 0x0f }, + { 0x462d, 0x00 }, + { 0x462e, 0x00 }, + { 0x4684, 0x54 }, + { 0x480a, 0x07 }, + { 0x4908, 0x07 }, + { 0x4909, 0x07 }, + { 0x490d, 0x0a }, + { 0x491e, 0x0f }, + { 0x4921, 0x06 }, + { 0x4923, 0x28 }, + { 0x4924, 0x28 }, + { 0x4925, 0x29 }, + { 0x4926, 0x29 }, + { 0x4927, 0x1f }, + { 0x4928, 0x20 }, + { 0x4929, 0x20 }, + { 0x492a, 0x20 }, + { 0x492c, 0x05 }, + { 0x492d, 0x06 }, + { 0x492e, 0x06 }, + { 0x492f, 0x06 }, + { 0x4930, 0x03 }, + { 0x4931, 0x04 }, + { 0x4932, 0x04 }, + { 0x4933, 0x05 }, + { 0x595e, 0x01 }, + { 0x5963, 0x01 }, + { 0x3030, 0x01 }, + { 0x3031, 0x01 }, + { 0x3045, 0x01 }, + { 0x4010, 0x00 }, + { 0x4011, 0x00 }, + { 0x4012, 0x00 }, + { 0x4013, 0x01 }, + { 0x68a8, 0xfe }, + { 0x68a9, 0xff }, + { 0x6888, 0x00 }, + { 0x6889, 0x00 }, + { 0x68b0, 0x00 }, + { 0x3058, 0x00 }, + { 0x305a, 0x00 }, +}; + +static const struct imx355_reg_list imx355_global_setting = { + .num_of_regs = ARRAY_SIZE(imx355_global_regs), + .regs = imx355_global_regs, +}; + +static const struct imx355_reg mode_3268x2448_regs[] = { + { 0x0112, 0x0a }, + { 0x0113, 0x0a }, + { 0x0114, 0x03 }, + { 0x0342, 0x0e }, + { 0x0343, 0x58 }, + { 0x0340, 0x0a }, + { 0x0341, 0x37 }, + { 0x0344, 0x00 }, + { 0x0345, 0x08 }, + { 0x0346, 0x00 }, + { 0x0347, 0x08 }, + { 0x0348, 0x0c }, + { 0x0349, 0xcb }, + { 0x034a, 0x09 }, + { 0x034b, 0x97 }, + { 0x0220, 0x00 }, + { 0x0222, 0x01 }, + { 0x0900, 0x00 }, + { 0x0901, 0x11 }, + { 0x0902, 0x00 }, + { 0x034c, 0x0c }, + { 0x034d, 0xc4 }, + { 0x034e, 0x09 }, + { 0x034f, 0x90 }, + { 0x0301, 0x05 }, + { 0x0303, 0x01 }, + { 0x0305, 0x02 }, + { 0x0306, 0x00 }, + { 0x0307, 0x78 }, + { 0x030b, 0x01 }, + { 0x030d, 0x02 }, + { 0x030e, 0x00 }, + { 0x030f, 0x4b }, + { 0x0310, 0x00 }, + { 0x0700, 0x00 }, + { 0x0701, 0x10 }, + { 0x0820, 0x0b }, + { 0x0821, 0x40 }, + { 0x3088, 0x04 }, + { 0x6813, 0x02 }, + { 0x6835, 0x07 }, + { 0x6836, 0x01 }, + { 0x6837, 0x04 }, + { 0x684d, 0x07 }, + { 0x684e, 0x01 }, + { 0x684f, 0x04 }, +}; + +static const struct imx355_reg mode_3264x2448_regs[] = { + { 0x0112, 0x0a }, + { 0x0113, 0x0a }, + { 0x0114, 0x03 }, + { 0x0342, 0x0e }, + { 0x0343, 0x58 }, + { 0x0340, 0x0a }, + { 0x0341, 0x37 }, + { 0x0344, 0x00 }, + { 0x0345, 0x08 }, + { 0x0346, 0x00 }, + { 0x0347, 0x08 }, + { 0x0348, 0x0c }, + { 0x0349, 0xc7 }, + { 0x034a, 0x09 }, + { 0x034b, 0x97 }, + { 0x0220, 0x00 }, + { 0x0222, 0x01 }, + { 0x0900, 0x00 }, + { 0x0901, 0x11 }, + { 0x0902, 0x00 }, + { 0x034c, 0x0c }, + { 0x034d, 0xc0 }, + { 0x034e, 0x09 }, + { 0x034f, 0x90 }, + { 0x0301, 0x05 }, + { 0x0303, 0x01 }, + { 0x0305, 0x02 }, + { 0x0306, 0x00 }, + { 0x0307, 0x78 }, + { 0x030b, 0x01 }, + { 0x030d, 0x02 }, + { 0x030e, 0x00 }, + { 0x030f, 0x4b }, + { 0x0310, 0x00 }, + { 0x0700, 0x00 }, + { 0x0701, 0x10 }, + { 0x0820, 0x0b }, + { 0x0821, 0x40 }, + { 0x3088, 0x04 }, + { 0x6813, 0x02 }, + { 0x6835, 0x07 }, + { 0x6836, 0x01 }, + { 0x6837, 0x04 }, + { 0x684d, 0x07 }, + { 0x684e, 0x01 }, + { 0x684f, 0x04 }, +}; + +static const struct imx355_reg mode_3280x2464_regs[] = { + { 0x0112, 0x0a }, + { 0x0113, 0x0a }, + { 0x0114, 0x03 }, + { 0x0342, 0x0e }, + { 0x0343, 0x58 }, + { 0x0340, 0x0a }, + { 0x0341, 0x37 }, + { 0x0344, 0x00 }, + { 0x0345, 0x00 }, + { 0x0346, 0x00 }, + { 0x0347, 0x00 }, + { 0x0348, 0x0c }, + { 0x0349, 0xcf }, + { 0x034a, 0x09 }, + { 0x034b, 0x9f }, + { 0x0220, 0x00 }, + { 0x0222, 0x01 }, + { 0x0900, 0x00 }, + { 0x0901, 0x11 }, + { 0x0902, 0x00 }, + { 0x034c, 0x0c }, + { 0x034d, 0xd0 }, + { 0x034e, 0x09 }, + { 0x034f, 0xa0 }, + { 0x0301, 0x05 }, + { 0x0303, 0x01 }, + { 0x0305, 0x02 }, + { 0x0306, 0x00 }, + { 0x0307, 0x78 }, + { 0x030b, 0x01 }, + { 0x030d, 0x02 }, + { 0x030e, 0x00 }, + { 0x030f, 0x4b }, + { 0x0310, 0x00 }, + { 0x0700, 0x00 }, + { 0x0701, 0x10 }, + { 0x0820, 0x0b }, + { 0x0821, 0x40 }, + { 0x3088, 0x04 }, + { 0x6813, 0x02 }, + { 0x6835, 0x07 }, + { 0x6836, 0x01 }, + { 0x6837, 0x04 }, + { 0x684d, 0x07 }, + { 0x684e, 0x01 }, + { 0x684f, 0x04 }, +}; + +static const struct imx355_reg mode_1940x1096_regs[] = { + { 0x0112, 0x0a }, + { 0x0113, 0x0a }, + { 0x0114, 0x03 }, + { 0x0342, 0x0e }, + { 0x0343, 0x58 }, + { 0x0340, 0x05 }, + { 0x0341, 0x1a }, + { 0x0344, 0x02 }, + { 0x0345, 0xa0 }, + { 0x0346, 0x02 }, + { 0x0347, 0xac }, + { 0x0348, 0x0a }, + { 0x0349, 0x33 }, + { 0x034a, 0x06 }, + { 0x034b, 0xf3 }, + { 0x0220, 0x00 }, + { 0x0222, 0x01 }, + { 0x0900, 0x00 }, + { 0x0901, 0x11 }, + { 0x0902, 0x00 }, + { 0x034c, 0x07 }, + { 0x034d, 0x94 }, + { 0x034e, 0x04 }, + { 0x034f, 0x48 }, + { 0x0301, 0x05 }, + { 0x0303, 0x01 }, + { 0x0305, 0x02 }, + { 0x0306, 0x00 }, + { 0x0307, 0x78 }, + { 0x030b, 0x01 }, + { 0x030d, 0x02 }, + { 0x030e, 0x00 }, + { 0x030f, 0x4b }, + { 0x0310, 0x00 }, + { 0x0700, 0x00 }, + { 0x0701, 0x10 }, + { 0x0820, 0x0b }, + { 0x0821, 0x40 }, + { 0x3088, 0x04 }, + { 0x6813, 0x02 }, + { 0x6835, 0x07 }, + { 0x6836, 0x01 }, + { 0x6837, 0x04 }, + { 0x684d, 0x07 }, + { 0x684e, 0x01 }, + { 0x684f, 0x04 }, +}; + +static const struct imx355_reg mode_1936x1096_regs[] = { + { 0x0112, 0x0a }, + { 0x0113, 0x0a }, + { 0x0114, 0x03 }, + { 0x0342, 0x0e }, + { 0x0343, 0x58 }, + { 0x0340, 0x05 }, + { 0x0341, 0x1a }, + { 0x0344, 0x02 }, + { 0x0345, 0xa0 }, + { 0x0346, 0x02 }, + { 0x0347, 0xac }, + { 0x0348, 0x0a }, + { 0x0349, 0x2f }, + { 0x034a, 0x06 }, + { 0x034b, 0xf3 }, + { 0x0220, 0x00 }, + { 0x0222, 0x01 }, + { 0x0900, 0x00 }, + { 0x0901, 0x11 }, + { 0x0902, 0x00 }, + { 0x034c, 0x07 }, + { 0x034d, 0x90 }, + { 0x034e, 0x04 }, + { 0x034f, 0x48 }, + { 0x0301, 0x05 }, + { 0x0303, 0x01 }, + { 0x0305, 0x02 }, + { 0x0306, 0x00 }, + { 0x0307, 0x78 }, + { 0x030b, 0x01 }, + { 0x030d, 0x02 }, + { 0x030e, 0x00 }, + { 0x030f, 0x4b }, + { 0x0310, 0x00 }, + { 0x0700, 0x00 }, + { 0x0701, 0x10 }, + { 0x0820, 0x0b }, + { 0x0821, 0x40 }, + { 0x3088, 0x04 }, + { 0x6813, 0x02 }, + { 0x6835, 0x07 }, + { 0x6836, 0x01 }, + { 0x6837, 0x04 }, + { 0x684d, 0x07 }, + { 0x684e, 0x01 }, + { 0x684f, 0x04 }, +}; + +static const struct imx355_reg mode_1924x1080_regs[] = { + { 0x0112, 0x0a }, + { 0x0113, 0x0a }, + { 0x0114, 0x03 }, + { 0x0342, 0x0e }, + { 0x0343, 0x58 }, + { 0x0340, 0x05 }, + { 0x0341, 0x1a }, + { 0x0344, 0x02 }, + { 0x0345, 0xa8 }, + { 0x0346, 0x02 }, + { 0x0347, 0xb4 }, + { 0x0348, 0x0a }, + { 0x0349, 0x2b }, + { 0x034a, 0x06 }, + { 0x034b, 0xeb }, + { 0x0220, 0x00 }, + { 0x0222, 0x01 }, + { 0x0900, 0x00 }, + { 0x0901, 0x11 }, + { 0x0902, 0x00 }, + { 0x034c, 0x07 }, + { 0x034d, 0x84 }, + { 0x034e, 0x04 }, + { 0x034f, 0x38 }, + { 0x0301, 0x05 }, + { 0x0303, 0x01 }, + { 0x0305, 0x02 }, + { 0x0306, 0x00 }, + { 0x0307, 0x78 }, + { 0x030b, 0x01 }, + { 0x030d, 0x02 }, + { 0x030e, 0x00 }, + { 0x030f, 0x4b }, + { 0x0310, 0x00 }, + { 0x0700, 0x00 }, + { 0x0701, 0x10 }, + { 0x0820, 0x0b }, + { 0x0821, 0x40 }, + { 0x3088, 0x04 }, + { 0x6813, 0x02 }, + { 0x6835, 0x07 }, + { 0x6836, 0x01 }, + { 0x6837, 0x04 }, + { 0x684d, 0x07 }, + { 0x684e, 0x01 }, + { 0x684f, 0x04 }, +}; + +static const struct imx355_reg mode_1920x1080_regs[] = { + { 0x0112, 0x0a }, + { 0x0113, 0x0a }, + { 0x0114, 0x03 }, + { 0x0342, 0x0e }, + { 0x0343, 0x58 }, + { 0x0340, 0x05 }, + { 0x0341, 0x1a }, + { 0x0344, 0x02 }, + { 0x0345, 0xa8 }, + { 0x0346, 0x02 }, + { 0x0347, 0xb4 }, + { 0x0348, 0x0a }, + { 0x0349, 0x27 }, + { 0x034a, 0x06 }, + { 0x034b, 0xeb }, + { 0x0220, 0x00 }, + { 0x0222, 0x01 }, + { 0x0900, 0x00 }, + { 0x0901, 0x11 }, + { 0x0902, 0x00 }, + { 0x034c, 0x07 }, + { 0x034d, 0x80 }, + { 0x034e, 0x04 }, + { 0x034f, 0x38 }, + { 0x0301, 0x05 }, + { 0x0303, 0x01 }, + { 0x0305, 0x02 }, + { 0x0306, 0x00 }, + { 0x0307, 0x78 }, + { 0x030b, 0x01 }, + { 0x030d, 0x02 }, + { 0x030e, 0x00 }, + { 0x030f, 0x4b }, + { 0x0310, 0x00 }, + { 0x0700, 0x00 }, + { 0x0701, 0x10 }, + { 0x0820, 0x0b }, + { 0x0821, 0x40 }, + { 0x3088, 0x04 }, + { 0x6813, 0x02 }, + { 0x6835, 0x07 }, + { 0x6836, 0x01 }, + { 0x6837, 0x04 }, + { 0x684d, 0x07 }, + { 0x684e, 0x01 }, + { 0x684f, 0x04 }, +}; + +static const struct imx355_reg mode_1640x1232_regs[] = { + { 0x0112, 0x0a }, + { 0x0113, 0x0a }, + { 0x0114, 0x03 }, + { 0x0342, 0x07 }, + { 0x0343, 0x2c }, + { 0x0340, 0x05 }, + { 0x0341, 0x1a }, + { 0x0344, 0x00 }, + { 0x0345, 0x00 }, + { 0x0346, 0x00 }, + { 0x0347, 0x00 }, + { 0x0348, 0x0c }, + { 0x0349, 0xcf }, + { 0x034a, 0x09 }, + { 0x034b, 0x9f }, + { 0x0220, 0x00 }, + { 0x0222, 0x01 }, + { 0x0900, 0x01 }, + { 0x0901, 0x22 }, + { 0x0902, 0x00 }, + { 0x034c, 0x06 }, + { 0x034d, 0x68 }, + { 0x034e, 0x04 }, + { 0x034f, 0xd0 }, + { 0x0301, 0x05 }, + { 0x0303, 0x01 }, + { 0x0305, 0x02 }, + { 0x0306, 0x00 }, + { 0x0307, 0x78 }, + { 0x030b, 0x01 }, + { 0x030d, 0x02 }, + { 0x030e, 0x00 }, + { 0x030f, 0x4b }, + { 0x0310, 0x00 }, + { 0x0700, 0x00 }, + { 0x0701, 0x10 }, + { 0x0820, 0x0b }, + { 0x0821, 0x40 }, + { 0x3088, 0x04 }, + { 0x6813, 0x02 }, + { 0x6835, 0x07 }, + { 0x6836, 0x01 }, + { 0x6837, 0x04 }, + { 0x684d, 0x07 }, + { 0x684e, 0x01 }, + { 0x684f, 0x04 }, +}; + +static const struct imx355_reg mode_1640x922_regs[] = { + { 0x0112, 0x0a }, + { 0x0113, 0x0a }, + { 0x0114, 0x03 }, + { 0x0342, 0x07 }, + { 0x0343, 0x2c }, + { 0x0340, 0x05 }, + { 0x0341, 0x1a }, + { 0x0344, 0x00 }, + { 0x0345, 0x00 }, + { 0x0346, 0x01 }, + { 0x0347, 0x30 }, + { 0x0348, 0x0c }, + { 0x0349, 0xcf }, + { 0x034a, 0x08 }, + { 0x034b, 0x63 }, + { 0x0220, 0x00 }, + { 0x0222, 0x01 }, + { 0x0900, 0x01 }, + { 0x0901, 0x22 }, + { 0x0902, 0x00 }, + { 0x034c, 0x06 }, + { 0x034d, 0x68 }, + { 0x034e, 0x03 }, + { 0x034f, 0x9a }, + { 0x0301, 0x05 }, + { 0x0303, 0x01 }, + { 0x0305, 0x02 }, + { 0x0306, 0x00 }, + { 0x0307, 0x78 }, + { 0x030b, 0x01 }, + { 0x030d, 0x02 }, + { 0x030e, 0x00 }, + { 0x030f, 0x4b }, + { 0x0310, 0x00 }, + { 0x0700, 0x00 }, + { 0x0701, 0x10 }, + { 0x0820, 0x0b }, + { 0x0821, 0x40 }, + { 0x3088, 0x04 }, + { 0x6813, 0x02 }, + { 0x6835, 0x07 }, + { 0x6836, 0x01 }, + { 0x6837, 0x04 }, + { 0x684d, 0x07 }, + { 0x684e, 0x01 }, + { 0x684f, 0x04 }, +}; + +static const struct imx355_reg mode_1300x736_regs[] = { + { 0x0112, 0x0a }, + { 0x0113, 0x0a }, + { 0x0114, 0x03 }, + { 0x0342, 0x07 }, + { 0x0343, 0x2c }, + { 0x0340, 0x05 }, + { 0x0341, 0x1a }, + { 0x0344, 0x01 }, + { 0x0345, 0x58 }, + { 0x0346, 0x01 }, + { 0x0347, 0xf0 }, + { 0x0348, 0x0b }, + { 0x0349, 0x7f }, + { 0x034a, 0x07 }, + { 0x034b, 0xaf }, + { 0x0220, 0x00 }, + { 0x0222, 0x01 }, + { 0x0900, 0x01 }, + { 0x0901, 0x22 }, + { 0x0902, 0x00 }, + { 0x034c, 0x05 }, + { 0x034d, 0x14 }, + { 0x034e, 0x02 }, + { 0x034f, 0xe0 }, + { 0x0301, 0x05 }, + { 0x0303, 0x01 }, + { 0x0305, 0x02 }, + { 0x0306, 0x00 }, + { 0x0307, 0x78 }, + { 0x030b, 0x01 }, + { 0x030d, 0x02 }, + { 0x030e, 0x00 }, + { 0x030f, 0x4b }, + { 0x0310, 0x00 }, + { 0x0700, 0x00 }, + { 0x0701, 0x10 }, + { 0x0820, 0x0b }, + { 0x0821, 0x40 }, + { 0x3088, 0x04 }, + { 0x6813, 0x02 }, + { 0x6835, 0x07 }, + { 0x6836, 0x01 }, + { 0x6837, 0x04 }, + { 0x684d, 0x07 }, + { 0x684e, 0x01 }, + { 0x684f, 0x04 }, +}; + +static const struct imx355_reg mode_1296x736_regs[] = { + { 0x0112, 0x0a }, + { 0x0113, 0x0a }, + { 0x0114, 0x03 }, + { 0x0342, 0x07 }, + { 0x0343, 0x2c }, + { 0x0340, 0x05 }, + { 0x0341, 0x1a }, + { 0x0344, 0x01 }, + { 0x0345, 0x58 }, + { 0x0346, 0x01 }, + { 0x0347, 0xf0 }, + { 0x0348, 0x0b }, + { 0x0349, 0x77 }, + { 0x034a, 0x07 }, + { 0x034b, 0xaf }, + { 0x0220, 0x00 }, + { 0x0222, 0x01 }, + { 0x0900, 0x01 }, + { 0x0901, 0x22 }, + { 0x0902, 0x00 }, + { 0x034c, 0x05 }, + { 0x034d, 0x10 }, + { 0x034e, 0x02 }, + { 0x034f, 0xe0 }, + { 0x0301, 0x05 }, + { 0x0303, 0x01 }, + { 0x0305, 0x02 }, + { 0x0306, 0x00 }, + { 0x0307, 0x78 }, + { 0x030b, 0x01 }, + { 0x030d, 0x02 }, + { 0x030e, 0x00 }, + { 0x030f, 0x4b }, + { 0x0310, 0x00 }, + { 0x0700, 0x00 }, + { 0x0701, 0x10 }, + { 0x0820, 0x0b }, + { 0x0821, 0x40 }, + { 0x3088, 0x04 }, + { 0x6813, 0x02 }, + { 0x6835, 0x07 }, + { 0x6836, 0x01 }, + { 0x6837, 0x04 }, + { 0x684d, 0x07 }, + { 0x684e, 0x01 }, + { 0x684f, 0x04 }, +}; + +static const struct imx355_reg mode_1284x720_regs[] = { + { 0x0112, 0x0a }, + { 0x0113, 0x0a }, + { 0x0114, 0x03 }, + { 0x0342, 0x07 }, + { 0x0343, 0x2c }, + { 0x0340, 0x05 }, + { 0x0341, 0x1a }, + { 0x0344, 0x01 }, + { 0x0345, 0x68 }, + { 0x0346, 0x02 }, + { 0x0347, 0x00 }, + { 0x0348, 0x0b }, + { 0x0349, 0x6f }, + { 0x034a, 0x07 }, + { 0x034b, 0x9f }, + { 0x0220, 0x00 }, + { 0x0222, 0x01 }, + { 0x0900, 0x01 }, + { 0x0901, 0x22 }, + { 0x0902, 0x00 }, + { 0x034c, 0x05 }, + { 0x034d, 0x04 }, + { 0x034e, 0x02 }, + { 0x034f, 0xd0 }, + { 0x0301, 0x05 }, + { 0x0303, 0x01 }, + { 0x0305, 0x02 }, + { 0x0306, 0x00 }, + { 0x0307, 0x78 }, + { 0x030b, 0x01 }, + { 0x030d, 0x02 }, + { 0x030e, 0x00 }, + { 0x030f, 0x4b }, + { 0x0310, 0x00 }, + { 0x0700, 0x00 }, + { 0x0701, 0x10 }, + { 0x0820, 0x0b }, + { 0x0821, 0x40 }, + { 0x3088, 0x04 }, + { 0x6813, 0x02 }, + { 0x6835, 0x07 }, + { 0x6836, 0x01 }, + { 0x6837, 0x04 }, + { 0x684d, 0x07 }, + { 0x684e, 0x01 }, + { 0x684f, 0x04 }, +}; + +static const struct imx355_reg mode_1280x720_regs[] = { + { 0x0112, 0x0a }, + { 0x0113, 0x0a }, + { 0x0114, 0x03 }, + { 0x0342, 0x07 }, + { 0x0343, 0x2c }, + { 0x0340, 0x05 }, + { 0x0341, 0x1a }, + { 0x0344, 0x01 }, + { 0x0345, 0x68 }, + { 0x0346, 0x02 }, + { 0x0347, 0x00 }, + { 0x0348, 0x0b }, + { 0x0349, 0x67 }, + { 0x034a, 0x07 }, + { 0x034b, 0x9f }, + { 0x0220, 0x00 }, + { 0x0222, 0x01 }, + { 0x0900, 0x01 }, + { 0x0901, 0x22 }, + { 0x0902, 0x00 }, + { 0x034c, 0x05 }, + { 0x034d, 0x00 }, + { 0x034e, 0x02 }, + { 0x034f, 0xd0 }, + { 0x0301, 0x05 }, + { 0x0303, 0x01 }, + { 0x0305, 0x02 }, + { 0x0306, 0x00 }, + { 0x0307, 0x78 }, + { 0x030b, 0x01 }, + { 0x030d, 0x02 }, + { 0x030e, 0x00 }, + { 0x030f, 0x4b }, + { 0x0310, 0x00 }, + { 0x0700, 0x00 }, + { 0x0701, 0x10 }, + { 0x0820, 0x0b }, + { 0x0821, 0x40 }, + { 0x3088, 0x04 }, + { 0x6813, 0x02 }, + { 0x6835, 0x07 }, + { 0x6836, 0x01 }, + { 0x6837, 0x04 }, + { 0x684d, 0x07 }, + { 0x684e, 0x01 }, + { 0x684f, 0x04 }, +}; + +static const struct imx355_reg mode_820x616_regs[] = { + { 0x0112, 0x0a }, + { 0x0113, 0x0a }, + { 0x0114, 0x03 }, + { 0x0342, 0x0e }, + { 0x0343, 0x58 }, + { 0x0340, 0x02 }, + { 0x0341, 0x8c }, + { 0x0344, 0x00 }, + { 0x0345, 0x00 }, + { 0x0346, 0x00 }, + { 0x0347, 0x00 }, + { 0x0348, 0x0c }, + { 0x0349, 0xcf }, + { 0x034a, 0x09 }, + { 0x034b, 0x9f }, + { 0x0220, 0x00 }, + { 0x0222, 0x01 }, + { 0x0900, 0x01 }, + { 0x0901, 0x44 }, + { 0x0902, 0x00 }, + { 0x034c, 0x03 }, + { 0x034d, 0x34 }, + { 0x034e, 0x02 }, + { 0x034f, 0x68 }, + { 0x0301, 0x05 }, + { 0x0303, 0x01 }, + { 0x0305, 0x02 }, + { 0x0306, 0x00 }, + { 0x0307, 0x78 }, + { 0x030b, 0x01 }, + { 0x030d, 0x02 }, + { 0x030e, 0x00 }, + { 0x030f, 0x4b }, + { 0x0310, 0x00 }, + { 0x0700, 0x02 }, + { 0x0701, 0x78 }, + { 0x0820, 0x0b }, + { 0x0821, 0x40 }, + { 0x3088, 0x04 }, + { 0x6813, 0x02 }, + { 0x6835, 0x07 }, + { 0x6836, 0x01 }, + { 0x6837, 0x04 }, + { 0x684d, 0x07 }, + { 0x684e, 0x01 }, + { 0x684f, 0x04 }, +}; + +static const char * const imx355_test_pattern_menu[] = { + "Disabled", + "100% color bars", + "Solid color", + "Fade to gray color bars", + "PN9" +}; + +/* supported link frequencies */ +static const s64 link_freq_menu_items[] = { + IMX355_LINK_FREQ_DEFAULT, +}; + +/* Mode configs */ +static const struct imx355_mode supported_modes[] = { + { + .width = 3280, + .height = 2464, + .fll_def = 2615, + .fll_min = 2615, + .llp = 3672, + .link_freq_index = IMX355_LINK_FREQ_INDEX, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_3280x2464_regs), + .regs = mode_3280x2464_regs, + }, + }, + { + .width = 3268, + .height = 2448, + .fll_def = 2615, + .fll_min = 2615, + .llp = 3672, + .link_freq_index = IMX355_LINK_FREQ_INDEX, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_3268x2448_regs), + .regs = mode_3268x2448_regs, + }, + }, + { + .width = 3264, + .height = 2448, + .fll_def = 2615, + .fll_min = 2615, + .llp = 3672, + .link_freq_index = IMX355_LINK_FREQ_INDEX, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_3264x2448_regs), + .regs = mode_3264x2448_regs, + }, + }, + { + .width = 1940, + .height = 1096, + .fll_def = 1306, + .fll_min = 1306, + .llp = 3672, + .link_freq_index = IMX355_LINK_FREQ_INDEX, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_1940x1096_regs), + .regs = mode_1940x1096_regs, + }, + }, + { + .width = 1936, + .height = 1096, + .fll_def = 1306, + .fll_min = 1306, + .llp = 3672, + .link_freq_index = IMX355_LINK_FREQ_INDEX, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_1936x1096_regs), + .regs = mode_1936x1096_regs, + }, + }, + { + .width = 1924, + .height = 1080, + .fll_def = 1306, + .fll_min = 1306, + .llp = 3672, + .link_freq_index = IMX355_LINK_FREQ_INDEX, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_1924x1080_regs), + .regs = mode_1924x1080_regs, + }, + }, + { + .width = 1920, + .height = 1080, + .fll_def = 1306, + .fll_min = 1306, + .llp = 3672, + .link_freq_index = IMX355_LINK_FREQ_INDEX, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_1920x1080_regs), + .regs = mode_1920x1080_regs, + }, + }, + { + .width = 1640, + .height = 1232, + .fll_def = 1306, + .fll_min = 1306, + .llp = 1836, + .link_freq_index = IMX355_LINK_FREQ_INDEX, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_1640x1232_regs), + .regs = mode_1640x1232_regs, + }, + }, + { + .width = 1640, + .height = 922, + .fll_def = 1306, + .fll_min = 1306, + .llp = 1836, + .link_freq_index = IMX355_LINK_FREQ_INDEX, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_1640x922_regs), + .regs = mode_1640x922_regs, + }, + }, + { + .width = 1300, + .height = 736, + .fll_def = 1306, + .fll_min = 1306, + .llp = 1836, + .link_freq_index = IMX355_LINK_FREQ_INDEX, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_1300x736_regs), + .regs = mode_1300x736_regs, + }, + }, + { + .width = 1296, + .height = 736, + .fll_def = 1306, + .fll_min = 1306, + .llp = 1836, + .link_freq_index = IMX355_LINK_FREQ_INDEX, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_1296x736_regs), + .regs = mode_1296x736_regs, + }, + }, + { + .width = 1284, + .height = 720, + .fll_def = 1306, + .fll_min = 1306, + .llp = 1836, + .link_freq_index = IMX355_LINK_FREQ_INDEX, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_1284x720_regs), + .regs = mode_1284x720_regs, + }, + }, + { + .width = 1280, + .height = 720, + .fll_def = 1306, + .fll_min = 1306, + .llp = 1836, + .link_freq_index = IMX355_LINK_FREQ_INDEX, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_1280x720_regs), + .regs = mode_1280x720_regs, + }, + }, + { + .width = 820, + .height = 616, + .fll_def = 652, + .fll_min = 652, + .llp = 3672, + .link_freq_index = IMX355_LINK_FREQ_INDEX, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_820x616_regs), + .regs = mode_820x616_regs, + }, + }, +}; + +static inline struct imx355 *to_imx355(struct v4l2_subdev *_sd) +{ + return container_of(_sd, struct imx355, sd); +} + +/* Get bayer order based on flip setting. */ +static u32 imx355_get_format_code(struct imx355 *imx355) +{ + /* + * Only one bayer order is supported. + * It depends on the flip settings. + */ + u32 code; + static const u32 codes[2][2] = { + { MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SGRBG10_1X10, }, + { MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SBGGR10_1X10, }, + }; + + lockdep_assert_held(&imx355->mutex); + code = codes[imx355->vflip->val][imx355->hflip->val]; + + return code; +} + +/* Read registers up to 4 at a time */ +static int imx355_read_reg(struct imx355 *imx355, u16 reg, u32 len, u32 *val) +{ + struct i2c_client *client = v4l2_get_subdevdata(&imx355->sd); + struct i2c_msg msgs[2]; + u8 addr_buf[2]; + u8 data_buf[4] = { 0 }; + int ret; + + if (len > 4) + return -EINVAL; + + put_unaligned_be16(reg, addr_buf); + /* Write register address */ + msgs[0].addr = client->addr; + msgs[0].flags = 0; + msgs[0].len = ARRAY_SIZE(addr_buf); + msgs[0].buf = addr_buf; + + /* Read data from register */ + msgs[1].addr = client->addr; + msgs[1].flags = I2C_M_RD; + msgs[1].len = len; + msgs[1].buf = &data_buf[4 - len]; + + ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + if (ret != ARRAY_SIZE(msgs)) + return -EIO; + + *val = get_unaligned_be32(data_buf); + + return 0; +} + +/* Write registers up to 4 at a time */ +static int imx355_write_reg(struct imx355 *imx355, u16 reg, u32 len, u32 val) +{ + struct i2c_client *client = v4l2_get_subdevdata(&imx355->sd); + u8 buf[6]; + + if (len > 4) + return -EINVAL; + + put_unaligned_be16(reg, buf); + put_unaligned_be32(val << (8 * (4 - len)), buf + 2); + if (i2c_master_send(client, buf, len + 2) != len + 2) + return -EIO; + + return 0; +} + +/* Write a list of registers */ +static int imx355_write_regs(struct imx355 *imx355, + const struct imx355_reg *regs, u32 len) +{ + struct i2c_client *client = v4l2_get_subdevdata(&imx355->sd); + int ret; + u32 i; + + for (i = 0; i < len; i++) { + ret = imx355_write_reg(imx355, regs[i].address, 1, regs[i].val); + if (ret) { + dev_err_ratelimited(&client->dev, + "write reg 0x%4.4x return err %d", + regs[i].address, ret); + + return ret; + } + } + + return 0; +} + +/* Open sub-device */ +static int imx355_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +{ + struct imx355 *imx355 = to_imx355(sd); + struct v4l2_mbus_framefmt *try_fmt = + v4l2_subdev_get_try_format(sd, fh->pad, 0); + + mutex_lock(&imx355->mutex); + + /* Initialize try_fmt */ + try_fmt->width = imx355->cur_mode->width; + try_fmt->height = imx355->cur_mode->height; + try_fmt->code = imx355_get_format_code(imx355); + try_fmt->field = V4L2_FIELD_NONE; + + mutex_unlock(&imx355->mutex); + + return 0; +} + +static int imx355_set_ctrl(struct v4l2_ctrl *ctrl) +{ + struct imx355 *imx355 = container_of(ctrl->handler, + struct imx355, ctrl_handler); + struct i2c_client *client = v4l2_get_subdevdata(&imx355->sd); + s64 max; + int ret; + + /* Propagate change of current control to all related controls */ + switch (ctrl->id) { + case V4L2_CID_VBLANK: + /* Update max exposure while meeting expected vblanking */ + max = imx355->cur_mode->height + ctrl->val - 10; + __v4l2_ctrl_modify_range(imx355->exposure, + imx355->exposure->minimum, + max, imx355->exposure->step, max); + break; + } + + /* + * Applying V4L2 control value only happens + * when power is up for streaming + */ + if (!pm_runtime_get_if_in_use(&client->dev)) + return 0; + + switch (ctrl->id) { + case V4L2_CID_ANALOGUE_GAIN: + /* Analog gain = 1024/(1024 - ctrl->val) times */ + ret = imx355_write_reg(imx355, IMX355_REG_ANALOG_GAIN, 2, + ctrl->val); + break; + case V4L2_CID_DIGITAL_GAIN: + ret = imx355_write_reg(imx355, IMX355_REG_DIG_GAIN_GLOBAL, 2, + ctrl->val); + break; + case V4L2_CID_EXPOSURE: + ret = imx355_write_reg(imx355, IMX355_REG_EXPOSURE, 2, + ctrl->val); + break; + case V4L2_CID_VBLANK: + /* Update FLL that meets expected vertical blanking */ + ret = imx355_write_reg(imx355, IMX355_REG_FLL, 2, + imx355->cur_mode->height + ctrl->val); + break; + case V4L2_CID_TEST_PATTERN: + ret = imx355_write_reg(imx355, IMX355_REG_TEST_PATTERN, + 2, ctrl->val); + break; + case V4L2_CID_HFLIP: + case V4L2_CID_VFLIP: + ret = imx355_write_reg(imx355, IMX355_REG_ORIENTATION, 1, + imx355->hflip->val | + imx355->vflip->val << 1); + break; + default: + ret = -EINVAL; + dev_info(&client->dev, "ctrl(id:0x%x,val:0x%x) is not handled", + ctrl->id, ctrl->val); + break; + } + + pm_runtime_put(&client->dev); + + return ret; +} + +static const struct v4l2_ctrl_ops imx355_ctrl_ops = { + .s_ctrl = imx355_set_ctrl, +}; + +static int imx355_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_mbus_code_enum *code) +{ + struct imx355 *imx355 = to_imx355(sd); + + if (code->index > 0) + return -EINVAL; + + mutex_lock(&imx355->mutex); + code->code = imx355_get_format_code(imx355); + mutex_unlock(&imx355->mutex); + + return 0; +} + +static int imx355_enum_frame_size(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_size_enum *fse) +{ + struct imx355 *imx355 = to_imx355(sd); + + if (fse->index >= ARRAY_SIZE(supported_modes)) + return -EINVAL; + + mutex_lock(&imx355->mutex); + if (fse->code != imx355_get_format_code(imx355)) { + mutex_unlock(&imx355->mutex); + return -EINVAL; + } + mutex_unlock(&imx355->mutex); + + fse->min_width = supported_modes[fse->index].width; + fse->max_width = fse->min_width; + fse->min_height = supported_modes[fse->index].height; + fse->max_height = fse->min_height; + + return 0; +} + +static void imx355_update_pad_format(struct imx355 *imx355, + const struct imx355_mode *mode, + struct v4l2_subdev_format *fmt) +{ + fmt->format.width = mode->width; + fmt->format.height = mode->height; + fmt->format.code = imx355_get_format_code(imx355); + fmt->format.field = V4L2_FIELD_NONE; +} + +static int imx355_do_get_pad_format(struct imx355 *imx355, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *fmt) +{ + struct v4l2_mbus_framefmt *framefmt; + struct v4l2_subdev *sd = &imx355->sd; + + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { + framefmt = v4l2_subdev_get_try_format(sd, cfg, fmt->pad); + fmt->format = *framefmt; + } else { + imx355_update_pad_format(imx355, imx355->cur_mode, fmt); + } + + return 0; +} + +static int imx355_get_pad_format(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *fmt) +{ + struct imx355 *imx355 = to_imx355(sd); + int ret; + + mutex_lock(&imx355->mutex); + ret = imx355_do_get_pad_format(imx355, cfg, fmt); + mutex_unlock(&imx355->mutex); + + return ret; +} + +static int +imx355_set_pad_format(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *fmt) +{ + struct imx355 *imx355 = to_imx355(sd); + const struct imx355_mode *mode; + struct v4l2_mbus_framefmt *framefmt; + s32 vblank_def; + s32 vblank_min; + s64 h_blank; + u64 pixel_rate; + u32 height; + + mutex_lock(&imx355->mutex); + + /* + * Only one bayer order is supported. + * It depends on the flip settings. + */ + fmt->format.code = imx355_get_format_code(imx355); + + mode = v4l2_find_nearest_size(supported_modes, + ARRAY_SIZE(supported_modes), + width, height, + fmt->format.width, fmt->format.height); + imx355_update_pad_format(imx355, mode, fmt); + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { + framefmt = v4l2_subdev_get_try_format(sd, cfg, fmt->pad); + *framefmt = fmt->format; + } else { + imx355->cur_mode = mode; + pixel_rate = imx355->link_def_freq * 2 * 4; + do_div(pixel_rate, 10); + __v4l2_ctrl_s_ctrl_int64(imx355->pixel_rate, pixel_rate); + /* Update limits and set FPS to default */ + height = imx355->cur_mode->height; + vblank_def = imx355->cur_mode->fll_def - height; + vblank_min = imx355->cur_mode->fll_min - height; + height = IMX355_FLL_MAX - height; + __v4l2_ctrl_modify_range(imx355->vblank, vblank_min, height, 1, + vblank_def); + __v4l2_ctrl_s_ctrl(imx355->vblank, vblank_def); + h_blank = mode->llp - imx355->cur_mode->width; + /* + * Currently hblank is not changeable. + * So FPS control is done only by vblank. + */ + __v4l2_ctrl_modify_range(imx355->hblank, h_blank, + h_blank, 1, h_blank); + } + + mutex_unlock(&imx355->mutex); + + return 0; +} + +/* Start streaming */ +static int imx355_start_streaming(struct imx355 *imx355) +{ + struct i2c_client *client = v4l2_get_subdevdata(&imx355->sd); + const struct imx355_reg_list *reg_list; + int ret; + + /* Global Setting */ + reg_list = &imx355_global_setting; + ret = imx355_write_regs(imx355, reg_list->regs, reg_list->num_of_regs); + if (ret) { + dev_err(&client->dev, "failed to set global settings"); + return ret; + } + + /* Apply default values of current mode */ + reg_list = &imx355->cur_mode->reg_list; + ret = imx355_write_regs(imx355, reg_list->regs, reg_list->num_of_regs); + if (ret) { + dev_err(&client->dev, "failed to set mode"); + return ret; + } + + /* set digital gain control to all color mode */ + ret = imx355_write_reg(imx355, IMX355_REG_DPGA_USE_GLOBAL_GAIN, 1, 1); + if (ret) + return ret; + + /* Apply customized values from user */ + ret = __v4l2_ctrl_handler_setup(imx355->sd.ctrl_handler); + if (ret) + return ret; + + return imx355_write_reg(imx355, IMX355_REG_MODE_SELECT, + 1, IMX355_MODE_STREAMING); +} + +/* Stop streaming */ +static int imx355_stop_streaming(struct imx355 *imx355) +{ + return imx355_write_reg(imx355, IMX355_REG_MODE_SELECT, + 1, IMX355_MODE_STANDBY); +} + +static int imx355_set_stream(struct v4l2_subdev *sd, int enable) +{ + struct imx355 *imx355 = to_imx355(sd); + struct i2c_client *client = v4l2_get_subdevdata(sd); + int ret = 0; + + mutex_lock(&imx355->mutex); + if (imx355->streaming == enable) { + mutex_unlock(&imx355->mutex); + return 0; + } + + if (enable) { + ret = pm_runtime_get_sync(&client->dev); + if (ret < 0) { + pm_runtime_put_noidle(&client->dev); + goto err_unlock; + } + + /* + * Apply default & customized values + * and then start streaming. + */ + ret = imx355_start_streaming(imx355); + if (ret) + goto err_rpm_put; + } else { + imx355_stop_streaming(imx355); + pm_runtime_put(&client->dev); + } + + imx355->streaming = enable; + + /* vflip and hflip cannot change during streaming */ + __v4l2_ctrl_grab(imx355->vflip, enable); + __v4l2_ctrl_grab(imx355->hflip, enable); + + mutex_unlock(&imx355->mutex); + + return ret; + +err_rpm_put: + pm_runtime_put(&client->dev); +err_unlock: + mutex_unlock(&imx355->mutex); + + return ret; +} + +static int __maybe_unused imx355_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct imx355 *imx355 = to_imx355(sd); + + if (imx355->streaming) + imx355_stop_streaming(imx355); + + return 0; +} + +static int __maybe_unused imx355_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct imx355 *imx355 = to_imx355(sd); + int ret; + + if (imx355->streaming) { + ret = imx355_start_streaming(imx355); + if (ret) + goto error; + } + + return 0; + +error: + imx355_stop_streaming(imx355); + imx355->streaming = 0; + return ret; +} + +/* Verify chip ID */ +static int imx355_identify_module(struct imx355 *imx355) +{ + struct i2c_client *client = v4l2_get_subdevdata(&imx355->sd); + int ret; + u32 val; + + ret = imx355_read_reg(imx355, IMX355_REG_CHIP_ID, 2, &val); + if (ret) + return ret; + + if (val != IMX355_CHIP_ID) { + dev_err(&client->dev, "chip id mismatch: %x!=%x", + IMX355_CHIP_ID, val); + return -EIO; + } + return 0; +} + +static const struct v4l2_subdev_core_ops imx355_subdev_core_ops = { + .subscribe_event = v4l2_ctrl_subdev_subscribe_event, + .unsubscribe_event = v4l2_event_subdev_unsubscribe, +}; + +static const struct v4l2_subdev_video_ops imx355_video_ops = { + .s_stream = imx355_set_stream, +}; + +static const struct v4l2_subdev_pad_ops imx355_pad_ops = { + .enum_mbus_code = imx355_enum_mbus_code, + .get_fmt = imx355_get_pad_format, + .set_fmt = imx355_set_pad_format, + .enum_frame_size = imx355_enum_frame_size, +}; + +static const struct v4l2_subdev_ops imx355_subdev_ops = { + .core = &imx355_subdev_core_ops, + .video = &imx355_video_ops, + .pad = &imx355_pad_ops, +}; + +static const struct media_entity_operations imx355_subdev_entity_ops = { + .link_validate = v4l2_subdev_link_validate, +}; + +static const struct v4l2_subdev_internal_ops imx355_internal_ops = { + .open = imx355_open, +}; + +/* Initialize control handlers */ +static int imx355_init_controls(struct imx355 *imx355) +{ + struct i2c_client *client = v4l2_get_subdevdata(&imx355->sd); + struct v4l2_ctrl_handler *ctrl_hdlr; + s64 exposure_max; + s64 vblank_def; + s64 vblank_min; + s64 hblank; + u64 pixel_rate; + const struct imx355_mode *mode; + u32 max; + int ret; + + ctrl_hdlr = &imx355->ctrl_handler; + ret = v4l2_ctrl_handler_init(ctrl_hdlr, 10); + if (ret) + return ret; + + ctrl_hdlr->lock = &imx355->mutex; + max = ARRAY_SIZE(link_freq_menu_items) - 1; + imx355->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx355_ctrl_ops, + V4L2_CID_LINK_FREQ, max, 0, + link_freq_menu_items); + if (imx355->link_freq) + imx355->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; + + /* pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample */ + pixel_rate = imx355->link_def_freq * 2 * 4; + do_div(pixel_rate, 10); + /* By default, PIXEL_RATE is read only */ + imx355->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops, + V4L2_CID_PIXEL_RATE, pixel_rate, + pixel_rate, 1, pixel_rate); + + /* Initialize vblank/hblank/exposure parameters based on current mode */ + mode = imx355->cur_mode; + vblank_def = mode->fll_def - mode->height; + vblank_min = mode->fll_min - mode->height; + imx355->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops, + V4L2_CID_VBLANK, vblank_min, + IMX355_FLL_MAX - mode->height, + 1, vblank_def); + + hblank = mode->llp - mode->width; + imx355->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops, + V4L2_CID_HBLANK, hblank, hblank, + 1, hblank); + if (imx355->hblank) + imx355->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; + + /* fll >= exposure time + adjust parameter (default value is 10) */ + exposure_max = mode->fll_def - 10; + imx355->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops, + V4L2_CID_EXPOSURE, + IMX355_EXPOSURE_MIN, exposure_max, + IMX355_EXPOSURE_STEP, + IMX355_EXPOSURE_DEFAULT); + + imx355->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops, + V4L2_CID_HFLIP, 0, 1, 1, 0); + imx355->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops, + V4L2_CID_VFLIP, 0, 1, 1, 0); + + v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops, V4L2_CID_ANALOGUE_GAIN, + IMX355_ANA_GAIN_MIN, IMX355_ANA_GAIN_MAX, + IMX355_ANA_GAIN_STEP, IMX355_ANA_GAIN_DEFAULT); + + /* Digital gain */ + v4l2_ctrl_new_std(ctrl_hdlr, &imx355_ctrl_ops, V4L2_CID_DIGITAL_GAIN, + IMX355_DGTL_GAIN_MIN, IMX355_DGTL_GAIN_MAX, + IMX355_DGTL_GAIN_STEP, IMX355_DGTL_GAIN_DEFAULT); + + v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx355_ctrl_ops, + V4L2_CID_TEST_PATTERN, + ARRAY_SIZE(imx355_test_pattern_menu) - 1, + 0, 0, imx355_test_pattern_menu); + if (ctrl_hdlr->error) { + ret = ctrl_hdlr->error; + dev_err(&client->dev, "control init failed: %d", ret); + goto error; + } + + imx355->sd.ctrl_handler = ctrl_hdlr; + + return 0; + +error: + v4l2_ctrl_handler_free(ctrl_hdlr); + + return ret; +} + +static struct imx355_hwcfg *imx355_get_hwcfg(struct device *dev) +{ + struct imx355_hwcfg *cfg; + struct v4l2_fwnode_endpoint bus_cfg = { + .bus_type = V4L2_MBUS_CSI2_DPHY + }; + struct fwnode_handle *ep; + struct fwnode_handle *fwnode = dev_fwnode(dev); + unsigned int i; + int ret; + + if (!fwnode) + return NULL; + + ep = fwnode_graph_get_next_endpoint(fwnode, NULL); + if (!ep) + return NULL; + + ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg); + if (ret) + goto out_err; + + cfg = devm_kzalloc(dev, sizeof(*cfg), GFP_KERNEL); + if (!cfg) + goto out_err; + + ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency", + &cfg->ext_clk); + if (ret) { + dev_err(dev, "can't get clock frequency"); + goto out_err; + } + + dev_dbg(dev, "ext clk: %d", cfg->ext_clk); + if (cfg->ext_clk != IMX355_EXT_CLK) { + dev_err(dev, "external clock %d is not supported", + cfg->ext_clk); + goto out_err; + } + + dev_dbg(dev, "num of link freqs: %d", bus_cfg.nr_of_link_frequencies); + if (!bus_cfg.nr_of_link_frequencies) { + dev_warn(dev, "no link frequencies defined"); + goto out_err; + } + + cfg->nr_of_link_freqs = bus_cfg.nr_of_link_frequencies; + cfg->link_freqs = devm_kcalloc(dev, + bus_cfg.nr_of_link_frequencies + 1, + sizeof(*cfg->link_freqs), GFP_KERNEL); + if (!cfg->link_freqs) + goto out_err; + + for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) { + cfg->link_freqs[i] = bus_cfg.link_frequencies[i]; + dev_dbg(dev, "link_freq[%d] = %lld", i, cfg->link_freqs[i]); + } + + v4l2_fwnode_endpoint_free(&bus_cfg); + fwnode_handle_put(ep); + return cfg; + +out_err: + v4l2_fwnode_endpoint_free(&bus_cfg); + fwnode_handle_put(ep); + return NULL; +} + +static int imx355_probe(struct i2c_client *client) +{ + struct imx355 *imx355; + int ret; + u32 i; + + imx355 = devm_kzalloc(&client->dev, sizeof(*imx355), GFP_KERNEL); + if (!imx355) + return -ENOMEM; + + mutex_init(&imx355->mutex); + + /* Initialize subdev */ + v4l2_i2c_subdev_init(&imx355->sd, client, &imx355_subdev_ops); + + /* Check module identity */ + ret = imx355_identify_module(imx355); + if (ret) { + dev_err(&client->dev, "failed to find sensor: %d", ret); + goto error_probe; + } + + imx355->hwcfg = imx355_get_hwcfg(&client->dev); + if (!imx355->hwcfg) { + dev_err(&client->dev, "failed to get hwcfg"); + ret = -ENODEV; + goto error_probe; + } + + imx355->link_def_freq = link_freq_menu_items[IMX355_LINK_FREQ_INDEX]; + for (i = 0; i < imx355->hwcfg->nr_of_link_freqs; i++) { + if (imx355->hwcfg->link_freqs[i] == imx355->link_def_freq) { + dev_dbg(&client->dev, "link freq index %d matched", i); + break; + } + } + + if (i == imx355->hwcfg->nr_of_link_freqs) { + dev_err(&client->dev, "no link frequency supported"); + ret = -EINVAL; + goto error_probe; + } + + /* Set default mode to max resolution */ + imx355->cur_mode = &supported_modes[0]; + + ret = imx355_init_controls(imx355); + if (ret) { + dev_err(&client->dev, "failed to init controls: %d", ret); + goto error_probe; + } + + /* Initialize subdev */ + imx355->sd.internal_ops = &imx355_internal_ops; + imx355->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | + V4L2_SUBDEV_FL_HAS_EVENTS; + imx355->sd.entity.ops = &imx355_subdev_entity_ops; + imx355->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; + + /* Initialize source pad */ + imx355->pad.flags = MEDIA_PAD_FL_SOURCE; + ret = media_entity_pads_init(&imx355->sd.entity, 1, &imx355->pad); + if (ret) { + dev_err(&client->dev, "failed to init entity pads: %d", ret); + goto error_handler_free; + } + + ret = v4l2_async_register_subdev_sensor_common(&imx355->sd); + if (ret < 0) + goto error_media_entity; + + /* + * Device is already turned on by i2c-core with ACPI domain PM. + * Enable runtime PM and turn off the device. + */ + pm_runtime_set_active(&client->dev); + pm_runtime_enable(&client->dev); + pm_runtime_idle(&client->dev); + + return 0; + +error_media_entity: + media_entity_cleanup(&imx355->sd.entity); + +error_handler_free: + v4l2_ctrl_handler_free(imx355->sd.ctrl_handler); + +error_probe: + mutex_destroy(&imx355->mutex); + + return ret; +} + +static int imx355_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct imx355 *imx355 = to_imx355(sd); + + v4l2_async_unregister_subdev(sd); + media_entity_cleanup(&sd->entity); + v4l2_ctrl_handler_free(sd->ctrl_handler); + + pm_runtime_disable(&client->dev); + pm_runtime_set_suspended(&client->dev); + + mutex_destroy(&imx355->mutex); + + return 0; +} + +static const struct dev_pm_ops imx355_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(imx355_suspend, imx355_resume) +}; + +static const struct acpi_device_id imx355_acpi_ids[] = { + { "SONY355A" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(acpi, imx355_acpi_ids); + +static struct i2c_driver imx355_i2c_driver = { + .driver = { + .name = "imx355", + .pm = &imx355_pm_ops, + .acpi_match_table = ACPI_PTR(imx355_acpi_ids), + }, + .probe_new = imx355_probe, + .remove = imx355_remove, +}; +module_i2c_driver(imx355_i2c_driver); + +MODULE_AUTHOR("Qiu, Tianshu <tian.shu.qiu@intel.com>"); +MODULE_AUTHOR("Rapolu, Chiranjeevi <chiranjeevi.rapolu@intel.com>"); +MODULE_AUTHOR("Bingbu Cao <bingbu.cao@intel.com>"); +MODULE_AUTHOR("Yang, Hyungwoo <hyungwoo.yang@intel.com>"); +MODULE_DESCRIPTION("Sony imx355 sensor driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/i2c/lm3560.c b/drivers/media/i2c/lm3560.c index 49c6644cbba7..f122f03bd6b7 100644 --- a/drivers/media/i2c/lm3560.c +++ b/drivers/media/i2c/lm3560.c @@ -362,7 +362,8 @@ static int lm3560_subdev_init(struct lm3560_flash *flash, v4l2_i2c_subdev_init(&flash->subdev_led[led_no], client, &lm3560_ops); flash->subdev_led[led_no].flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - strcpy(flash->subdev_led[led_no].name, led_name); + strscpy(flash->subdev_led[led_no].name, led_name, + sizeof(flash->subdev_led[led_no].name)); rval = lm3560_init_controls(flash, led_no); if (rval) goto err_out; diff --git a/drivers/media/i2c/lm3646.c b/drivers/media/i2c/lm3646.c index 7e9967af36ec..12ef2653987b 100644 --- a/drivers/media/i2c/lm3646.c +++ b/drivers/media/i2c/lm3646.c @@ -278,7 +278,8 @@ static int lm3646_subdev_init(struct lm3646_flash *flash) v4l2_i2c_subdev_init(&flash->subdev_led, client, &lm3646_ops); flash->subdev_led.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - strcpy(flash->subdev_led.name, LM3646_NAME); + strscpy(flash->subdev_led.name, LM3646_NAME, + sizeof(flash->subdev_led.name)); rval = lm3646_init_controls(flash); if (rval) goto err_out; diff --git a/drivers/media/i2c/m5mols/m5mols_core.c b/drivers/media/i2c/m5mols/m5mols_core.c index 12e79f9e32d5..b8b2bf4cbfb2 100644 --- a/drivers/media/i2c/m5mols/m5mols_core.c +++ b/drivers/media/i2c/m5mols/m5mols_core.c @@ -987,7 +987,8 @@ static int m5mols_probe(struct i2c_client *client, sd = &info->sd; v4l2_i2c_subdev_init(sd, client, &m5mols_ops); - strlcpy(sd->name, MODULE_NAME, sizeof(sd->name)); + /* Static name; NEVER use in new drivers! */ + strscpy(sd->name, MODULE_NAME, sizeof(sd->name)); sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; sd->internal_ops = &m5mols_subdev_internal_ops; diff --git a/drivers/media/i2c/max2175.c b/drivers/media/i2c/max2175.c index 008a082cb8ad..7b226fadcdb8 100644 --- a/drivers/media/i2c/max2175.c +++ b/drivers/media/i2c/max2175.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Maxim Integrated MAX2175 RF to Bits tuner driver * @@ -6,15 +7,6 @@ * * Copyright (C) 2016 Maxim Integrated Products * Copyright (C) 2017 Renesas Electronics Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #include <linux/clk.h> @@ -1165,7 +1157,7 @@ static int max2175_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) if (vt->index > 0) return -EINVAL; - strlcpy(vt->name, "RF", sizeof(vt->name)); + strscpy(vt->name, "RF", sizeof(vt->name)); vt->type = V4L2_TUNER_RF; vt->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS; vt->rangelow = ctx->bands_rf->rangelow; diff --git a/drivers/media/i2c/max2175.h b/drivers/media/i2c/max2175.h index eb43373ce7e2..1ece587c153d 100644 --- a/drivers/media/i2c/max2175.h +++ b/drivers/media/i2c/max2175.h @@ -1,4 +1,5 @@ -/* +/* SPDX-License-Identifier: GPL-2.0 + * * Maxim Integrated MAX2175 RF to Bits tuner driver * * This driver & most of the hard coded values are based on the reference @@ -6,15 +7,6 @@ * * Copyright (C) 2016 Maxim Integrated Products * Copyright (C) 2017 Renesas Electronics Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #ifndef __MAX2175_H__ diff --git a/drivers/media/i2c/msp3400-driver.c b/drivers/media/i2c/msp3400-driver.c index 3db966db83eb..c63be01059b2 100644 --- a/drivers/media/i2c/msp3400-driver.c +++ b/drivers/media/i2c/msp3400-driver.c @@ -688,7 +688,7 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id) #endif if (!id) - strlcpy(client->name, "msp3400", sizeof(client->name)); + strscpy(client->name, "msp3400", sizeof(client->name)); if (msp_reset(client) == -1) { dev_dbg_lvl(&client->dev, 1, msp_debug, "msp3400 not found\n"); @@ -703,8 +703,10 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id) v4l2_i2c_subdev_init(sd, client, &msp_ops); #if defined(CONFIG_MEDIA_CONTROLLER) - state->pads[IF_AUD_DEC_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK; - state->pads[IF_AUD_DEC_PAD_OUT].flags = MEDIA_PAD_FL_SOURCE; + state->pads[MSP3400_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK; + state->pads[MSP3400_PAD_IF_INPUT].sig_type = PAD_SIGNAL_AUDIO; + state->pads[MSP3400_PAD_OUT].flags = MEDIA_PAD_FL_SOURCE; + state->pads[MSP3400_PAD_OUT].sig_type = PAD_SIGNAL_AUDIO; sd->entity.function = MEDIA_ENT_F_IF_AUD_DECODER; diff --git a/drivers/media/i2c/msp3400-driver.h b/drivers/media/i2c/msp3400-driver.h index b6c7698bce5a..2bb9d5ff1bbd 100644 --- a/drivers/media/i2c/msp3400-driver.h +++ b/drivers/media/i2c/msp3400-driver.h @@ -52,6 +52,12 @@ extern int msp_standard; extern bool msp_dolby; extern int msp_stereo_thresh; +enum msp3400_pads { + MSP3400_PAD_IF_INPUT, + MSP3400_PAD_OUT, + MSP3400_NUM_PADS +}; + struct msp_state { struct v4l2_subdev sd; struct v4l2_ctrl_handler hdl; @@ -106,7 +112,7 @@ struct msp_state { unsigned int watch_stereo:1; #if IS_ENABLED(CONFIG_MEDIA_CONTROLLER) - struct media_pad pads[IF_AUD_DEC_PAD_NUM_PADS]; + struct media_pad pads[MSP3400_NUM_PADS]; #endif }; diff --git a/drivers/media/i2c/mt9m111.c b/drivers/media/i2c/mt9m111.c index efda1aa95ca0..1395986a07bb 100644 --- a/drivers/media/i2c/mt9m111.c +++ b/drivers/media/i2c/mt9m111.c @@ -445,7 +445,6 @@ static int mt9m111_get_selection(struct v4l2_subdev *sd, switch (sel->target) { case V4L2_SEL_TGT_CROP_BOUNDS: - case V4L2_SEL_TGT_CROP_DEFAULT: sel->r.left = MT9M111_MIN_DARK_COLS; sel->r.top = MT9M111_MIN_DARK_ROWS; sel->r.width = MT9M111_MAX_WIDTH; diff --git a/drivers/media/i2c/mt9t112.c b/drivers/media/i2c/mt9t112.c index af8cca984215..ef353a244e33 100644 --- a/drivers/media/i2c/mt9t112.c +++ b/drivers/media/i2c/mt9t112.c @@ -888,12 +888,6 @@ static int mt9t112_get_selection(struct v4l2_subdev *sd, sel->r.width = MAX_WIDTH; sel->r.height = MAX_HEIGHT; return 0; - case V4L2_SEL_TGT_CROP_DEFAULT: - sel->r.left = 0; - sel->r.top = 0; - sel->r.width = VGA_WIDTH; - sel->r.height = VGA_HEIGHT; - return 0; case V4L2_SEL_TGT_CROP: sel->r = priv->frame; return 0; diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c index f74730d24d8f..67f69ad6ecf4 100644 --- a/drivers/media/i2c/mt9v032.c +++ b/drivers/media/i2c/mt9v032.c @@ -989,7 +989,7 @@ static struct mt9v032_platform_data * mt9v032_get_pdata(struct i2c_client *client) { struct mt9v032_platform_data *pdata = NULL; - struct v4l2_fwnode_endpoint endpoint; + struct v4l2_fwnode_endpoint endpoint = { .bus_type = 0 }; struct device_node *np; struct property *prop; diff --git a/drivers/media/i2c/noon010pc30.c b/drivers/media/i2c/noon010pc30.c index 88c498ad45df..11479e65a9ae 100644 --- a/drivers/media/i2c/noon010pc30.c +++ b/drivers/media/i2c/noon010pc30.c @@ -720,7 +720,8 @@ static int noon010_probe(struct i2c_client *client, mutex_init(&info->lock); sd = &info->sd; v4l2_i2c_subdev_init(sd, client, &noon010_ops); - strlcpy(sd->name, MODULE_NAME, sizeof(sd->name)); + /* Static name; NEVER use in new drivers! */ + strscpy(sd->name, MODULE_NAME, sizeof(sd->name)); sd->internal_ops = &noon010_subdev_internal_ops; sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; diff --git a/drivers/media/i2c/ov13858.c b/drivers/media/i2c/ov13858.c index a66f6201f53c..c8bbc1f52261 100644 --- a/drivers/media/i2c/ov13858.c +++ b/drivers/media/i2c/ov13858.c @@ -1230,7 +1230,7 @@ static int ov13858_set_ctrl(struct v4l2_ctrl *ctrl) * Applying V4L2 control value only happens * when power is up for streaming */ - if (pm_runtime_get_if_in_use(&client->dev) <= 0) + if (!pm_runtime_get_if_in_use(&client->dev)) return 0; ret = 0; @@ -1735,10 +1735,9 @@ static int ov13858_probe(struct i2c_client *client, * Device is already turned on by i2c-core with ACPI domain PM. * Enable runtime PM and turn off the device. */ - pm_runtime_get_noresume(&client->dev); pm_runtime_set_active(&client->dev); pm_runtime_enable(&client->dev); - pm_runtime_put(&client->dev); + pm_runtime_idle(&client->dev); return 0; @@ -1761,14 +1760,7 @@ static int ov13858_remove(struct i2c_client *client) media_entity_cleanup(&sd->entity); ov13858_free_controls(ov13858); - /* - * Disable runtime PM but keep the device turned on. - * i2c-core with ACPI domain PM will turn off the device. - */ - pm_runtime_get_sync(&client->dev); pm_runtime_disable(&client->dev); - pm_runtime_set_suspended(&client->dev); - pm_runtime_put_noidle(&client->dev); return 0; } diff --git a/drivers/media/i2c/ov2640.c b/drivers/media/i2c/ov2640.c index beb722065152..20a8853ba1e2 100644 --- a/drivers/media/i2c/ov2640.c +++ b/drivers/media/i2c/ov2640.c @@ -1010,7 +1010,6 @@ static int ov2640_get_selection(struct v4l2_subdev *sd, switch (sel->target) { case V4L2_SEL_TGT_CROP_BOUNDS: - case V4L2_SEL_TGT_CROP_DEFAULT: case V4L2_SEL_TGT_CROP: sel->r.left = 0; sel->r.top = 0; diff --git a/drivers/media/i2c/ov2659.c b/drivers/media/i2c/ov2659.c index 4715edc8ca33..799acce803fe 100644 --- a/drivers/media/i2c/ov2659.c +++ b/drivers/media/i2c/ov2659.c @@ -1347,8 +1347,9 @@ static struct ov2659_platform_data * ov2659_get_pdata(struct i2c_client *client) { struct ov2659_platform_data *pdata; - struct v4l2_fwnode_endpoint *bus_cfg; + struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 }; struct device_node *endpoint; + int ret; if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) return client->dev.platform_data; @@ -1357,8 +1358,9 @@ ov2659_get_pdata(struct i2c_client *client) if (!endpoint) return NULL; - bus_cfg = v4l2_fwnode_endpoint_alloc_parse(of_fwnode_handle(endpoint)); - if (IS_ERR(bus_cfg)) { + ret = v4l2_fwnode_endpoint_alloc_parse(of_fwnode_handle(endpoint), + &bus_cfg); + if (ret) { pdata = NULL; goto done; } @@ -1367,17 +1369,17 @@ ov2659_get_pdata(struct i2c_client *client) if (!pdata) goto done; - if (!bus_cfg->nr_of_link_frequencies) { + if (!bus_cfg.nr_of_link_frequencies) { dev_err(&client->dev, "link-frequencies property not found or too many\n"); pdata = NULL; goto done; } - pdata->link_frequency = bus_cfg->link_frequencies[0]; + pdata->link_frequency = bus_cfg.link_frequencies[0]; done: - v4l2_fwnode_endpoint_free(bus_cfg); + v4l2_fwnode_endpoint_free(&bus_cfg); of_node_put(endpoint); return pdata; } diff --git a/drivers/media/i2c/ov2680.c b/drivers/media/i2c/ov2680.c index f753a1c333ef..0e34e15b67b3 100644 --- a/drivers/media/i2c/ov2680.c +++ b/drivers/media/i2c/ov2680.c @@ -926,7 +926,7 @@ static int ov2680_mode_init(struct ov2680_dev *sensor) return 0; } -static int ov2680_v4l2_init(struct ov2680_dev *sensor) +static int ov2680_v4l2_register(struct ov2680_dev *sensor) { const struct v4l2_ctrl_ops *ops = &ov2680_ctrl_ops; struct ov2680_ctrls *ctrls = &sensor->ctrls; @@ -1088,26 +1088,20 @@ static int ov2680_probe(struct i2c_client *client) mutex_init(&sensor->lock); - ret = ov2680_v4l2_init(sensor); + ret = ov2680_check_id(sensor); if (ret < 0) goto lock_destroy; - ret = ov2680_check_id(sensor); + ret = ov2680_v4l2_register(sensor); if (ret < 0) - goto error_cleanup; + goto lock_destroy; dev_info(dev, "ov2680 init correctly\n"); return 0; -error_cleanup: - dev_err(dev, "ov2680 init fail: %d\n", ret); - - media_entity_cleanup(&sensor->sd.entity); - v4l2_async_unregister_subdev(&sensor->sd); - v4l2_ctrl_handler_free(&sensor->ctrls.handler); - lock_destroy: + dev_err(dev, "ov2680 init fail: %d\n", ret); mutex_destroy(&sensor->lock); return ret; diff --git a/drivers/media/i2c/ov2685.c b/drivers/media/i2c/ov2685.c index 385c1886a947..98a1f2e312b5 100644 --- a/drivers/media/i2c/ov2685.c +++ b/drivers/media/i2c/ov2685.c @@ -549,7 +549,7 @@ static int ov2685_set_ctrl(struct v4l2_ctrl *ctrl) break; } - if (pm_runtime_get_if_in_use(&client->dev) <= 0) + if (!pm_runtime_get_if_in_use(&client->dev)) return 0; switch (ctrl->id) { diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c index 071f4bc240ca..eaefdb58653b 100644 --- a/drivers/media/i2c/ov5640.c +++ b/drivers/media/i2c/ov5640.c @@ -223,8 +223,10 @@ struct ov5640_dev { int power_count; struct v4l2_mbus_framefmt fmt; + bool pending_fmt_change; const struct ov5640_mode_info *current_mode; + const struct ov5640_mode_info *last_mode; enum ov5640_frame_rate current_fr; struct v4l2_fract frame_interval; @@ -255,7 +257,7 @@ static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl) * should be identified and removed to speed register load time * over i2c. */ - +/* YUV422 UYVY VGA@30fps */ static const struct reg_value ov5640_init_setting_30fps_VGA[] = { {0x3103, 0x11, 0, 0}, {0x3008, 0x82, 0, 5}, {0x3008, 0x42, 0, 0}, {0x3103, 0x03, 0, 0}, {0x3017, 0x00, 0, 0}, {0x3018, 0x00, 0, 0}, @@ -286,10 +288,10 @@ static const struct reg_value ov5640_init_setting_30fps_VGA[] = { {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0}, {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x3000, 0x00, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3006, 0xc3, 0, 0}, - {0x300e, 0x45, 0, 0}, {0x302e, 0x08, 0, 0}, {0x4300, 0x3f, 0, 0}, + {0x302e, 0x08, 0, 0}, {0x4300, 0x3f, 0, 0}, {0x501f, 0x00, 0, 0}, {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x440e, 0x00, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0}, - {0x4837, 0x0a, 0, 0}, {0x4800, 0x04, 0, 0}, {0x3824, 0x02, 0, 0}, + {0x4837, 0x0a, 0, 0}, {0x3824, 0x02, 0, 0}, {0x5000, 0xa7, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0xf2, 0, 0}, {0x5182, 0x00, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0}, {0x5186, 0x09, 0, 0}, @@ -606,7 +608,7 @@ static const struct reg_value ov5640_setting_15fps_720P_1280_720[] = { {0x3a03, 0xe4, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0xbc, 0, 0}, {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x72, 0, 0}, {0x3a0e, 0x01, 0, 0}, {0x3a0d, 0x02, 0, 0}, {0x3a14, 0x02, 0, 0}, {0x3a15, 0xe4, 0, 0}, - {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x02, 0, 0}, + {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3824, 0x04, 0, 0}, {0x5001, 0x83, 0, 0}, }; @@ -908,6 +910,26 @@ static int ov5640_mod_reg(struct ov5640_dev *sensor, u16 reg, } /* download ov5640 settings to sensor through i2c */ +static int ov5640_set_timings(struct ov5640_dev *sensor, + const struct ov5640_mode_info *mode) +{ + int ret; + + ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_DVPHO, mode->hact); + if (ret < 0) + return ret; + + ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_DVPVO, mode->vact); + if (ret < 0) + return ret; + + ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_HTS, mode->htot); + if (ret < 0) + return ret; + + return ov5640_write_reg16(sensor, OV5640_REG_TIMING_VTS, mode->vtot); +} + static int ov5640_load_regs(struct ov5640_dev *sensor, const struct ov5640_mode_info *mode) { @@ -935,7 +957,13 @@ static int ov5640_load_regs(struct ov5640_dev *sensor, usleep_range(1000 * delay_ms, 1000 * delay_ms + 100); } - return ret; + return ov5640_set_timings(sensor, mode); +} + +static int ov5640_set_autoexposure(struct ov5640_dev *sensor, bool on) +{ + return ov5640_mod_reg(sensor, OV5640_REG_AEC_PK_MANUAL, + BIT(0), on ? 0 : BIT(0)); } /* read exposure, in number of line periods */ @@ -994,6 +1022,18 @@ static int ov5640_get_gain(struct ov5640_dev *sensor) return gain & 0x3ff; } +static int ov5640_set_gain(struct ov5640_dev *sensor, int gain) +{ + return ov5640_write_reg16(sensor, OV5640_REG_AEC_PK_REAL_GAIN, + (u16)gain & 0x3ff); +} + +static int ov5640_set_autogain(struct ov5640_dev *sensor, bool on) +{ + return ov5640_mod_reg(sensor, OV5640_REG_AEC_PK_MANUAL, + BIT(1), on ? 0 : BIT(1)); +} + static int ov5640_set_stream_dvp(struct ov5640_dev *sensor, bool on) { int ret; @@ -1102,12 +1142,25 @@ static int ov5640_set_stream_mipi(struct ov5640_dev *sensor, bool on) { int ret; - ret = ov5640_mod_reg(sensor, OV5640_REG_MIPI_CTRL00, BIT(5), - on ? 0 : BIT(5)); - if (ret) - return ret; - ret = ov5640_write_reg(sensor, OV5640_REG_PAD_OUTPUT00, - on ? 0x00 : 0x70); + /* + * Enable/disable the MIPI interface + * + * 0x300e = on ? 0x45 : 0x40 + * + * FIXME: the sensor manual (version 2.03) reports + * [7:5] = 000 : 1 data lane mode + * [7:5] = 001 : 2 data lanes mode + * But this settings do not work, while the following ones + * have been validated for 2 data lanes mode. + * + * [7:5] = 010 : 2 data lanes mode + * [4] = 0 : Power up MIPI HS Tx + * [3] = 0 : Power up MIPI LS Rx + * [2] = 1/0 : MIPI interface enable/disable + * [1:0] = 01/00: FIXME: 'debug' + */ + ret = ov5640_write_reg(sensor, OV5640_REG_IO_MIPI_CTRL00, + on ? 0x45 : 0x40); if (ret) return ret; @@ -1331,7 +1384,7 @@ static int ov5640_set_ae_target(struct ov5640_dev *sensor, int target) return ov5640_write_reg(sensor, OV5640_REG_AEC_CTRL1F, fast_low); } -static int ov5640_binning_on(struct ov5640_dev *sensor) +static int ov5640_get_binning(struct ov5640_dev *sensor) { u8 temp; int ret; @@ -1339,8 +1392,8 @@ static int ov5640_binning_on(struct ov5640_dev *sensor) ret = ov5640_read_reg(sensor, OV5640_REG_TIMING_TC_REG21, &temp); if (ret) return ret; - temp &= 0xfe; - return temp ? 1 : 0; + + return temp & BIT(0); } static int ov5640_set_binning(struct ov5640_dev *sensor, bool enable) @@ -1385,30 +1438,6 @@ static int ov5640_set_virtual_channel(struct ov5640_dev *sensor) return ov5640_write_reg(sensor, OV5640_REG_DEBUG_MODE, temp); } -static int ov5640_set_timings(struct ov5640_dev *sensor, - const struct ov5640_mode_info *mode) -{ - int ret; - - ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_DVPHO, mode->hact); - if (ret < 0) - return ret; - - ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_DVPVO, mode->vact); - if (ret < 0) - return ret; - - ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_HTS, mode->htot); - if (ret < 0) - return ret; - - ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_VTS, mode->vtot); - if (ret < 0) - return ret; - - return 0; -} - static const struct ov5640_mode_info * ov5640_find_mode(struct ov5640_dev *sensor, enum ov5640_frame_rate fr, int width, int height, bool nearest) @@ -1450,7 +1479,7 @@ static int ov5640_set_mode_exposure_calc(struct ov5640_dev *sensor, if (ret < 0) return ret; prev_shutter = ret; - ret = ov5640_binning_on(sensor); + ret = ov5640_get_binning(sensor); if (ret < 0) return ret; if (ret && mode->id != OV5640_MODE_720P_1280_720 && @@ -1571,7 +1600,7 @@ static int ov5640_set_mode_exposure_calc(struct ov5640_dev *sensor, } /* set capture gain */ - ret = __v4l2_ctrl_s_ctrl(sensor->ctrls.gain, cap_gain16); + ret = ov5640_set_gain(sensor, cap_gain16); if (ret) return ret; @@ -1584,7 +1613,7 @@ static int ov5640_set_mode_exposure_calc(struct ov5640_dev *sensor, } /* set exposure */ - return __v4l2_ctrl_s_ctrl(sensor->ctrls.exposure, cap_shutter); + return ov5640_set_exposure(sensor, cap_shutter); } /* @@ -1592,53 +1621,45 @@ static int ov5640_set_mode_exposure_calc(struct ov5640_dev *sensor, * change mode directly */ static int ov5640_set_mode_direct(struct ov5640_dev *sensor, - const struct ov5640_mode_info *mode, - s32 exposure) + const struct ov5640_mode_info *mode) { - int ret; - if (!mode->reg_data) return -EINVAL; /* Write capture setting */ - ret = ov5640_load_regs(sensor, mode); - if (ret < 0) - return ret; - - /* turn auto gain/exposure back on for direct mode */ - ret = __v4l2_ctrl_s_ctrl(sensor->ctrls.auto_gain, 1); - if (ret) - return ret; - - return __v4l2_ctrl_s_ctrl(sensor->ctrls.auto_exp, exposure); + return ov5640_load_regs(sensor, mode); } -static int ov5640_set_mode(struct ov5640_dev *sensor, - const struct ov5640_mode_info *orig_mode) +static int ov5640_set_mode(struct ov5640_dev *sensor) { const struct ov5640_mode_info *mode = sensor->current_mode; + const struct ov5640_mode_info *orig_mode = sensor->last_mode; enum ov5640_downsize_mode dn_mode, orig_dn_mode; - s32 exposure; + bool auto_gain = sensor->ctrls.auto_gain->val == 1; + bool auto_exp = sensor->ctrls.auto_exp->val == V4L2_EXPOSURE_AUTO; int ret; dn_mode = mode->dn_mode; orig_dn_mode = orig_mode->dn_mode; /* auto gain and exposure must be turned off when changing modes */ - ret = __v4l2_ctrl_s_ctrl(sensor->ctrls.auto_gain, 0); - if (ret) - return ret; + if (auto_gain) { + ret = ov5640_set_autogain(sensor, false); + if (ret) + return ret; + } - exposure = sensor->ctrls.auto_exp->val; - ret = ov5640_set_exposure(sensor, V4L2_EXPOSURE_MANUAL); - if (ret) - return ret; + if (auto_exp) { + ret = ov5640_set_autoexposure(sensor, false); + if (ret) + goto restore_auto_gain; + } if ((dn_mode == SUBSAMPLING && orig_dn_mode == SCALING) || (dn_mode == SCALING && orig_dn_mode == SUBSAMPLING)) { /* * change between subsampling and scaling - * go through exposure calucation + * go through exposure calculation */ ret = ov5640_set_mode_exposure_calc(sensor, mode); } else { @@ -1646,15 +1667,16 @@ static int ov5640_set_mode(struct ov5640_dev *sensor, * change inside subsampling or scaling * download firmware directly */ - ret = ov5640_set_mode_direct(sensor, mode, exposure); + ret = ov5640_set_mode_direct(sensor, mode); } - if (ret < 0) - return ret; + goto restore_auto_exp_gain; - ret = ov5640_set_timings(sensor, mode); - if (ret < 0) - return ret; + /* restore auto gain and exposure */ + if (auto_gain) + ov5640_set_autogain(sensor, true); + if (auto_exp) + ov5640_set_autoexposure(sensor, true); ret = ov5640_set_binning(sensor, dn_mode != SCALING); if (ret < 0) @@ -1673,8 +1695,18 @@ static int ov5640_set_mode(struct ov5640_dev *sensor, return ret; sensor->pending_mode_change = false; + sensor->last_mode = mode; return 0; + +restore_auto_exp_gain: + if (auto_exp) + ov5640_set_autoexposure(sensor, true); +restore_auto_gain: + if (auto_gain) + ov5640_set_autogain(sensor, true); + + return ret; } static int ov5640_set_framefmt(struct ov5640_dev *sensor, @@ -1689,6 +1721,7 @@ static int ov5640_restore_mode(struct ov5640_dev *sensor) ret = ov5640_load_regs(sensor, &ov5640_mode_init_data); if (ret < 0) return ret; + sensor->last_mode = &ov5640_mode_init_data; ret = ov5640_mod_reg(sensor, OV5640_REG_SYS_ROOT_DIVIDER, 0x3f, (ilog2(OV5640_SCLK2X_ROOT_DIVIDER_DEFAULT) << 2) | @@ -1697,7 +1730,7 @@ static int ov5640_restore_mode(struct ov5640_dev *sensor) return ret; /* now restore the last capture mode */ - ret = ov5640_set_mode(sensor, &ov5640_mode_init_data); + ret = ov5640_set_mode(sensor); if (ret < 0) return ret; @@ -1786,23 +1819,69 @@ static int ov5640_set_power(struct ov5640_dev *sensor, bool on) if (ret) goto power_off; - if (sensor->ep.bus_type == V4L2_MBUS_CSI2) { - /* - * start streaming briefly followed by stream off in - * order to coax the clock lane into LP-11 state. - */ - ret = ov5640_set_stream_mipi(sensor, true); - if (ret) - goto power_off; - usleep_range(1000, 2000); - ret = ov5640_set_stream_mipi(sensor, false); - if (ret) - goto power_off; + /* We're done here for DVP bus, while CSI-2 needs setup. */ + if (sensor->ep.bus_type != V4L2_MBUS_CSI2_DPHY) + return 0; + + /* + * Power up MIPI HS Tx and LS Rx; 2 data lanes mode + * + * 0x300e = 0x40 + * [7:5] = 010 : 2 data lanes mode (see FIXME note in + * "ov5640_set_stream_mipi()") + * [4] = 0 : Power up MIPI HS Tx + * [3] = 0 : Power up MIPI LS Rx + * [2] = 0 : MIPI interface disabled + */ + ret = ov5640_write_reg(sensor, + OV5640_REG_IO_MIPI_CTRL00, 0x40); + if (ret) + goto power_off; + + /* + * Gate clock and set LP11 in 'no packets mode' (idle) + * + * 0x4800 = 0x24 + * [5] = 1 : Gate clock when 'no packets' + * [2] = 1 : MIPI bus in LP11 when 'no packets' + */ + ret = ov5640_write_reg(sensor, + OV5640_REG_MIPI_CTRL00, 0x24); + if (ret) + goto power_off; + + /* + * Set data lanes and clock in LP11 when 'sleeping' + * + * 0x3019 = 0x70 + * [6] = 1 : MIPI data lane 2 in LP11 when 'sleeping' + * [5] = 1 : MIPI data lane 1 in LP11 when 'sleeping' + * [4] = 1 : MIPI clock lane in LP11 when 'sleeping' + */ + ret = ov5640_write_reg(sensor, + OV5640_REG_PAD_OUTPUT00, 0x70); + if (ret) + goto power_off; + + /* Give lanes some time to coax into LP11 state. */ + usleep_range(500, 1000); + + } else { + if (sensor->ep.bus_type == V4L2_MBUS_CSI2_DPHY) { + /* Reset MIPI bus settings to their default values. */ + ov5640_write_reg(sensor, + OV5640_REG_IO_MIPI_CTRL00, 0x58); + ov5640_write_reg(sensor, + OV5640_REG_MIPI_CTRL00, 0x04); + ov5640_write_reg(sensor, + OV5640_REG_PAD_OUTPUT00, 0x00); } - return 0; + ov5640_set_power_off(sensor); } + return 0; + power_off: ov5640_set_power_off(sensor); return ret; @@ -1968,9 +2047,12 @@ static int ov5640_set_fmt(struct v4l2_subdev *sd, if (new_mode != sensor->current_mode) { sensor->current_mode = new_mode; - sensor->fmt = *mbus_fmt; sensor->pending_mode_change = true; } + if (mbus_fmt->code != sensor->fmt.code) { + sensor->fmt = *mbus_fmt; + sensor->pending_fmt_change = true; + } out: mutex_unlock(&sensor->lock); return ret; @@ -2137,20 +2219,20 @@ static int ov5640_set_ctrl_white_balance(struct ov5640_dev *sensor, int awb) return ret; } -static int ov5640_set_ctrl_exposure(struct ov5640_dev *sensor, int exp) +static int ov5640_set_ctrl_exposure(struct ov5640_dev *sensor, + enum v4l2_exposure_auto_type auto_exposure) { struct ov5640_ctrls *ctrls = &sensor->ctrls; - bool auto_exposure = (exp == V4L2_EXPOSURE_AUTO); + bool auto_exp = (auto_exposure == V4L2_EXPOSURE_AUTO); int ret = 0; if (ctrls->auto_exp->is_new) { - ret = ov5640_mod_reg(sensor, OV5640_REG_AEC_PK_MANUAL, - BIT(0), auto_exposure ? 0 : BIT(0)); + ret = ov5640_set_autoexposure(sensor, auto_exp); if (ret) return ret; } - if (!auto_exposure && ctrls->exposure->is_new) { + if (!auto_exp && ctrls->exposure->is_new) { u16 max_exp; ret = ov5640_read_reg16(sensor, OV5640_REG_AEC_PK_VTS, @@ -2170,25 +2252,19 @@ static int ov5640_set_ctrl_exposure(struct ov5640_dev *sensor, int exp) return ret; } -static int ov5640_set_ctrl_gain(struct ov5640_dev *sensor, int auto_gain) +static int ov5640_set_ctrl_gain(struct ov5640_dev *sensor, bool auto_gain) { struct ov5640_ctrls *ctrls = &sensor->ctrls; int ret = 0; if (ctrls->auto_gain->is_new) { - ret = ov5640_mod_reg(sensor, OV5640_REG_AEC_PK_MANUAL, - BIT(1), - ctrls->auto_gain->val ? 0 : BIT(1)); + ret = ov5640_set_autogain(sensor, auto_gain); if (ret) return ret; } - if (!auto_gain && ctrls->gain->is_new) { - u16 gain = (u16)ctrls->gain->val; - - ret = ov5640_write_reg16(sensor, OV5640_REG_AEC_PK_REAL_GAIN, - gain & 0x3ff); - } + if (!auto_gain && ctrls->gain->is_new) + ret = ov5640_set_gain(sensor, ctrls->gain->val); return ret; } @@ -2261,16 +2337,12 @@ static int ov5640_g_volatile_ctrl(struct v4l2_ctrl *ctrl) switch (ctrl->id) { case V4L2_CID_AUTOGAIN: - if (!ctrl->val) - return 0; val = ov5640_get_gain(sensor); if (val < 0) return val; sensor->ctrls.gain->val = val; break; case V4L2_CID_EXPOSURE_AUTO: - if (ctrl->val == V4L2_EXPOSURE_MANUAL) - return 0; val = ov5640_get_exposure(sensor); if (val < 0) return val; @@ -2501,8 +2573,6 @@ static int ov5640_s_frame_interval(struct v4l2_subdev *sd, if (frame_rate < 0) frame_rate = OV5640_15_FPS; - sensor->current_fr = frame_rate; - sensor->frame_interval = fi->interval; mode = ov5640_find_mode(sensor, frame_rate, mode->hact, mode->vact, true); if (!mode) { @@ -2510,7 +2580,10 @@ static int ov5640_s_frame_interval(struct v4l2_subdev *sd, goto out; } - if (mode != sensor->current_mode) { + if (mode != sensor->current_mode || + frame_rate != sensor->current_fr) { + sensor->current_fr = frame_rate; + sensor->frame_interval = fi->interval; sensor->current_mode = mode; sensor->pending_mode_change = true; } @@ -2541,16 +2614,19 @@ static int ov5640_s_stream(struct v4l2_subdev *sd, int enable) if (sensor->streaming == !enable) { if (enable && sensor->pending_mode_change) { - ret = ov5640_set_mode(sensor, sensor->current_mode); + ret = ov5640_set_mode(sensor); if (ret) goto out; + } + if (enable && sensor->pending_fmt_change) { ret = ov5640_set_framefmt(sensor, &sensor->fmt); if (ret) goto out; + sensor->pending_fmt_change = false; } - if (sensor->ep.bus_type == V4L2_MBUS_CSI2) + if (sensor->ep.bus_type == V4L2_MBUS_CSI2_DPHY) ret = ov5640_set_stream_mipi(sensor, enable); else ret = ov5640_set_stream_dvp(sensor, enable); @@ -2642,9 +2718,14 @@ static int ov5640_probe(struct i2c_client *client, return -ENOMEM; sensor->i2c_client = client; + + /* + * default init sequence initialize sensor to + * YUV422 UYVY VGA@30fps + */ fmt = &sensor->fmt; - fmt->code = ov5640_formats[0].code; - fmt->colorspace = ov5640_formats[0].colorspace; + fmt->code = MEDIA_BUS_FMT_UYVY8_2X8; + fmt->colorspace = V4L2_COLORSPACE_SRGB; fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace); fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE; fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt->colorspace); @@ -2656,7 +2737,7 @@ static int ov5640_probe(struct i2c_client *client, sensor->current_fr = OV5640_30_FPS; sensor->current_mode = &ov5640_mode_data[OV5640_30_FPS][OV5640_MODE_VGA_640_480]; - sensor->pending_mode_change = true; + sensor->last_mode = sensor->current_mode; sensor->ae_target = 52; diff --git a/drivers/media/i2c/ov5645.c b/drivers/media/i2c/ov5645.c index 1722cdab0daf..5eba8dd7222b 100644 --- a/drivers/media/i2c/ov5645.c +++ b/drivers/media/i2c/ov5645.c @@ -1127,7 +1127,7 @@ static int ov5645_probe(struct i2c_client *client, return ret; } - if (ov5645->ep.bus_type != V4L2_MBUS_CSI2) { + if (ov5645->ep.bus_type != V4L2_MBUS_CSI2_DPHY) { dev_err(dev, "invalid bus type, must be CSI2\n"); return -EINVAL; } diff --git a/drivers/media/i2c/ov5647.c b/drivers/media/i2c/ov5647.c index da39c49de503..4589631798c9 100644 --- a/drivers/media/i2c/ov5647.c +++ b/drivers/media/i2c/ov5647.c @@ -532,7 +532,7 @@ static const struct v4l2_subdev_internal_ops ov5647_subdev_internal_ops = { static int ov5647_parse_dt(struct device_node *np) { - struct v4l2_fwnode_endpoint bus_cfg; + struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 }; struct device_node *ep; int ret; diff --git a/drivers/media/i2c/ov5670.c b/drivers/media/i2c/ov5670.c index 7b7c74d77370..041fcbb4eebd 100644 --- a/drivers/media/i2c/ov5670.c +++ b/drivers/media/i2c/ov5670.c @@ -2016,7 +2016,7 @@ static int ov5670_set_ctrl(struct v4l2_ctrl *ctrl) } /* V4L2 controls values will be applied only when power is already up */ - if (pm_runtime_get_if_in_use(&client->dev) <= 0) + if (!pm_runtime_get_if_in_use(&client->dev)) return 0; switch (ctrl->id) { @@ -2504,10 +2504,9 @@ static int ov5670_probe(struct i2c_client *client) * Device is already turned on by i2c-core with ACPI domain PM. * Enable runtime PM and turn off the device. */ - pm_runtime_get_noresume(&client->dev); pm_runtime_set_active(&client->dev); pm_runtime_enable(&client->dev); - pm_runtime_put(&client->dev); + pm_runtime_idle(&client->dev); return 0; @@ -2536,14 +2535,7 @@ static int ov5670_remove(struct i2c_client *client) v4l2_ctrl_handler_free(sd->ctrl_handler); mutex_destroy(&ov5670->mutex); - /* - * Disable runtime PM but keep the device turned on. - * i2c-core with ACPI domain PM will turn off the device. - */ - pm_runtime_get_sync(&client->dev); pm_runtime_disable(&client->dev); - pm_runtime_set_suspended(&client->dev); - pm_runtime_put_noidle(&client->dev); return 0; } diff --git a/drivers/media/i2c/ov5695.c b/drivers/media/i2c/ov5695.c index 9a80decd93d3..5d107c53364d 100644 --- a/drivers/media/i2c/ov5695.c +++ b/drivers/media/i2c/ov5695.c @@ -1110,7 +1110,7 @@ static int ov5695_set_ctrl(struct v4l2_ctrl *ctrl) break; } - if (pm_runtime_get_if_in_use(&client->dev) <= 0) + if (!pm_runtime_get_if_in_use(&client->dev)) return 0; switch (ctrl->id) { diff --git a/drivers/media/i2c/ov6650.c b/drivers/media/i2c/ov6650.c index 17a34b4a819d..5d1b218bb7f0 100644 --- a/drivers/media/i2c/ov6650.c +++ b/drivers/media/i2c/ov6650.c @@ -449,7 +449,6 @@ static int ov6650_get_selection(struct v4l2_subdev *sd, switch (sel->target) { case V4L2_SEL_TGT_CROP_BOUNDS: - case V4L2_SEL_TGT_CROP_DEFAULT: sel->r.left = DEF_HSTRT << 1; sel->r.top = DEF_VSTRT << 1; sel->r.width = W_CIF; diff --git a/drivers/media/i2c/ov7251.c b/drivers/media/i2c/ov7251.c index d3ebb7529fca..0c10203f822b 100644 --- a/drivers/media/i2c/ov7251.c +++ b/drivers/media/i2c/ov7251.c @@ -1279,9 +1279,9 @@ static int ov7251_probe(struct i2c_client *client) return ret; } - if (ov7251->ep.bus_type != V4L2_MBUS_CSI2) { + if (ov7251->ep.bus_type != V4L2_MBUS_CSI2_DPHY) { dev_err(dev, "invalid bus type (%u), must be CSI2 (%u)\n", - ov7251->ep.bus_type, V4L2_MBUS_CSI2); + ov7251->ep.bus_type, V4L2_MBUS_CSI2_DPHY); return -EINVAL; } diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c index 31bf577b0bd3..bc68a3a5b4ec 100644 --- a/drivers/media/i2c/ov7670.c +++ b/drivers/media/i2c/ov7670.c @@ -1728,7 +1728,7 @@ static int ov7670_parse_dt(struct device *dev, struct ov7670_info *info) { struct fwnode_handle *fwnode = dev_fwnode(dev); - struct v4l2_fwnode_endpoint bus_cfg; + struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 }; struct fwnode_handle *ep; int ret; @@ -1808,17 +1808,24 @@ static int ov7670_probe(struct i2c_client *client, info->pclk_hb_disable = true; } - info->clk = devm_clk_get(&client->dev, "xclk"); - if (IS_ERR(info->clk)) - return PTR_ERR(info->clk); - ret = clk_prepare_enable(info->clk); - if (ret) - return ret; + info->clk = devm_clk_get(&client->dev, "xclk"); /* optional */ + if (IS_ERR(info->clk)) { + ret = PTR_ERR(info->clk); + if (ret == -ENOENT) + info->clk = NULL; + else + return ret; + } + if (info->clk) { + ret = clk_prepare_enable(info->clk); + if (ret) + return ret; - info->clock_speed = clk_get_rate(info->clk) / 1000000; - if (info->clock_speed < 10 || info->clock_speed > 48) { - ret = -EINVAL; - goto clk_disable; + info->clock_speed = clk_get_rate(info->clk) / 1000000; + if (info->clock_speed < 10 || info->clock_speed > 48) { + ret = -EINVAL; + goto clk_disable; + } } ret = ov7670_init_gpio(client, info); diff --git a/drivers/media/i2c/ov772x.c b/drivers/media/i2c/ov772x.c index 7158c31d8403..fefff7fd7d68 100644 --- a/drivers/media/i2c/ov772x.c +++ b/drivers/media/i2c/ov772x.c @@ -21,6 +21,7 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/regmap.h> #include <linux/slab.h> #include <linux/v4l2-mediabus.h> #include <linux/videodev2.h> @@ -414,6 +415,7 @@ struct ov772x_priv { struct v4l2_subdev subdev; struct v4l2_ctrl_handler hdl; struct clk *clk; + struct regmap *regmap; struct ov772x_camera_info *info; struct gpio_desc *pwdn_gpio; struct gpio_desc *rstb_gpio; @@ -549,51 +551,18 @@ static struct ov772x_priv *to_ov772x(struct v4l2_subdev *sd) return container_of(sd, struct ov772x_priv, subdev); } -static int ov772x_read(struct i2c_client *client, u8 addr) -{ - int ret; - u8 val; - - ret = i2c_master_send(client, &addr, 1); - if (ret < 0) - return ret; - ret = i2c_master_recv(client, &val, 1); - if (ret < 0) - return ret; - - return val; -} - -static inline int ov772x_write(struct i2c_client *client, u8 addr, u8 value) -{ - return i2c_smbus_write_byte_data(client, addr, value); -} - -static int ov772x_mask_set(struct i2c_client *client, u8 command, u8 mask, - u8 set) -{ - s32 val = ov772x_read(client, command); - - if (val < 0) - return val; - - val &= ~mask; - val |= set & mask; - - return ov772x_write(client, command, val); -} - -static int ov772x_reset(struct i2c_client *client) +static int ov772x_reset(struct ov772x_priv *priv) { int ret; - ret = ov772x_write(client, COM7, SCCB_RESET); + ret = regmap_write(priv->regmap, COM7, SCCB_RESET); if (ret < 0) return ret; usleep_range(1000, 5000); - return ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE); + return regmap_update_bits(priv->regmap, COM2, SOFT_SLEEP_MODE, + SOFT_SLEEP_MODE); } /* @@ -611,8 +580,8 @@ static int ov772x_s_stream(struct v4l2_subdev *sd, int enable) if (priv->streaming == enable) goto done; - ret = ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, - enable ? 0 : SOFT_SLEEP_MODE); + ret = regmap_update_bits(priv->regmap, COM2, SOFT_SLEEP_MODE, + enable ? 0 : SOFT_SLEEP_MODE); if (ret) goto done; @@ -657,7 +626,6 @@ static int ov772x_set_frame_rate(struct ov772x_priv *priv, const struct ov772x_color_format *cfmt, const struct ov772x_win_size *win) { - struct i2c_client *client = v4l2_get_subdevdata(&priv->subdev); unsigned long fin = clk_get_rate(priv->clk); unsigned int best_diff; unsigned int fsize; @@ -723,11 +691,11 @@ static int ov772x_set_frame_rate(struct ov772x_priv *priv, } } - ret = ov772x_write(client, COM4, com4 | COM4_RESERVED); + ret = regmap_write(priv->regmap, COM4, com4 | COM4_RESERVED); if (ret < 0) return ret; - ret = ov772x_write(client, CLKRC, clkrc | CLKRC_RESERVED); + ret = regmap_write(priv->regmap, CLKRC, clkrc | CLKRC_RESERVED); if (ret < 0) return ret; @@ -788,8 +756,7 @@ static int ov772x_s_ctrl(struct v4l2_ctrl *ctrl) { struct ov772x_priv *priv = container_of(ctrl->handler, struct ov772x_priv, hdl); - struct v4l2_subdev *sd = &priv->subdev; - struct i2c_client *client = v4l2_get_subdevdata(sd); + struct regmap *regmap = priv->regmap; int ret = 0; u8 val; @@ -808,27 +775,27 @@ static int ov772x_s_ctrl(struct v4l2_ctrl *ctrl) val = ctrl->val ? VFLIP_IMG : 0x00; if (priv->info && (priv->info->flags & OV772X_FLAG_VFLIP)) val ^= VFLIP_IMG; - return ov772x_mask_set(client, COM3, VFLIP_IMG, val); + return regmap_update_bits(regmap, COM3, VFLIP_IMG, val); case V4L2_CID_HFLIP: val = ctrl->val ? HFLIP_IMG : 0x00; if (priv->info && (priv->info->flags & OV772X_FLAG_HFLIP)) val ^= HFLIP_IMG; - return ov772x_mask_set(client, COM3, HFLIP_IMG, val); + return regmap_update_bits(regmap, COM3, HFLIP_IMG, val); case V4L2_CID_BAND_STOP_FILTER: if (!ctrl->val) { /* Switch the filter off, it is on now */ - ret = ov772x_mask_set(client, BDBASE, 0xff, 0xff); + ret = regmap_update_bits(regmap, BDBASE, 0xff, 0xff); if (!ret) - ret = ov772x_mask_set(client, COM8, - BNDF_ON_OFF, 0); + ret = regmap_update_bits(regmap, COM8, + BNDF_ON_OFF, 0); } else { /* Switch the filter on, set AEC low limit */ val = 256 - ctrl->val; - ret = ov772x_mask_set(client, COM8, - BNDF_ON_OFF, BNDF_ON_OFF); + ret = regmap_update_bits(regmap, COM8, + BNDF_ON_OFF, BNDF_ON_OFF); if (!ret) - ret = ov772x_mask_set(client, BDBASE, - 0xff, val); + ret = regmap_update_bits(regmap, BDBASE, + 0xff, val); } return ret; @@ -841,18 +808,19 @@ static int ov772x_s_ctrl(struct v4l2_ctrl *ctrl) static int ov772x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); + struct ov772x_priv *priv = to_ov772x(sd); int ret; + unsigned int val; reg->size = 1; if (reg->reg > 0xff) return -EINVAL; - ret = ov772x_read(client, reg->reg); + ret = regmap_read(priv->regmap, reg->reg, &val); if (ret < 0) return ret; - reg->val = (__u64)ret; + reg->val = (__u64)val; return 0; } @@ -860,13 +828,13 @@ static int ov772x_g_register(struct v4l2_subdev *sd, static int ov772x_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); + struct ov772x_priv *priv = to_ov772x(sd); if (reg->reg > 0xff || reg->val > 0xff) return -EINVAL; - return ov772x_write(client, reg->reg, reg->val); + return regmap_write(priv->regmap, reg->reg, reg->val); } #endif @@ -896,6 +864,7 @@ static int ov772x_power_on(struct ov772x_priv *priv) GPIOD_OUT_LOW); if (IS_ERR(priv->rstb_gpio)) { dev_info(&client->dev, "Unable to get GPIO \"reset\""); + clk_disable_unprepare(priv->clk); return PTR_ERR(priv->rstb_gpio); } @@ -1004,7 +973,7 @@ static void ov772x_select_params(const struct v4l2_mbus_framefmt *mf, static int ov772x_edgectrl(struct ov772x_priv *priv) { - struct i2c_client *client = v4l2_get_subdevdata(&priv->subdev); + struct regmap *regmap = priv->regmap; int ret; if (!priv->info) @@ -1018,19 +987,19 @@ static int ov772x_edgectrl(struct ov772x_priv *priv) * Remove it when manual mode. */ - ret = ov772x_mask_set(client, DSPAUTO, EDGE_ACTRL, 0x00); + ret = regmap_update_bits(regmap, DSPAUTO, EDGE_ACTRL, 0x00); if (ret < 0) return ret; - ret = ov772x_mask_set(client, - EDGE_TRSHLD, OV772X_EDGE_THRESHOLD_MASK, - priv->info->edgectrl.threshold); + ret = regmap_update_bits(regmap, EDGE_TRSHLD, + OV772X_EDGE_THRESHOLD_MASK, + priv->info->edgectrl.threshold); if (ret < 0) return ret; - ret = ov772x_mask_set(client, - EDGE_STRNGT, OV772X_EDGE_STRENGTH_MASK, - priv->info->edgectrl.strength); + ret = regmap_update_bits(regmap, EDGE_STRNGT, + OV772X_EDGE_STRENGTH_MASK, + priv->info->edgectrl.strength); if (ret < 0) return ret; @@ -1040,15 +1009,15 @@ static int ov772x_edgectrl(struct ov772x_priv *priv) * * Set upper and lower limit. */ - ret = ov772x_mask_set(client, - EDGE_UPPER, OV772X_EDGE_UPPER_MASK, - priv->info->edgectrl.upper); + ret = regmap_update_bits(regmap, EDGE_UPPER, + OV772X_EDGE_UPPER_MASK, + priv->info->edgectrl.upper); if (ret < 0) return ret; - ret = ov772x_mask_set(client, - EDGE_LOWER, OV772X_EDGE_LOWER_MASK, - priv->info->edgectrl.lower); + ret = regmap_update_bits(regmap, EDGE_LOWER, + OV772X_EDGE_LOWER_MASK, + priv->info->edgectrl.lower); if (ret < 0) return ret; } @@ -1060,12 +1029,11 @@ static int ov772x_set_params(struct ov772x_priv *priv, const struct ov772x_color_format *cfmt, const struct ov772x_win_size *win) { - struct i2c_client *client = v4l2_get_subdevdata(&priv->subdev); int ret; u8 val; /* Reset hardware. */ - ov772x_reset(client); + ov772x_reset(priv); /* Edge Ctrl. */ ret = ov772x_edgectrl(priv); @@ -1073,32 +1041,32 @@ static int ov772x_set_params(struct ov772x_priv *priv, return ret; /* Format and window size. */ - ret = ov772x_write(client, HSTART, win->rect.left >> 2); + ret = regmap_write(priv->regmap, HSTART, win->rect.left >> 2); if (ret < 0) goto ov772x_set_fmt_error; - ret = ov772x_write(client, HSIZE, win->rect.width >> 2); + ret = regmap_write(priv->regmap, HSIZE, win->rect.width >> 2); if (ret < 0) goto ov772x_set_fmt_error; - ret = ov772x_write(client, VSTART, win->rect.top >> 1); + ret = regmap_write(priv->regmap, VSTART, win->rect.top >> 1); if (ret < 0) goto ov772x_set_fmt_error; - ret = ov772x_write(client, VSIZE, win->rect.height >> 1); + ret = regmap_write(priv->regmap, VSIZE, win->rect.height >> 1); if (ret < 0) goto ov772x_set_fmt_error; - ret = ov772x_write(client, HOUTSIZE, win->rect.width >> 2); + ret = regmap_write(priv->regmap, HOUTSIZE, win->rect.width >> 2); if (ret < 0) goto ov772x_set_fmt_error; - ret = ov772x_write(client, VOUTSIZE, win->rect.height >> 1); + ret = regmap_write(priv->regmap, VOUTSIZE, win->rect.height >> 1); if (ret < 0) goto ov772x_set_fmt_error; - ret = ov772x_write(client, HREF, + ret = regmap_write(priv->regmap, HREF, ((win->rect.top & 1) << HREF_VSTART_SHIFT) | ((win->rect.left & 3) << HREF_HSTART_SHIFT) | ((win->rect.height & 1) << HREF_VSIZE_SHIFT) | ((win->rect.width & 3) << HREF_HSIZE_SHIFT)); if (ret < 0) goto ov772x_set_fmt_error; - ret = ov772x_write(client, EXHCH, + ret = regmap_write(priv->regmap, EXHCH, ((win->rect.height & 1) << EXHCH_VSIZE_SHIFT) | ((win->rect.width & 3) << EXHCH_HSIZE_SHIFT)); if (ret < 0) @@ -1107,15 +1075,14 @@ static int ov772x_set_params(struct ov772x_priv *priv, /* Set DSP_CTRL3. */ val = cfmt->dsp3; if (val) { - ret = ov772x_mask_set(client, - DSP_CTRL3, UV_MASK, val); + ret = regmap_update_bits(priv->regmap, DSP_CTRL3, UV_MASK, val); if (ret < 0) goto ov772x_set_fmt_error; } /* DSP_CTRL4: AEC reference point and DSP output format. */ if (cfmt->dsp4) { - ret = ov772x_write(client, DSP_CTRL4, cfmt->dsp4); + ret = regmap_write(priv->regmap, DSP_CTRL4, cfmt->dsp4); if (ret < 0) goto ov772x_set_fmt_error; } @@ -1131,13 +1098,12 @@ static int ov772x_set_params(struct ov772x_priv *priv, if (priv->hflip_ctrl->val) val ^= HFLIP_IMG; - ret = ov772x_mask_set(client, - COM3, SWAP_MASK | IMG_MASK, val); + ret = regmap_update_bits(priv->regmap, COM3, SWAP_MASK | IMG_MASK, val); if (ret < 0) goto ov772x_set_fmt_error; /* COM7: Sensor resolution and output format control. */ - ret = ov772x_write(client, COM7, win->com7_bit | cfmt->com7); + ret = regmap_write(priv->regmap, COM7, win->com7_bit | cfmt->com7); if (ret < 0) goto ov772x_set_fmt_error; @@ -1150,10 +1116,11 @@ static int ov772x_set_params(struct ov772x_priv *priv, if (priv->band_filter_ctrl->val) { unsigned short band_filter = priv->band_filter_ctrl->val; - ret = ov772x_mask_set(client, COM8, BNDF_ON_OFF, BNDF_ON_OFF); + ret = regmap_update_bits(priv->regmap, COM8, + BNDF_ON_OFF, BNDF_ON_OFF); if (!ret) - ret = ov772x_mask_set(client, BDBASE, - 0xff, 256 - band_filter); + ret = regmap_update_bits(priv->regmap, BDBASE, + 0xff, 256 - band_filter); if (ret < 0) goto ov772x_set_fmt_error; } @@ -1162,7 +1129,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, ov772x_set_fmt_error: - ov772x_reset(client); + ov772x_reset(priv); return ret; } @@ -1180,7 +1147,6 @@ static int ov772x_get_selection(struct v4l2_subdev *sd, sel->r.top = 0; switch (sel->target) { case V4L2_SEL_TGT_CROP_BOUNDS: - case V4L2_SEL_TGT_CROP_DEFAULT: case V4L2_SEL_TGT_CROP: sel->r.width = priv->win->rect.width; sel->r.height = priv->win->rect.height; @@ -1276,12 +1242,12 @@ static int ov772x_video_probe(struct ov772x_priv *priv) return ret; /* Check and show product ID and manufacturer ID. */ - pid = ov772x_read(client, PID); - if (pid < 0) - return pid; - ver = ov772x_read(client, VER); - if (ver < 0) - return ver; + ret = regmap_read(priv->regmap, PID, &pid); + if (ret < 0) + return ret; + ret = regmap_read(priv->regmap, VER, &ver); + if (ret < 0) + return ret; switch (VERSION(pid, ver)) { case OV7720: @@ -1297,12 +1263,12 @@ static int ov772x_video_probe(struct ov772x_priv *priv) goto done; } - midh = ov772x_read(client, MIDH); - if (midh < 0) - return midh; - midl = ov772x_read(client, MIDL); - if (midl < 0) - return midl; + ret = regmap_read(priv->regmap, MIDH, &midh); + if (ret < 0) + return ret; + ret = regmap_read(priv->regmap, MIDL, &midl); + if (ret < 0) + return ret; dev_info(&client->dev, "%s Product ID %0x:%0x Manufacturer ID %x:%x\n", @@ -1386,8 +1352,12 @@ static int ov772x_probe(struct i2c_client *client, const struct i2c_device_id *did) { struct ov772x_priv *priv; - struct i2c_adapter *adapter = client->adapter; int ret; + static const struct regmap_config ov772x_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = DSPAUTO, + }; if (!client->dev.of_node && !client->dev.platform_data) { dev_err(&client->dev, @@ -1395,16 +1365,16 @@ static int ov772x_probe(struct i2c_client *client, return -EINVAL; } - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { - dev_err(&adapter->dev, - "I2C-Adapter doesn't support SMBUS_BYTE_DATA\n"); - return -EIO; - } - priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; + priv->regmap = devm_regmap_init_sccb(client, &ov772x_regmap_config); + if (IS_ERR(priv->regmap)) { + dev_err(&client->dev, "Failed to allocate register map\n"); + return PTR_ERR(priv->regmap); + } + priv->info = client->dev.platform_data; mutex_init(&priv->lock); diff --git a/drivers/media/i2c/ov7740.c b/drivers/media/i2c/ov7740.c index 605f3e25ad82..6e9c233cfbe3 100644 --- a/drivers/media/i2c/ov7740.c +++ b/drivers/media/i2c/ov7740.c @@ -510,7 +510,7 @@ static int ov7740_set_ctrl(struct v4l2_ctrl *ctrl) int ret; u8 val = 0; - if (pm_runtime_get_if_in_use(&client->dev) <= 0) + if (!pm_runtime_get_if_in_use(&client->dev)) return 0; switch (ctrl->id) { diff --git a/drivers/media/i2c/ov9650.c b/drivers/media/i2c/ov9650.c index 5bea31cd41aa..f0587c0c0a72 100644 --- a/drivers/media/i2c/ov9650.c +++ b/drivers/media/i2c/ov9650.c @@ -20,6 +20,7 @@ #include <linux/media.h> #include <linux/module.h> #include <linux/ratelimit.h> +#include <linux/regmap.h> #include <linux/slab.h> #include <linux/string.h> #include <linux/videodev2.h> @@ -259,7 +260,7 @@ struct ov965x { /* Protects the struct fields below */ struct mutex lock; - struct i2c_client *client; + struct regmap *regmap; /* Exposure row interval in us */ unsigned int exp_row_interval; @@ -424,51 +425,42 @@ static inline struct ov965x *to_ov965x(struct v4l2_subdev *sd) return container_of(sd, struct ov965x, sd); } -static int ov965x_read(struct i2c_client *client, u8 addr, u8 *val) +static int ov965x_read(struct ov965x *ov965x, u8 addr, u8 *val) { - u8 buf = addr; - struct i2c_msg msg = { - .addr = client->addr, - .flags = 0, - .len = 1, - .buf = &buf - }; int ret; + unsigned int buf; - ret = i2c_transfer(client->adapter, &msg, 1); - if (ret == 1) { - msg.flags = I2C_M_RD; - ret = i2c_transfer(client->adapter, &msg, 1); - - if (ret == 1) - *val = buf; - } + ret = regmap_read(ov965x->regmap, addr, &buf); + if (!ret) + *val = buf; + else + *val = -1; - v4l2_dbg(2, debug, client, "%s: 0x%02x @ 0x%02x. (%d)\n", + v4l2_dbg(2, debug, &ov965x->sd, "%s: 0x%02x @ 0x%02x. (%d)\n", __func__, *val, addr, ret); - return ret == 1 ? 0 : ret; + return ret; } -static int ov965x_write(struct i2c_client *client, u8 addr, u8 val) +static int ov965x_write(struct ov965x *ov965x, u8 addr, u8 val) { - u8 buf[2] = { addr, val }; + int ret; - int ret = i2c_master_send(client, buf, 2); + ret = regmap_write(ov965x->regmap, addr, val); - v4l2_dbg(2, debug, client, "%s: 0x%02x @ 0x%02X (%d)\n", + v4l2_dbg(2, debug, &ov965x->sd, "%s: 0x%02x @ 0x%02X (%d)\n", __func__, val, addr, ret); - return ret == 2 ? 0 : ret; + return ret; } -static int ov965x_write_array(struct i2c_client *client, +static int ov965x_write_array(struct ov965x *ov965x, const struct i2c_rv *regs) { int i, ret = 0; for (i = 0; ret == 0 && regs[i].addr != REG_NULL; i++) - ret = ov965x_write(client, regs[i].addr, regs[i].value); + ret = ov965x_write(ov965x, regs[i].addr, regs[i].value); return ret; } @@ -486,7 +478,7 @@ static int ov965x_set_default_gamma_curve(struct ov965x *ov965x) unsigned int i; for (i = 0; i < ARRAY_SIZE(gamma_curve); i++) { - int ret = ov965x_write(ov965x->client, addr, gamma_curve[i]); + int ret = ov965x_write(ov965x, addr, gamma_curve[i]); if (ret < 0) return ret; @@ -506,7 +498,7 @@ static int ov965x_set_color_matrix(struct ov965x *ov965x) unsigned int i; for (i = 0; i < ARRAY_SIZE(mtx); i++) { - int ret = ov965x_write(ov965x->client, addr, mtx[i]); + int ret = ov965x_write(ov965x, addr, mtx[i]); if (ret < 0) return ret; @@ -542,16 +534,15 @@ static int __ov965x_set_power(struct ov965x *ov965x, int on) static int ov965x_s_power(struct v4l2_subdev *sd, int on) { struct ov965x *ov965x = to_ov965x(sd); - struct i2c_client *client = ov965x->client; int ret = 0; - v4l2_dbg(1, debug, client, "%s: on: %d\n", __func__, on); + v4l2_dbg(1, debug, sd, "%s: on: %d\n", __func__, on); mutex_lock(&ov965x->lock); if (ov965x->power == !on) { ret = __ov965x_set_power(ov965x, on); if (!ret && on) { - ret = ov965x_write_array(client, + ret = ov965x_write_array(ov965x, ov965x_init_regs); ov965x->apply_frame_fmt = 1; ov965x->ctrls.update = 1; @@ -609,13 +600,13 @@ static int ov965x_set_banding_filter(struct ov965x *ov965x, int value) int ret; u8 reg; - ret = ov965x_read(ov965x->client, REG_COM8, ®); + ret = ov965x_read(ov965x, REG_COM8, ®); if (!ret) { if (value == V4L2_CID_POWER_LINE_FREQUENCY_DISABLED) reg &= ~COM8_BFILT; else reg |= COM8_BFILT; - ret = ov965x_write(ov965x->client, REG_COM8, reg); + ret = ov965x_write(ov965x, REG_COM8, reg); } if (value == V4L2_CID_POWER_LINE_FREQUENCY_DISABLED) return 0; @@ -631,7 +622,7 @@ static int ov965x_set_banding_filter(struct ov965x *ov965x, int value) ov965x->fiv->interval.numerator; mbd = ((mbd / (light_freq * 2)) + 500) / 1000UL; - return ov965x_write(ov965x->client, REG_MBD, mbd); + return ov965x_write(ov965x, REG_MBD, mbd); } static int ov965x_set_white_balance(struct ov965x *ov965x, int awb) @@ -639,17 +630,17 @@ static int ov965x_set_white_balance(struct ov965x *ov965x, int awb) int ret; u8 reg; - ret = ov965x_read(ov965x->client, REG_COM8, ®); + ret = ov965x_read(ov965x, REG_COM8, ®); if (!ret) { reg = awb ? reg | REG_COM8 : reg & ~REG_COM8; - ret = ov965x_write(ov965x->client, REG_COM8, reg); + ret = ov965x_write(ov965x, REG_COM8, reg); } if (!ret && !awb) { - ret = ov965x_write(ov965x->client, REG_BLUE, + ret = ov965x_write(ov965x, REG_BLUE, ov965x->ctrls.blue_balance->val); if (ret < 0) return ret; - ret = ov965x_write(ov965x->client, REG_RED, + ret = ov965x_write(ov965x, REG_RED, ov965x->ctrls.red_balance->val); } return ret; @@ -677,14 +668,13 @@ static int ov965x_set_brightness(struct ov965x *ov965x, int val) return -EINVAL; for (i = 0; i < NUM_BR_REGS && !ret; i++) - ret = ov965x_write(ov965x->client, regs[0][i], + ret = ov965x_write(ov965x, regs[0][i], regs[val][i]); return ret; } static int ov965x_set_gain(struct ov965x *ov965x, int auto_gain) { - struct i2c_client *client = ov965x->client; struct ov965x_ctrls *ctrls = &ov965x->ctrls; int ret = 0; u8 reg; @@ -693,14 +683,14 @@ static int ov965x_set_gain(struct ov965x *ov965x, int auto_gain) * gain value in REG_VREF, REG_GAIN is not overwritten. */ if (ctrls->auto_gain->is_new) { - ret = ov965x_read(client, REG_COM8, ®); + ret = ov965x_read(ov965x, REG_COM8, ®); if (ret < 0) return ret; if (ctrls->auto_gain->val) reg |= COM8_AGC; else reg &= ~COM8_AGC; - ret = ov965x_write(client, REG_COM8, reg); + ret = ov965x_write(ov965x, REG_COM8, reg); if (ret < 0) return ret; } @@ -719,15 +709,15 @@ static int ov965x_set_gain(struct ov965x *ov965x, int auto_gain) rgain = (gain - ((1 << m) * 16)) / (1 << m); rgain |= (((1 << m) - 1) << 4); - ret = ov965x_write(client, REG_GAIN, rgain & 0xff); + ret = ov965x_write(ov965x, REG_GAIN, rgain & 0xff); if (ret < 0) return ret; - ret = ov965x_read(client, REG_VREF, ®); + ret = ov965x_read(ov965x, REG_VREF, ®); if (ret < 0) return ret; reg &= ~VREF_GAIN_MASK; reg |= (((rgain >> 8) & 0x3) << 6); - ret = ov965x_write(client, REG_VREF, reg); + ret = ov965x_write(ov965x, REG_VREF, reg); if (ret < 0) return ret; /* Return updated control's value to userspace */ @@ -742,10 +732,10 @@ static int ov965x_set_sharpness(struct ov965x *ov965x, unsigned int value) u8 com14, edge; int ret; - ret = ov965x_read(ov965x->client, REG_COM14, &com14); + ret = ov965x_read(ov965x, REG_COM14, &com14); if (ret < 0) return ret; - ret = ov965x_read(ov965x->client, REG_EDGE, &edge); + ret = ov965x_read(ov965x, REG_EDGE, &edge); if (ret < 0) return ret; com14 = value ? com14 | COM14_EDGE_EN : com14 & ~COM14_EDGE_EN; @@ -756,33 +746,32 @@ static int ov965x_set_sharpness(struct ov965x *ov965x, unsigned int value) } else { com14 &= ~COM14_EEF_X2; } - ret = ov965x_write(ov965x->client, REG_COM14, com14); + ret = ov965x_write(ov965x, REG_COM14, com14); if (ret < 0) return ret; edge &= ~EDGE_FACTOR_MASK; edge |= ((u8)value & 0x0f); - return ov965x_write(ov965x->client, REG_EDGE, edge); + return ov965x_write(ov965x, REG_EDGE, edge); } static int ov965x_set_exposure(struct ov965x *ov965x, int exp) { - struct i2c_client *client = ov965x->client; struct ov965x_ctrls *ctrls = &ov965x->ctrls; bool auto_exposure = (exp == V4L2_EXPOSURE_AUTO); int ret; u8 reg; if (ctrls->auto_exp->is_new) { - ret = ov965x_read(client, REG_COM8, ®); + ret = ov965x_read(ov965x, REG_COM8, ®); if (ret < 0) return ret; if (auto_exposure) reg |= (COM8_AEC | COM8_AGC); else reg &= ~(COM8_AEC | COM8_AGC); - ret = ov965x_write(client, REG_COM8, reg); + ret = ov965x_write(ov965x, REG_COM8, reg); if (ret < 0) return ret; } @@ -794,12 +783,12 @@ static int ov965x_set_exposure(struct ov965x *ov965x, int exp) * Manual exposure value * [b15:b0] - AECHM (b15:b10), AECH (b9:b2), COM1 (b1:b0) */ - ret = ov965x_write(client, REG_COM1, exposure & 0x3); + ret = ov965x_write(ov965x, REG_COM1, exposure & 0x3); if (!ret) - ret = ov965x_write(client, REG_AECH, + ret = ov965x_write(ov965x, REG_AECH, (exposure >> 2) & 0xff); if (!ret) - ret = ov965x_write(client, REG_AECHM, + ret = ov965x_write(ov965x, REG_AECHM, (exposure >> 10) & 0x3f); /* Update the value to minimize rounding errors */ ctrls->exposure->val = ((exposure * ov965x->exp_row_interval) @@ -822,7 +811,7 @@ static int ov965x_set_flip(struct ov965x *ov965x) if (ov965x->ctrls.vflip->val) mvfp |= MVFP_FLIP; - return ov965x_write(ov965x->client, REG_MVFP, mvfp); + return ov965x_write(ov965x, REG_MVFP, mvfp); } #define NUM_SAT_LEVELS 5 @@ -846,7 +835,7 @@ static int ov965x_set_saturation(struct ov965x *ov965x, int val) return -EINVAL; for (i = 0; i < NUM_SAT_REGS && !ret; i++) - ret = ov965x_write(ov965x->client, addr + i, regs[val][i]); + ret = ov965x_write(ov965x, addr + i, regs[val][i]); return ret; } @@ -856,16 +845,15 @@ static int ov965x_set_test_pattern(struct ov965x *ov965x, int value) int ret; u8 reg; - ret = ov965x_read(ov965x->client, REG_COM23, ®); + ret = ov965x_read(ov965x, REG_COM23, ®); if (ret < 0) return ret; reg = value ? reg | COM23_TEST_MODE : reg & ~COM23_TEST_MODE; - return ov965x_write(ov965x->client, REG_COM23, reg); + return ov965x_write(ov965x, REG_COM23, reg); } static int __g_volatile_ctrl(struct ov965x *ov965x, struct v4l2_ctrl *ctrl) { - struct i2c_client *client = ov965x->client; unsigned int exposure, gain, m; u8 reg0, reg1, reg2; int ret; @@ -877,10 +865,10 @@ static int __g_volatile_ctrl(struct ov965x *ov965x, struct v4l2_ctrl *ctrl) case V4L2_CID_AUTOGAIN: if (!ctrl->val) return 0; - ret = ov965x_read(client, REG_GAIN, ®0); + ret = ov965x_read(ov965x, REG_GAIN, ®0); if (ret < 0) return ret; - ret = ov965x_read(client, REG_VREF, ®1); + ret = ov965x_read(ov965x, REG_VREF, ®1); if (ret < 0) return ret; gain = ((reg1 >> 6) << 8) | reg0; @@ -891,13 +879,13 @@ static int __g_volatile_ctrl(struct ov965x *ov965x, struct v4l2_ctrl *ctrl) case V4L2_CID_EXPOSURE_AUTO: if (ctrl->val == V4L2_EXPOSURE_MANUAL) return 0; - ret = ov965x_read(client, REG_COM1, ®0); + ret = ov965x_read(ov965x, REG_COM1, ®0); if (ret < 0) return ret; - ret = ov965x_read(client, REG_AECH, ®1); + ret = ov965x_read(ov965x, REG_AECH, ®1); if (ret < 0) return ret; - ret = ov965x_read(client, REG_AECHM, ®2); + ret = ov965x_read(ov965x, REG_AECHM, ®2); if (ret < 0) return ret; exposure = ((reg2 & 0x3f) << 10) | (reg1 << 2) | @@ -1279,32 +1267,31 @@ static int ov965x_set_frame_size(struct ov965x *ov965x) int i, ret = 0; for (i = 0; ret == 0 && i < NUM_FMT_REGS; i++) - ret = ov965x_write(ov965x->client, frame_size_reg_addr[i], + ret = ov965x_write(ov965x, frame_size_reg_addr[i], ov965x->frame_size->regs[i]); return ret; } static int __ov965x_set_params(struct ov965x *ov965x) { - struct i2c_client *client = ov965x->client; struct ov965x_ctrls *ctrls = &ov965x->ctrls; int ret = 0; u8 reg; if (ov965x->apply_frame_fmt) { reg = DEF_CLKRC + ov965x->fiv->clkrc_div; - ret = ov965x_write(client, REG_CLKRC, reg); + ret = ov965x_write(ov965x, REG_CLKRC, reg); if (ret < 0) return ret; ret = ov965x_set_frame_size(ov965x); if (ret < 0) return ret; - ret = ov965x_read(client, REG_TSLB, ®); + ret = ov965x_read(ov965x, REG_TSLB, ®); if (ret < 0) return ret; reg &= ~TSLB_YUYV_MASK; reg |= ov965x->tslb_reg; - ret = ov965x_write(client, REG_TSLB, reg); + ret = ov965x_write(ov965x, REG_TSLB, reg); if (ret < 0) return ret; } @@ -1318,10 +1305,10 @@ static int __ov965x_set_params(struct ov965x *ov965x) * Select manual banding filter, the filter will * be enabled further if required. */ - ret = ov965x_read(client, REG_COM11, ®); + ret = ov965x_read(ov965x, REG_COM11, ®); if (!ret) reg |= COM11_BANDING; - ret = ov965x_write(client, REG_COM11, reg); + ret = ov965x_write(ov965x, REG_COM11, reg); if (ret < 0) return ret; /* @@ -1333,12 +1320,11 @@ static int __ov965x_set_params(struct ov965x *ov965x) static int ov965x_s_stream(struct v4l2_subdev *sd, int on) { - struct i2c_client *client = v4l2_get_subdevdata(sd); struct ov965x *ov965x = to_ov965x(sd); struct ov965x_ctrls *ctrls = &ov965x->ctrls; int ret = 0; - v4l2_dbg(1, debug, client, "%s: on: %d\n", __func__, on); + v4l2_dbg(1, debug, sd, "%s: on: %d\n", __func__, on); mutex_lock(&ov965x->lock); if (ov965x->streaming == !on) { @@ -1358,7 +1344,7 @@ static int ov965x_s_stream(struct v4l2_subdev *sd, int on) ctrls->update = 0; } if (!ret) - ret = ov965x_write(client, REG_COM2, + ret = ov965x_write(ov965x, REG_COM2, on ? 0x01 : 0x11); } if (!ret) @@ -1421,6 +1407,7 @@ static int ov965x_configure_gpios_pdata(struct ov965x *ov965x, { int ret, i; int gpios[NUM_GPIOS]; + struct device *dev = regmap_get_device(ov965x->regmap); gpios[GPIO_PWDN] = pdata->gpio_pwdn; gpios[GPIO_RST] = pdata->gpio_reset; @@ -1430,7 +1417,7 @@ static int ov965x_configure_gpios_pdata(struct ov965x *ov965x, if (!gpio_is_valid(gpio)) continue; - ret = devm_gpio_request_one(&ov965x->client->dev, gpio, + ret = devm_gpio_request_one(dev, gpio, GPIOF_OUT_INIT_HIGH, "OV965X"); if (ret < 0) return ret; @@ -1446,7 +1433,7 @@ static int ov965x_configure_gpios_pdata(struct ov965x *ov965x, static int ov965x_configure_gpios(struct ov965x *ov965x) { - struct device *dev = &ov965x->client->dev; + struct device *dev = regmap_get_device(ov965x->regmap); ov965x->gpios[GPIO_PWDN] = devm_gpiod_get_optional(dev, "powerdown", GPIOD_OUT_HIGH); @@ -1467,7 +1454,6 @@ static int ov965x_configure_gpios(struct ov965x *ov965x) static int ov965x_detect_sensor(struct v4l2_subdev *sd) { - struct i2c_client *client = v4l2_get_subdevdata(sd); struct ov965x *ov965x = to_ov965x(sd); u8 pid, ver; int ret; @@ -1480,9 +1466,9 @@ static int ov965x_detect_sensor(struct v4l2_subdev *sd) msleep(25); /* Check sensor revision */ - ret = ov965x_read(client, REG_PID, &pid); + ret = ov965x_read(ov965x, REG_PID, &pid); if (!ret) - ret = ov965x_read(client, REG_VER, &ver); + ret = ov965x_read(ov965x, REG_VER, &ver); __ov965x_set_power(ov965x, 0); @@ -1509,12 +1495,21 @@ static int ov965x_probe(struct i2c_client *client, struct v4l2_subdev *sd; struct ov965x *ov965x; int ret; + static const struct regmap_config ov965x_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0xab, + }; ov965x = devm_kzalloc(&client->dev, sizeof(*ov965x), GFP_KERNEL); if (!ov965x) return -ENOMEM; - ov965x->client = client; + ov965x->regmap = devm_regmap_init_sccb(client, &ov965x_regmap_config); + if (IS_ERR(ov965x->regmap)) { + dev_err(&client->dev, "Failed to allocate register map\n"); + return PTR_ERR(ov965x->regmap); + } if (pdata) { if (pdata->mclk_frequency == 0) { @@ -1527,7 +1522,7 @@ static int ov965x_probe(struct i2c_client *client, if (ret < 0) return ret; } else if (dev_fwnode(&client->dev)) { - ov965x->clk = devm_clk_get(&ov965x->client->dev, NULL); + ov965x->clk = devm_clk_get(&client->dev, NULL); if (IS_ERR(ov965x->clk)) return PTR_ERR(ov965x->clk); ov965x->mclk_frequency = clk_get_rate(ov965x->clk); @@ -1546,7 +1541,7 @@ static int ov965x_probe(struct i2c_client *client, sd = &ov965x->sd; v4l2_i2c_subdev_init(sd, client, &ov965x_subdev_ops); - strlcpy(sd->name, DRIVER_NAME, sizeof(sd->name)); + strscpy(sd->name, DRIVER_NAME, sizeof(sd->name)); sd->internal_ops = &ov965x_sd_internal_ops; sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | diff --git a/drivers/media/i2c/rj54n1cb0c.c b/drivers/media/i2c/rj54n1cb0c.c index 6ad998ad1b16..4cc51e001874 100644 --- a/drivers/media/i2c/rj54n1cb0c.c +++ b/drivers/media/i2c/rj54n1cb0c.c @@ -589,7 +589,6 @@ static int rj54n1_get_selection(struct v4l2_subdev *sd, switch (sel->target) { case V4L2_SEL_TGT_CROP_BOUNDS: - case V4L2_SEL_TGT_CROP_DEFAULT: sel->r.left = RJ54N1_COLUMN_SKIP; sel->r.top = RJ54N1_ROW_SKIP; sel->r.width = RJ54N1_MAX_WIDTH; diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c index ce196b60f917..c461847ddae8 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c @@ -1603,7 +1603,7 @@ static int s5c73m3_get_platform_data(struct s5c73m3 *state) const struct s5c73m3_platform_data *pdata = dev->platform_data; struct device_node *node = dev->of_node; struct device_node *node_ep; - struct v4l2_fwnode_endpoint ep; + struct v4l2_fwnode_endpoint ep = { .bus_type = 0 }; int ret; if (!node) { @@ -1644,7 +1644,7 @@ static int s5c73m3_get_platform_data(struct s5c73m3 *state) if (ret) return ret; - if (ep.bus_type != V4L2_MBUS_CSI2) { + if (ep.bus_type != V4L2_MBUS_CSI2_DPHY) { dev_err(dev, "unsupported bus type\n"); return -EINVAL; } @@ -1683,7 +1683,7 @@ static int s5c73m3_probe(struct i2c_client *client, v4l2_subdev_init(sd, &s5c73m3_subdev_ops); sd->owner = client->dev.driver->owner; v4l2_set_subdevdata(sd, state); - strlcpy(sd->name, "S5C73M3", sizeof(sd->name)); + strscpy(sd->name, "S5C73M3", sizeof(sd->name)); sd->internal_ops = &s5c73m3_internal_ops; sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; @@ -1698,7 +1698,8 @@ static int s5c73m3_probe(struct i2c_client *client, return ret; v4l2_i2c_subdev_init(oif_sd, client, &oif_subdev_ops); - strcpy(oif_sd->name, "S5C73M3-OIF"); + /* Static name; NEVER use in new drivers! */ + strscpy(oif_sd->name, "S5C73M3-OIF", sizeof(oif_sd->name)); oif_sd->internal_ops = &oif_internal_ops; oif_sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; diff --git a/drivers/media/i2c/s5k4ecgx.c b/drivers/media/i2c/s5k4ecgx.c index 6ebcf254989a..79aa2740edc4 100644 --- a/drivers/media/i2c/s5k4ecgx.c +++ b/drivers/media/i2c/s5k4ecgx.c @@ -954,7 +954,8 @@ static int s5k4ecgx_probe(struct i2c_client *client, sd = &priv->sd; /* Registering subdev */ v4l2_i2c_subdev_init(sd, client, &s5k4ecgx_ops); - strlcpy(sd->name, S5K4ECGX_DRIVER_NAME, sizeof(sd->name)); + /* Static name; NEVER use in new drivers! */ + strscpy(sd->name, S5K4ECGX_DRIVER_NAME, sizeof(sd->name)); sd->internal_ops = &s5k4ecgx_subdev_internal_ops; /* Support v4l2 sub-device user space API */ diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c index 5007c9659342..727db7c0670a 100644 --- a/drivers/media/i2c/s5k5baf.c +++ b/drivers/media/i2c/s5k5baf.c @@ -766,7 +766,7 @@ static int s5k5baf_hw_set_video_bus(struct s5k5baf *state) { u16 en_pkts; - if (state->bus_type == V4L2_MBUS_CSI2) + if (state->bus_type == V4L2_MBUS_CSI2_DPHY) en_pkts = EN_PACKETS_CSI2; else en_pkts = 0; @@ -1841,7 +1841,7 @@ static int s5k5baf_parse_device_node(struct s5k5baf *state, struct device *dev) { struct device_node *node = dev->of_node; struct device_node *node_ep; - struct v4l2_fwnode_endpoint ep; + struct v4l2_fwnode_endpoint ep = { .bus_type = 0 }; int ret; if (!node) { @@ -1875,7 +1875,7 @@ static int s5k5baf_parse_device_node(struct s5k5baf *state, struct device *dev) state->bus_type = ep.bus_type; switch (state->bus_type) { - case V4L2_MBUS_CSI2: + case V4L2_MBUS_CSI2_DPHY: state->nlanes = ep.bus.mipi_csi2.num_data_lanes; break; case V4L2_MBUS_PARALLEL: diff --git a/drivers/media/i2c/s5k6aa.c b/drivers/media/i2c/s5k6aa.c index 13c10b5e2b45..ab26f549d716 100644 --- a/drivers/media/i2c/s5k6aa.c +++ b/drivers/media/i2c/s5k6aa.c @@ -688,7 +688,7 @@ static int s5k6aa_configure_video_bus(struct s5k6aa *s5k6aa, * but there is nothing indicating how to switch between both * in the datasheet. For now default BT.601 interface is assumed. */ - if (bus_type == V4L2_MBUS_CSI2) + if (bus_type == V4L2_MBUS_CSI2_DPHY) cfg = nlanes; else if (bus_type != V4L2_MBUS_PARALLEL) return -EINVAL; @@ -1576,7 +1576,8 @@ static int s5k6aa_probe(struct i2c_client *client, sd = &s5k6aa->sd; v4l2_i2c_subdev_init(sd, client, &s5k6aa_subdev_ops); - strlcpy(sd->name, DRIVER_NAME, sizeof(sd->name)); + /* Static name; NEVER use in new drivers! */ + strscpy(sd->name, DRIVER_NAME, sizeof(sd->name)); sd->internal_ops = &s5k6aa_subdev_internal_ops; sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; diff --git a/drivers/media/i2c/saa7115.c b/drivers/media/i2c/saa7115.c index b07114b5efb2..6bc278aa31fc 100644 --- a/drivers/media/i2c/saa7115.c +++ b/drivers/media/i2c/saa7115.c @@ -59,10 +59,16 @@ enum saa711x_model { SAA7118, }; +enum saa711x_pads { + SAA711X_PAD_IF_INPUT, + SAA711X_PAD_VID_OUT, + SAA711X_NUM_PADS +}; + struct saa711x_state { struct v4l2_subdev sd; #ifdef CONFIG_MEDIA_CONTROLLER - struct media_pad pads[DEMOD_NUM_PADS]; + struct media_pad pads[SAA711X_NUM_PADS]; #endif struct v4l2_ctrl_handler hdl; @@ -1765,7 +1771,7 @@ static int saa711x_detect_chip(struct i2c_client *client, * the lower nibble is a gm7113c. */ - strlcpy(name, "gm7113c", CHIP_VER_SIZE); + strscpy(name, "gm7113c", CHIP_VER_SIZE); if (!autodetect && strcmp(name, id->name)) return -EINVAL; @@ -1779,7 +1785,7 @@ static int saa711x_detect_chip(struct i2c_client *client, /* Check if it is a CJC7113 */ if (!memcmp(name, "1111111111111111", CHIP_VER_SIZE)) { - strlcpy(name, "cjc7113", CHIP_VER_SIZE); + strscpy(name, "cjc7113", CHIP_VER_SIZE); if (!autodetect && strcmp(name, id->name)) return -EINVAL; @@ -1825,7 +1831,7 @@ static int saa711x_probe(struct i2c_client *client, if (ident < 0) return ident; - strlcpy(client->name, name, sizeof(client->name)); + strscpy(client->name, name, sizeof(client->name)); state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (state == NULL) @@ -1834,13 +1840,15 @@ static int saa711x_probe(struct i2c_client *client, v4l2_i2c_subdev_init(sd, client, &saa711x_ops); #if defined(CONFIG_MEDIA_CONTROLLER) - state->pads[DEMOD_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK; - state->pads[DEMOD_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE; - state->pads[DEMOD_PAD_VBI_OUT].flags = MEDIA_PAD_FL_SOURCE; + state->pads[SAA711X_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK; + state->pads[SAA711X_PAD_IF_INPUT].sig_type = PAD_SIGNAL_ANALOG; + state->pads[SAA711X_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE; + state->pads[SAA711X_PAD_VID_OUT].sig_type = PAD_SIGNAL_DV; sd->entity.function = MEDIA_ENT_F_ATV_DECODER; - ret = media_entity_pads_init(&sd->entity, DEMOD_NUM_PADS, state->pads); + ret = media_entity_pads_init(&sd->entity, SAA711X_NUM_PADS, + state->pads); if (ret < 0) return ret; #endif diff --git a/drivers/media/i2c/saa7127.c b/drivers/media/i2c/saa7127.c index e58a150cec5c..a67865b810c0 100644 --- a/drivers/media/i2c/saa7127.c +++ b/drivers/media/i2c/saa7127.c @@ -761,10 +761,10 @@ static int saa7127_probe(struct i2c_client *client, saa7127_write(sd, SAA7129_REG_FADE_KEY_COL2, read_result); state->ident = SAA7129; - strlcpy(client->name, "saa7129", I2C_NAME_SIZE); + strscpy(client->name, "saa7129", I2C_NAME_SIZE); } else { state->ident = SAA7127; - strlcpy(client->name, "saa7127", I2C_NAME_SIZE); + strscpy(client->name, "saa7127", I2C_NAME_SIZE); } } diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c index 1236683da8f7..58a45c353e27 100644 --- a/drivers/media/i2c/smiapp/smiapp-core.c +++ b/drivers/media/i2c/smiapp/smiapp-core.c @@ -624,7 +624,7 @@ static int smiapp_init_late_controls(struct smiapp_sensor *sensor) { unsigned long *valid_link_freqs = &sensor->valid_link_freqs[ sensor->csi_format->compressed - sensor->compressed_min_bpp]; - unsigned int max, i; + unsigned int i; for (i = 0; i < ARRAY_SIZE(sensor->test_data); i++) { int max_value = (1 << sensor->csi_format->width) - 1; @@ -635,8 +635,6 @@ static int smiapp_init_late_controls(struct smiapp_sensor *sensor) 0, max_value, 1, max_value); } - for (max = 0; sensor->hwcfg->op_sys_clock[max + 1]; max++); - sensor->link_freq = v4l2_ctrl_new_int_menu( &sensor->src->ctrl_handler, &smiapp_ctrl_ops, V4L2_CID_LINK_FREQ, __fls(*valid_link_freqs), @@ -2617,9 +2615,7 @@ static void smiapp_create_subdev(struct smiapp_sensor *sensor, ssd->npads = num_pads; ssd->source_pad = num_pads - 1; - snprintf(ssd->sd.name, - sizeof(ssd->sd.name), "%s %s %d-%4.4x", sensor->minfo.name, - name, i2c_adapter_id(client->adapter), client->addr); + v4l2_i2c_subdev_set_name(&ssd->sd, client, sensor->minfo.name, name); smiapp_get_native_size(ssd, &ssd->sink_fmt); @@ -2761,7 +2757,7 @@ static int __maybe_unused smiapp_resume(struct device *dev) static struct smiapp_hwconfig *smiapp_get_hwconfig(struct device *dev) { struct smiapp_hwconfig *hwcfg; - struct v4l2_fwnode_endpoint *bus_cfg; + struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 }; struct fwnode_handle *ep; struct fwnode_handle *fwnode = dev_fwnode(dev); u32 rotation; @@ -2775,27 +2771,33 @@ static struct smiapp_hwconfig *smiapp_get_hwconfig(struct device *dev) if (!ep) return NULL; - bus_cfg = v4l2_fwnode_endpoint_alloc_parse(ep); - if (IS_ERR(bus_cfg)) + bus_cfg.bus_type = V4L2_MBUS_CSI2_DPHY; + rval = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg); + if (rval == -ENXIO) { + bus_cfg = (struct v4l2_fwnode_endpoint) + { .bus_type = V4L2_MBUS_CCP2 }; + rval = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg); + } + if (rval) goto out_err; hwcfg = devm_kzalloc(dev, sizeof(*hwcfg), GFP_KERNEL); if (!hwcfg) goto out_err; - switch (bus_cfg->bus_type) { - case V4L2_MBUS_CSI2: + switch (bus_cfg.bus_type) { + case V4L2_MBUS_CSI2_DPHY: hwcfg->csi_signalling_mode = SMIAPP_CSI_SIGNALLING_MODE_CSI2; - hwcfg->lanes = bus_cfg->bus.mipi_csi2.num_data_lanes; + hwcfg->lanes = bus_cfg.bus.mipi_csi2.num_data_lanes; break; case V4L2_MBUS_CCP2: - hwcfg->csi_signalling_mode = (bus_cfg->bus.mipi_csi1.strobe) ? + hwcfg->csi_signalling_mode = (bus_cfg.bus.mipi_csi1.strobe) ? SMIAPP_CSI_SIGNALLING_MODE_CCP2_DATA_STROBE : SMIAPP_CSI_SIGNALLING_MODE_CCP2_DATA_CLOCK; hwcfg->lanes = 1; break; default: - dev_err(dev, "unsupported bus %u\n", bus_cfg->bus_type); + dev_err(dev, "unsupported bus %u\n", bus_cfg.bus_type); goto out_err; } @@ -2827,28 +2829,28 @@ static struct smiapp_hwconfig *smiapp_get_hwconfig(struct device *dev) dev_dbg(dev, "nvm %d, clk %d, mode %d\n", hwcfg->nvm_size, hwcfg->ext_clk, hwcfg->csi_signalling_mode); - if (!bus_cfg->nr_of_link_frequencies) { + if (!bus_cfg.nr_of_link_frequencies) { dev_warn(dev, "no link frequencies defined\n"); goto out_err; } hwcfg->op_sys_clock = devm_kcalloc( - dev, bus_cfg->nr_of_link_frequencies + 1 /* guardian */, + dev, bus_cfg.nr_of_link_frequencies + 1 /* guardian */, sizeof(*hwcfg->op_sys_clock), GFP_KERNEL); if (!hwcfg->op_sys_clock) goto out_err; - for (i = 0; i < bus_cfg->nr_of_link_frequencies; i++) { - hwcfg->op_sys_clock[i] = bus_cfg->link_frequencies[i]; + for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) { + hwcfg->op_sys_clock[i] = bus_cfg.link_frequencies[i]; dev_dbg(dev, "freq %d: %lld\n", i, hwcfg->op_sys_clock[i]); } - v4l2_fwnode_endpoint_free(bus_cfg); + v4l2_fwnode_endpoint_free(&bus_cfg); fwnode_handle_put(ep); return hwcfg; out_err: - v4l2_fwnode_endpoint_free(bus_cfg); + v4l2_fwnode_endpoint_free(&bus_cfg); fwnode_handle_put(ep); return NULL; } @@ -3064,9 +3066,9 @@ static int smiapp_probe(struct i2c_client *client, if (sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0) sensor->pll.flags |= SMIAPP_PLL_FLAG_NO_OP_CLOCKS; - smiapp_create_subdev(sensor, sensor->scaler, "scaler", 2); - smiapp_create_subdev(sensor, sensor->binner, "binner", 2); - smiapp_create_subdev(sensor, sensor->pixel_array, "pixel_array", 1); + smiapp_create_subdev(sensor, sensor->scaler, " scaler", 2); + smiapp_create_subdev(sensor, sensor->binner, " binner", 2); + smiapp_create_subdev(sensor, sensor->pixel_array, " pixel_array", 1); dev_dbg(&client->dev, "profile %d\n", sensor->minfo.smiapp_profile); diff --git a/drivers/media/i2c/soc_camera/Makefile b/drivers/media/i2c/soc_camera/Makefile index 8c7770f62997..09ae483b96ef 100644 --- a/drivers/media/i2c/soc_camera/Makefile +++ b/drivers/media/i2c/soc_camera/Makefile @@ -1,10 +1,10 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o -obj-$(CONFIG_SOC_CAMERA_MT9T112) += mt9t112.o -obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o -obj-$(CONFIG_SOC_CAMERA_OV5642) += ov5642.o -obj-$(CONFIG_SOC_CAMERA_OV772X) += ov772x.o -obj-$(CONFIG_SOC_CAMERA_OV9640) += ov9640.o -obj-$(CONFIG_SOC_CAMERA_OV9740) += ov9740.o -obj-$(CONFIG_SOC_CAMERA_RJ54N1) += rj54n1cb0c.o -obj-$(CONFIG_SOC_CAMERA_TW9910) += tw9910.o +obj-$(CONFIG_SOC_CAMERA_MT9M001) += soc_mt9m001.o +obj-$(CONFIG_SOC_CAMERA_MT9T112) += soc_mt9t112.o +obj-$(CONFIG_SOC_CAMERA_MT9V022) += soc_mt9v022.o +obj-$(CONFIG_SOC_CAMERA_OV5642) += soc_ov5642.o +obj-$(CONFIG_SOC_CAMERA_OV772X) += soc_ov772x.o +obj-$(CONFIG_SOC_CAMERA_OV9640) += soc_ov9640.o +obj-$(CONFIG_SOC_CAMERA_OV9740) += soc_ov9740.o +obj-$(CONFIG_SOC_CAMERA_RJ54N1) += soc_rj54n1cb0c.o +obj-$(CONFIG_SOC_CAMERA_TW9910) += soc_tw9910.o diff --git a/drivers/media/i2c/soc_camera/mt9m001.c b/drivers/media/i2c/soc_camera/soc_mt9m001.c index 1bfb0d53059e..a1a85ff838c5 100644 --- a/drivers/media/i2c/soc_camera/mt9m001.c +++ b/drivers/media/i2c/soc_camera/soc_mt9m001.c @@ -243,7 +243,6 @@ static int mt9m001_get_selection(struct v4l2_subdev *sd, switch (sel->target) { case V4L2_SEL_TGT_CROP_BOUNDS: - case V4L2_SEL_TGT_CROP_DEFAULT: sel->r.left = MT9M001_COLUMN_SKIP; sel->r.top = MT9M001_ROW_SKIP; sel->r.width = MT9M001_MAX_WIDTH; diff --git a/drivers/media/i2c/soc_camera/mt9t112.c b/drivers/media/i2c/soc_camera/soc_mt9t112.c index b53c36dfa469..ea1ff270bc2d 100644 --- a/drivers/media/i2c/soc_camera/mt9t112.c +++ b/drivers/media/i2c/soc_camera/soc_mt9t112.c @@ -884,12 +884,6 @@ static int mt9t112_get_selection(struct v4l2_subdev *sd, sel->r.width = MAX_WIDTH; sel->r.height = MAX_HEIGHT; return 0; - case V4L2_SEL_TGT_CROP_DEFAULT: - sel->r.left = 0; - sel->r.top = 0; - sel->r.width = VGA_WIDTH; - sel->r.height = VGA_HEIGHT; - return 0; case V4L2_SEL_TGT_CROP: sel->r = priv->frame; return 0; diff --git a/drivers/media/i2c/soc_camera/mt9v022.c b/drivers/media/i2c/soc_camera/soc_mt9v022.c index 762f06919329..6d922b17ea94 100644 --- a/drivers/media/i2c/soc_camera/mt9v022.c +++ b/drivers/media/i2c/soc_camera/soc_mt9v022.c @@ -368,7 +368,6 @@ static int mt9v022_get_selection(struct v4l2_subdev *sd, switch (sel->target) { case V4L2_SEL_TGT_CROP_BOUNDS: - case V4L2_SEL_TGT_CROP_DEFAULT: sel->r.left = MT9V022_COLUMN_SKIP; sel->r.top = MT9V022_ROW_SKIP; sel->r.width = MT9V022_MAX_WIDTH; diff --git a/drivers/media/i2c/soc_camera/ov5642.c b/drivers/media/i2c/soc_camera/soc_ov5642.c index 39f420db9c70..0931898c79dd 100644 --- a/drivers/media/i2c/soc_camera/ov5642.c +++ b/drivers/media/i2c/soc_camera/soc_ov5642.c @@ -896,7 +896,6 @@ static int ov5642_get_selection(struct v4l2_subdev *sd, switch (sel->target) { case V4L2_SEL_TGT_CROP_BOUNDS: - case V4L2_SEL_TGT_CROP_DEFAULT: sel->r.left = 0; sel->r.top = 0; sel->r.width = OV5642_MAX_WIDTH; @@ -913,7 +912,7 @@ static int ov5642_get_selection(struct v4l2_subdev *sd, static int ov5642_g_mbus_config(struct v4l2_subdev *sd, struct v4l2_mbus_config *cfg) { - cfg->type = V4L2_MBUS_CSI2; + cfg->type = V4L2_MBUS_CSI2_DPHY; cfg->flags = V4L2_MBUS_CSI2_2_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; diff --git a/drivers/media/i2c/soc_camera/ov772x.c b/drivers/media/i2c/soc_camera/soc_ov772x.c index 14377af7c888..fafd372527b2 100644 --- a/drivers/media/i2c/soc_camera/ov772x.c +++ b/drivers/media/i2c/soc_camera/soc_ov772x.c @@ -862,7 +862,6 @@ static int ov772x_get_selection(struct v4l2_subdev *sd, sel->r.top = 0; switch (sel->target) { case V4L2_SEL_TGT_CROP_BOUNDS: - case V4L2_SEL_TGT_CROP_DEFAULT: sel->r.width = OV772X_MAX_WIDTH; sel->r.height = OV772X_MAX_HEIGHT; return 0; diff --git a/drivers/media/i2c/soc_camera/ov9640.c b/drivers/media/i2c/soc_camera/soc_ov9640.c index c63948989688..eb91b8240083 100644 --- a/drivers/media/i2c/soc_camera/ov9640.c +++ b/drivers/media/i2c/soc_camera/soc_ov9640.c @@ -554,7 +554,6 @@ static int ov9640_get_selection(struct v4l2_subdev *sd, sel->r.top = 0; switch (sel->target) { case V4L2_SEL_TGT_CROP_BOUNDS: - case V4L2_SEL_TGT_CROP_DEFAULT: case V4L2_SEL_TGT_CROP: sel->r.width = W_SXGA; sel->r.height = H_SXGA; diff --git a/drivers/media/i2c/soc_camera/ov9740.c b/drivers/media/i2c/soc_camera/soc_ov9740.c index 755de2289c39..a07d3145d1b4 100644 --- a/drivers/media/i2c/soc_camera/ov9740.c +++ b/drivers/media/i2c/soc_camera/soc_ov9740.c @@ -730,7 +730,6 @@ static int ov9740_get_selection(struct v4l2_subdev *sd, switch (sel->target) { case V4L2_SEL_TGT_CROP_BOUNDS: - case V4L2_SEL_TGT_CROP_DEFAULT: case V4L2_SEL_TGT_CROP: sel->r.left = 0; sel->r.top = 0; diff --git a/drivers/media/i2c/soc_camera/rj54n1cb0c.c b/drivers/media/i2c/soc_camera/soc_rj54n1cb0c.c index 02398d0bc649..f0cb49a6167b 100644 --- a/drivers/media/i2c/soc_camera/rj54n1cb0c.c +++ b/drivers/media/i2c/soc_camera/soc_rj54n1cb0c.c @@ -591,7 +591,6 @@ static int rj54n1_get_selection(struct v4l2_subdev *sd, switch (sel->target) { case V4L2_SEL_TGT_CROP_BOUNDS: - case V4L2_SEL_TGT_CROP_DEFAULT: sel->r.left = RJ54N1_COLUMN_SKIP; sel->r.top = RJ54N1_ROW_SKIP; sel->r.width = RJ54N1_MAX_WIDTH; diff --git a/drivers/media/i2c/soc_camera/tw9910.c b/drivers/media/i2c/soc_camera/soc_tw9910.c index bdb5e0a431e9..bdb5e0a431e9 100644 --- a/drivers/media/i2c/soc_camera/tw9910.c +++ b/drivers/media/i2c/soc_camera/soc_tw9910.c diff --git a/drivers/media/i2c/sr030pc30.c b/drivers/media/i2c/sr030pc30.c index 2a4882cddc51..11f6c7a5e0e7 100644 --- a/drivers/media/i2c/sr030pc30.c +++ b/drivers/media/i2c/sr030pc30.c @@ -569,7 +569,7 @@ static int sr030pc30_base_config(struct v4l2_subdev *sd) if (!ret) ret = sr030pc30_pwr_ctrl(sd, false, false); - if (!ret && !info->pdata) + if (ret) return ret; expmin = EXPOS_MIN_MS * info->pdata->clk_rate / (8 * 1000); @@ -703,7 +703,6 @@ static int sr030pc30_probe(struct i2c_client *client, return -ENOMEM; sd = &info->sd; - strcpy(sd->name, MODULE_NAME); info->pdata = client->dev.platform_data; v4l2_i2c_subdev_init(sd, client, &sr030pc30_ops); diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c index 44c41933415a..ca5d92942820 100644 --- a/drivers/media/i2c/tc358743.c +++ b/drivers/media/i2c/tc358743.c @@ -1243,9 +1243,9 @@ static int tc358743_log_status(struct v4l2_subdev *sd) u8 vi_status3 = i2c_rd8(sd, VI_STATUS3); const int deep_color_mode[4] = { 8, 10, 12, 16 }; static const char * const input_color_space[] = { - "RGB", "YCbCr 601", "Adobe RGB", "YCbCr 709", "NA (4)", + "RGB", "YCbCr 601", "opRGB", "YCbCr 709", "NA (4)", "xvYCC 601", "NA(6)", "xvYCC 709", "NA(8)", "sYCC601", - "NA(10)", "NA(11)", "NA(12)", "Adobe YCC 601"}; + "NA(10)", "NA(11)", "NA(12)", "opYCC 601"}; v4l2_info(sd, "-----Chip status-----\n"); v4l2_info(sd, "Chip ID: 0x%02x\n", @@ -1607,7 +1607,7 @@ static int tc358743_g_mbus_config(struct v4l2_subdev *sd, { struct tc358743_state *state = to_state(sd); - cfg->type = V4L2_MBUS_CSI2; + cfg->type = V4L2_MBUS_CSI2_DPHY; /* Support for non-continuous CSI-2 clock is missing in the driver */ cfg->flags = V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; @@ -1789,7 +1789,7 @@ static int tc358743_s_edid(struct v4l2_subdev *sd, return -E2BIG; } pa = cec_get_edid_phys_addr(edid->edid, edid->blocks * 128, NULL); - err = cec_phys_addr_validate(pa, &pa, NULL); + err = v4l2_phys_addr_validate(pa, &pa, NULL); if (err) return err; @@ -1895,11 +1895,11 @@ static void tc358743_gpio_reset(struct tc358743_state *state) static int tc358743_probe_of(struct tc358743_state *state) { struct device *dev = &state->i2c_client->dev; - struct v4l2_fwnode_endpoint *endpoint; + struct v4l2_fwnode_endpoint endpoint = { .bus_type = 0 }; struct device_node *ep; struct clk *refclk; u32 bps_pr_lane; - int ret = -EINVAL; + int ret; refclk = devm_clk_get(dev, "refclk"); if (IS_ERR(refclk)) { @@ -1915,26 +1915,28 @@ static int tc358743_probe_of(struct tc358743_state *state) return -EINVAL; } - endpoint = v4l2_fwnode_endpoint_alloc_parse(of_fwnode_handle(ep)); - if (IS_ERR(endpoint)) { + ret = v4l2_fwnode_endpoint_alloc_parse(of_fwnode_handle(ep), &endpoint); + if (ret) { dev_err(dev, "failed to parse endpoint\n"); - ret = PTR_ERR(endpoint); + ret = ret; goto put_node; } - if (endpoint->bus_type != V4L2_MBUS_CSI2 || - endpoint->bus.mipi_csi2.num_data_lanes == 0 || - endpoint->nr_of_link_frequencies == 0) { + if (endpoint.bus_type != V4L2_MBUS_CSI2_DPHY || + endpoint.bus.mipi_csi2.num_data_lanes == 0 || + endpoint.nr_of_link_frequencies == 0) { dev_err(dev, "missing CSI-2 properties in endpoint\n"); + ret = -EINVAL; goto free_endpoint; } - if (endpoint->bus.mipi_csi2.num_data_lanes > 4) { + if (endpoint.bus.mipi_csi2.num_data_lanes > 4) { dev_err(dev, "invalid number of lanes\n"); + ret = -EINVAL; goto free_endpoint; } - state->bus = endpoint->bus.mipi_csi2; + state->bus = endpoint.bus.mipi_csi2; ret = clk_prepare_enable(refclk); if (ret) { @@ -1967,7 +1969,7 @@ static int tc358743_probe_of(struct tc358743_state *state) * The CSI bps per lane must be between 62.5 Mbps and 1 Gbps. * The default is 594 Mbps for 4-lane 1080p60 or 2-lane 720p60. */ - bps_pr_lane = 2 * endpoint->link_frequencies[0]; + bps_pr_lane = 2 * endpoint.link_frequencies[0]; if (bps_pr_lane < 62500000U || bps_pr_lane > 1000000000U) { dev_err(dev, "unsupported bps per lane: %u bps\n", bps_pr_lane); goto disable_clk; @@ -2013,7 +2015,7 @@ static int tc358743_probe_of(struct tc358743_state *state) disable_clk: clk_disable_unprepare(refclk); free_endpoint: - v4l2_fwnode_endpoint_free(endpoint); + v4l2_fwnode_endpoint_free(&endpoint); put_node: of_node_put(ep); return ret; diff --git a/drivers/media/i2c/tda1997x.c b/drivers/media/i2c/tda1997x.c index d114ac5243ec..c4c2a6134e1e 100644 --- a/drivers/media/i2c/tda1997x.c +++ b/drivers/media/i2c/tda1997x.c @@ -2265,7 +2265,7 @@ MODULE_DEVICE_TABLE(of, tda1997x_of_id); static int tda1997x_parse_dt(struct tda1997x_state *state) { struct tda1997x_platform_data *pdata = &state->pdata; - struct v4l2_fwnode_endpoint bus_cfg; + struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 }; struct device_node *ep; struct device_node *np; unsigned int flags; diff --git a/drivers/media/i2c/tvaudio.c b/drivers/media/i2c/tvaudio.c index 5919214a56bf..af2da977a685 100644 --- a/drivers/media/i2c/tvaudio.c +++ b/drivers/media/i2c/tvaudio.c @@ -1981,7 +1981,7 @@ static int tvaudio_probe(struct i2c_client *client, const struct i2c_device_id * /* fill required data structures */ if (!id) - strlcpy(client->name, desc->name, I2C_NAME_SIZE); + strscpy(client->name, desc->name, I2C_NAME_SIZE); chip->desc = desc; chip->shadow.count = desc->registers+1; chip->prevmode = -1; diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c index 675b9ae212ab..1cc83cb934e2 100644 --- a/drivers/media/i2c/tvp514x.c +++ b/drivers/media/i2c/tvp514x.c @@ -989,7 +989,7 @@ static struct tvp514x_platform_data * tvp514x_get_pdata(struct i2c_client *client) { struct tvp514x_platform_data *pdata = NULL; - struct v4l2_fwnode_endpoint bus_cfg; + struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 }; struct device_node *endpoint; unsigned int flags; diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 76e6bed5a1da..0e91b9949c3a 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -10,8 +10,10 @@ #include <linux/videodev2.h> #include <linux/delay.h> #include <linux/gpio/consumer.h> +#include <linux/interrupt.h> #include <linux/module.h> #include <linux/of_graph.h> +#include <linux/regmap.h> #include <media/v4l2-async.h> #include <media/v4l2-device.h> #include <media/v4l2-ctrls.h> @@ -26,6 +28,9 @@ #define TVP5150_MAX_CROP_LEFT 511 #define TVP5150_MAX_CROP_TOP 127 #define TVP5150_CROP_SHIFT 2 +#define TVP5150_MBUS_FMT MEDIA_BUS_FMT_UYVY8_2X8 +#define TVP5150_FIELD V4L2_FIELD_ALTERNATE +#define TVP5150_COLORSPACE V4L2_COLORSPACE_SMPTE170M MODULE_DESCRIPTION("Texas Instruments TVP5150A/TVP5150AM1/TVP5151 video decoder driver"); MODULE_AUTHOR("Mauro Carvalho Chehab"); @@ -38,20 +43,31 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)"); #define dprintk0(__dev, __arg...) dev_dbg_lvl(__dev, 0, 0, __arg) +enum tvp5150_pads { + TVP5150_PAD_IF_INPUT, + TVP5150_PAD_VID_OUT, + TVP5150_NUM_PADS +}; + struct tvp5150 { struct v4l2_subdev sd; #ifdef CONFIG_MEDIA_CONTROLLER - struct media_pad pads[DEMOD_NUM_PADS]; + struct media_pad pads[TVP5150_NUM_PADS]; struct media_entity input_ent[TVP5150_INPUT_NUM]; struct media_pad input_pad[TVP5150_INPUT_NUM]; #endif struct v4l2_ctrl_handler hdl; struct v4l2_rect rect; + struct regmap *regmap; + int irq; v4l2_std_id norm; /* Current set standard */ + v4l2_std_id detected_norm; u32 input; u32 output; + u32 oe; int enable; + bool lock; u16 dev_id; u16 rom_ver; @@ -71,32 +87,14 @@ static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) static int tvp5150_read(struct v4l2_subdev *sd, unsigned char addr) { - struct i2c_client *c = v4l2_get_subdevdata(sd); - int rc; - - rc = i2c_smbus_read_byte_data(c, addr); - if (rc < 0) { - dev_err(sd->dev, "i2c i/o error: rc == %d\n", rc); - return rc; - } - - dev_dbg_lvl(sd->dev, 2, debug, "tvp5150: read 0x%02x = %02x\n", addr, rc); - - return rc; -} - -static int tvp5150_write(struct v4l2_subdev *sd, unsigned char addr, - unsigned char value) -{ - struct i2c_client *c = v4l2_get_subdevdata(sd); - int rc; + struct tvp5150 *decoder = to_tvp5150(sd); + int ret, val; - dev_dbg_lvl(sd->dev, 2, debug, "tvp5150: writing %02x %02x\n", addr, value); - rc = i2c_smbus_write_byte_data(c, addr, value); - if (rc < 0) - dev_err(sd->dev, "i2c i/o error: rc == %d\n", rc); + ret = regmap_read(decoder->regmap, addr, &val); + if (ret < 0) + return ret; - return rc; + return val; } static void dump_reg_range(struct v4l2_subdev *sd, char *s, u8 init, @@ -262,8 +260,8 @@ static void tvp5150_selmux(struct v4l2_subdev *sd) { int opmode = 0; struct tvp5150 *decoder = to_tvp5150(sd); + unsigned int mask, val; int input = 0; - int val; /* Only tvp5150am1 and tvp5151 have signal generator support */ if ((decoder->dev_id == 0x5150 && decoder->rom_ver == 0x0400) || @@ -288,8 +286,8 @@ static void tvp5150_selmux(struct v4l2_subdev *sd) decoder->input, decoder->output, input, opmode); - tvp5150_write(sd, TVP5150_OP_MODE_CTL, opmode); - tvp5150_write(sd, TVP5150_VD_IN_SRC_SEL_1, input); + regmap_write(decoder->regmap, TVP5150_OP_MODE_CTL, opmode); + regmap_write(decoder->regmap, TVP5150_VD_IN_SRC_SEL_1, input); /* * Setup the FID/GLCO/VLK/HVLK and INTREQ/GPCL/VBLK output signals. For @@ -298,17 +296,12 @@ static void tvp5150_selmux(struct v4l2_subdev *sd) * field indicator (FID) signal on FID/GLCO/VLK/HVLK and set * INTREQ/GPCL/VBLK to logic 1. */ - val = tvp5150_read(sd, TVP5150_MISC_CTL); - if (val < 0) { - dev_err(sd->dev, "%s: failed with error = %d\n", __func__, val); - return; - } - + mask = TVP5150_MISC_CTL_GPCL | TVP5150_MISC_CTL_HVLK; if (decoder->input == TVP5150_SVIDEO) - val = (val & ~TVP5150_MISC_CTL_GPCL) | TVP5150_MISC_CTL_HVLK; + val = TVP5150_MISC_CTL_HVLK; else - val = (val & ~TVP5150_MISC_CTL_HVLK) | TVP5150_MISC_CTL_GPCL; - tvp5150_write(sd, TVP5150_MISC_CTL, val); + val = TVP5150_MISC_CTL_GPCL; + regmap_update_bits(decoder->regmap, TVP5150_MISC_CTL, mask, val); }; struct i2c_reg_value { @@ -454,9 +447,7 @@ static const struct i2c_reg_value tvp5150_init_default[] = { /* Default values as sugested at TVP5150AM1 datasheet */ static const struct i2c_reg_value tvp5150_init_enable[] = { - { - TVP5150_CONF_SHARED_PIN, 2 - }, { /* Automatic offset and AGC enabled */ + { /* Automatic offset and AGC enabled */ TVP5150_ANAL_CHL_CTL, 0x15 }, { /* Activate YCrCb output 0x9 or 0xd ? */ TVP5150_MISC_CTL, TVP5150_MISC_CTL_GPCL | @@ -583,8 +574,10 @@ static struct i2c_vbi_ram_value vbi_ram_default[] = { static int tvp5150_write_inittab(struct v4l2_subdev *sd, const struct i2c_reg_value *regs) { + struct tvp5150 *decoder = to_tvp5150(sd); + while (regs->reg != 0xff) { - tvp5150_write(sd, regs->reg, regs->value); + regmap_write(decoder->regmap, regs->reg, regs->value); regs++; } return 0; @@ -592,15 +585,17 @@ static int tvp5150_write_inittab(struct v4l2_subdev *sd, static int tvp5150_vdp_init(struct v4l2_subdev *sd) { + struct tvp5150 *decoder = to_tvp5150(sd); + struct regmap *map = decoder->regmap; unsigned int i; int j; /* Disable Full Field */ - tvp5150_write(sd, TVP5150_FULL_FIELD_ENA, 0); + regmap_write(map, TVP5150_FULL_FIELD_ENA, 0); /* Before programming, Line mode should be at 0xff */ for (i = TVP5150_LINE_MODE_INI; i <= TVP5150_LINE_MODE_END; i++) - tvp5150_write(sd, i, 0xff); + regmap_write(map, i, 0xff); /* Load Ram Table */ for (j = 0; j < ARRAY_SIZE(vbi_ram_default); j++) { @@ -609,11 +604,12 @@ static int tvp5150_vdp_init(struct v4l2_subdev *sd) if (!regs->type.vbi_type) continue; - tvp5150_write(sd, TVP5150_CONF_RAM_ADDR_HIGH, regs->reg >> 8); - tvp5150_write(sd, TVP5150_CONF_RAM_ADDR_LOW, regs->reg); + regmap_write(map, TVP5150_CONF_RAM_ADDR_HIGH, regs->reg >> 8); + regmap_write(map, TVP5150_CONF_RAM_ADDR_LOW, regs->reg); for (i = 0; i < 16; i++) - tvp5150_write(sd, TVP5150_VDP_CONF_RAM_DATA, regs->values[i]); + regmap_write(map, TVP5150_VDP_CONF_RAM_DATA, + regs->values[i]); } return 0; } @@ -693,10 +689,10 @@ static int tvp5150_set_vbi(struct v4l2_subdev *sd, reg = ((line - 6) << 1) + TVP5150_LINE_MODE_INI; if (fields & 1) - tvp5150_write(sd, reg, type); + regmap_write(decoder->regmap, reg, type); if (fields & 2) - tvp5150_write(sd, reg + 1, type); + regmap_write(decoder->regmap, reg + 1, type); return type; } @@ -742,8 +738,6 @@ static int tvp5150_set_std(struct v4l2_subdev *sd, v4l2_std_id std) struct tvp5150 *decoder = to_tvp5150(sd); int fmt = 0; - decoder->norm = std; - /* First tests should be against specific std */ if (std == V4L2_STD_NTSC_443) { @@ -763,7 +757,16 @@ static int tvp5150_set_std(struct v4l2_subdev *sd, v4l2_std_id std) } dev_dbg_lvl(sd->dev, 1, debug, "Set video std register to %d.\n", fmt); - tvp5150_write(sd, TVP5150_VIDEO_STD, fmt); + regmap_write(decoder->regmap, TVP5150_VIDEO_STD, fmt); + return 0; +} + +static int tvp5150_g_std(struct v4l2_subdev *sd, v4l2_std_id *std) +{ + struct tvp5150 *decoder = to_tvp5150(sd); + + *std = decoder->norm; + return 0; } @@ -780,33 +783,166 @@ static int tvp5150_s_std(struct v4l2_subdev *sd, v4l2_std_id std) else decoder->rect.height = TVP5150_V_MAX_OTHERS; + decoder->norm = std; return tvp5150_set_std(sd, std); } +static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd) +{ + int val = tvp5150_read(sd, TVP5150_STATUS_REG_5); + + switch (val & 0x0F) { + case 0x01: + return V4L2_STD_NTSC; + case 0x03: + return V4L2_STD_PAL; + case 0x05: + return V4L2_STD_PAL_M; + case 0x07: + return V4L2_STD_PAL_N | V4L2_STD_PAL_Nc; + case 0x09: + return V4L2_STD_NTSC_443; + case 0xb: + return V4L2_STD_SECAM; + default: + return V4L2_STD_UNKNOWN; + } +} + +static int query_lock(struct v4l2_subdev *sd) +{ + struct tvp5150 *decoder = to_tvp5150(sd); + int status; + + if (decoder->irq) + return decoder->lock; + + regmap_read(decoder->regmap, TVP5150_STATUS_REG_1, &status); + + /* For standard detection, we need the 3 locks */ + return (status & 0x0e) == 0x0e; +} + +static int tvp5150_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id) +{ + *std_id = query_lock(sd) ? tvp5150_read_std(sd) : V4L2_STD_UNKNOWN; + + return 0; +} + +static const struct v4l2_event tvp5150_ev_fmt = { + .type = V4L2_EVENT_SOURCE_CHANGE, + .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION, +}; + +static irqreturn_t tvp5150_isr(int irq, void *dev_id) +{ + struct tvp5150 *decoder = dev_id; + struct regmap *map = decoder->regmap; + unsigned int mask, active = 0, status = 0; + + mask = TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_SYNC_OE | + TVP5150_MISC_CTL_CLOCK_OE; + + regmap_read(map, TVP5150_INT_STATUS_REG_A, &status); + if (status) { + regmap_write(map, TVP5150_INT_STATUS_REG_A, status); + + if (status & TVP5150_INT_A_LOCK) { + decoder->lock = !!(status & TVP5150_INT_A_LOCK_STATUS); + dev_dbg_lvl(decoder->sd.dev, 1, debug, + "sync lo%s signal\n", + decoder->lock ? "ck" : "ss"); + v4l2_subdev_notify_event(&decoder->sd, &tvp5150_ev_fmt); + regmap_update_bits(map, TVP5150_MISC_CTL, mask, + decoder->lock ? decoder->oe : 0); + } + + return IRQ_HANDLED; + } + + regmap_read(map, TVP5150_INT_ACTIVE_REG_B, &active); + if (active) { + status = 0; + regmap_read(map, TVP5150_INT_STATUS_REG_B, &status); + if (status) + regmap_write(map, TVP5150_INT_RESET_REG_B, status); + } + + return IRQ_HANDLED; +} + static int tvp5150_reset(struct v4l2_subdev *sd, u32 val) { struct tvp5150 *decoder = to_tvp5150(sd); + struct regmap *map = decoder->regmap; /* Initializes TVP5150 to its default values */ tvp5150_write_inittab(sd, tvp5150_init_default); + if (decoder->irq) { + /* Configure pins: FID, VSYNC, INTREQ, SCLK */ + regmap_write(map, TVP5150_CONF_SHARED_PIN, 0x0); + /* Set interrupt polarity to active high */ + regmap_write(map, TVP5150_INT_CONF, TVP5150_VDPOE | 0x1); + regmap_write(map, TVP5150_INTT_CONFIG_REG_B, 0x1); + } else { + /* Configure pins: FID, VSYNC, GPCL/VBLK, SCLK */ + regmap_write(map, TVP5150_CONF_SHARED_PIN, 0x2); + /* Keep interrupt polarity active low */ + regmap_write(map, TVP5150_INT_CONF, TVP5150_VDPOE); + regmap_write(map, TVP5150_INTT_CONFIG_REG_B, 0x0); + } + /* Initializes VDP registers */ tvp5150_vdp_init(sd); /* Selects decoder input */ tvp5150_selmux(sd); + /* Initialize image preferences */ + v4l2_ctrl_handler_setup(&decoder->hdl); + + return 0; +} + +static int tvp5150_enable(struct v4l2_subdev *sd) +{ + struct tvp5150 *decoder = to_tvp5150(sd); + v4l2_std_id std; + /* Initializes TVP5150 to stream enabled values */ tvp5150_write_inittab(sd, tvp5150_init_enable); - /* Initialize image preferences */ - v4l2_ctrl_handler_setup(&decoder->hdl); + if (decoder->norm == V4L2_STD_ALL) + std = tvp5150_read_std(sd); + else + std = decoder->norm; - tvp5150_set_std(sd, decoder->norm); + /* Disable autoswitch mode */ + tvp5150_set_std(sd, std); - if (decoder->mbus_type == V4L2_MBUS_PARALLEL) - tvp5150_write(sd, TVP5150_DATA_RATE_SEL, 0x40); + /* + * Enable the YCbCr and clock outputs. In discrete sync mode + * (non-BT.656) additionally enable the the sync outputs. + */ + switch (decoder->mbus_type) { + case V4L2_MBUS_PARALLEL: + /* 8-bit 4:2:2 YUV with discrete sync output */ + regmap_update_bits(decoder->regmap, TVP5150_DATA_RATE_SEL, + 0x7, 0x0); + decoder->oe = TVP5150_MISC_CTL_YCBCR_OE | + TVP5150_MISC_CTL_CLOCK_OE | + TVP5150_MISC_CTL_SYNC_OE; + break; + case V4L2_MBUS_BT656: + decoder->oe = TVP5150_MISC_CTL_YCBCR_OE | + TVP5150_MISC_CTL_CLOCK_OE; + break; + default: + return -EINVAL; + } return 0; }; @@ -818,17 +954,18 @@ static int tvp5150_s_ctrl(struct v4l2_ctrl *ctrl) switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: - tvp5150_write(sd, TVP5150_BRIGHT_CTL, ctrl->val); + regmap_write(decoder->regmap, TVP5150_BRIGHT_CTL, ctrl->val); return 0; case V4L2_CID_CONTRAST: - tvp5150_write(sd, TVP5150_CONTRAST_CTL, ctrl->val); + regmap_write(decoder->regmap, TVP5150_CONTRAST_CTL, ctrl->val); return 0; case V4L2_CID_SATURATION: - tvp5150_write(sd, TVP5150_SATURATION_CTL, ctrl->val); + regmap_write(decoder->regmap, TVP5150_SATURATION_CTL, + ctrl->val); return 0; case V4L2_CID_HUE: - tvp5150_write(sd, TVP5150_HUE_CTL, ctrl->val); - break; + regmap_write(decoder->regmap, TVP5150_HUE_CTL, ctrl->val); + return 0; case V4L2_CID_TEST_PATTERN: decoder->enable = ctrl->val ? false : true; tvp5150_selmux(sd); @@ -837,36 +974,26 @@ static int tvp5150_s_ctrl(struct v4l2_ctrl *ctrl) return -EINVAL; } -static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd) +static void tvp5150_set_default(v4l2_std_id std, struct v4l2_rect *crop) { - int val = tvp5150_read(sd, TVP5150_STATUS_REG_5); - - switch (val & 0x0F) { - case 0x01: - return V4L2_STD_NTSC; - case 0x03: - return V4L2_STD_PAL; - case 0x05: - return V4L2_STD_PAL_M; - case 0x07: - return V4L2_STD_PAL_N | V4L2_STD_PAL_Nc; - case 0x09: - return V4L2_STD_NTSC_443; - case 0xb: - return V4L2_STD_SECAM; - default: - return V4L2_STD_UNKNOWN; - } + /* Default is no cropping */ + crop->top = 0; + crop->left = 0; + crop->width = TVP5150_H_MAX; + if (std & V4L2_STD_525_60) + crop->height = TVP5150_V_MAX_525_60; + else + crop->height = TVP5150_V_MAX_OTHERS; } static int tvp5150_fill_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *format) + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *format) { struct v4l2_mbus_framefmt *f; struct tvp5150 *decoder = to_tvp5150(sd); - if (!format || (format->pad != DEMOD_PAD_VID_OUT)) + if (!format || (format->pad != TVP5150_PAD_VID_OUT)) return -EINVAL; f = &format->format; @@ -874,12 +1001,12 @@ static int tvp5150_fill_fmt(struct v4l2_subdev *sd, f->width = decoder->rect.width; f->height = decoder->rect.height / 2; - f->code = MEDIA_BUS_FMT_UYVY8_2X8; - f->field = V4L2_FIELD_ALTERNATE; - f->colorspace = V4L2_COLORSPACE_SMPTE170M; + f->code = TVP5150_MBUS_FMT; + f->field = TVP5150_FIELD; + f->colorspace = TVP5150_COLORSPACE; dev_dbg_lvl(sd->dev, 1, debug, "width = %d, height = %d\n", f->width, - f->height); + f->height); return 0; } @@ -901,9 +1028,6 @@ static int tvp5150_set_selection(struct v4l2_subdev *sd, /* tvp5150 has some special limits */ rect.left = clamp(rect.left, 0, TVP5150_MAX_CROP_LEFT); - rect.width = clamp_t(unsigned int, rect.width, - TVP5150_H_MAX - TVP5150_MAX_CROP_LEFT - rect.left, - TVP5150_H_MAX - rect.left); rect.top = clamp(rect.top, 0, TVP5150_MAX_CROP_TOP); /* Calculate height based on current standard */ @@ -917,22 +1041,29 @@ static int tvp5150_set_selection(struct v4l2_subdev *sd, else hmax = TVP5150_V_MAX_OTHERS; - rect.height = clamp_t(unsigned int, rect.height, + /* + * alignments: + * - width = 2 due to UYVY colorspace + * - height, image = no special alignment + */ + v4l_bound_align_image(&rect.width, + TVP5150_H_MAX - TVP5150_MAX_CROP_LEFT - rect.left, + TVP5150_H_MAX - rect.left, 1, &rect.height, hmax - TVP5150_MAX_CROP_TOP - rect.top, - hmax - rect.top); - - tvp5150_write(sd, TVP5150_VERT_BLANKING_START, rect.top); - tvp5150_write(sd, TVP5150_VERT_BLANKING_STOP, - rect.top + rect.height - hmax); - tvp5150_write(sd, TVP5150_ACT_VD_CROP_ST_MSB, - rect.left >> TVP5150_CROP_SHIFT); - tvp5150_write(sd, TVP5150_ACT_VD_CROP_ST_LSB, - rect.left | (1 << TVP5150_CROP_SHIFT)); - tvp5150_write(sd, TVP5150_ACT_VD_CROP_STP_MSB, - (rect.left + rect.width - TVP5150_MAX_CROP_LEFT) >> - TVP5150_CROP_SHIFT); - tvp5150_write(sd, TVP5150_ACT_VD_CROP_STP_LSB, - rect.left + rect.width - TVP5150_MAX_CROP_LEFT); + hmax - rect.top, 0, 0); + + regmap_write(decoder->regmap, TVP5150_VERT_BLANKING_START, rect.top); + regmap_write(decoder->regmap, TVP5150_VERT_BLANKING_STOP, + rect.top + rect.height - hmax); + regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_ST_MSB, + rect.left >> TVP5150_CROP_SHIFT); + regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_ST_LSB, + rect.left | (1 << TVP5150_CROP_SHIFT)); + regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_STP_MSB, + (rect.left + rect.width - TVP5150_MAX_CROP_LEFT) >> + TVP5150_CROP_SHIFT); + regmap_write(decoder->regmap, TVP5150_ACT_VD_CROP_STP_LSB, + rect.left + rect.width - TVP5150_MAX_CROP_LEFT); decoder->rect = rect; @@ -951,7 +1082,6 @@ static int tvp5150_get_selection(struct v4l2_subdev *sd, switch (sel->target) { case V4L2_SEL_TGT_CROP_BOUNDS: - case V4L2_SEL_TGT_CROP_DEFAULT: sel->r.left = 0; sel->r.top = 0; sel->r.width = TVP5150_H_MAX; @@ -989,6 +1119,27 @@ static int tvp5150_g_mbus_config(struct v4l2_subdev *sd, /**************************************************************************** V4L2 subdev pad ops ****************************************************************************/ +static int tvp5150_init_cfg(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg) +{ + struct tvp5150 *decoder = to_tvp5150(sd); + v4l2_std_id std; + + /* + * Reset selection to maximum on subdev_open() if autodetection is on + * and a standard change is detected. + */ + if (decoder->norm == V4L2_STD_ALL) { + std = tvp5150_read_std(sd); + if (std != decoder->detected_norm) { + decoder->detected_norm = std; + tvp5150_set_default(std, &decoder->rect); + } + } + + return 0; +} + static int tvp5150_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_mbus_code_enum *code) @@ -996,7 +1147,7 @@ static int tvp5150_enum_mbus_code(struct v4l2_subdev *sd, if (code->pad || code->index) return -EINVAL; - code->code = MEDIA_BUS_FMT_UYVY8_2X8; + code->code = TVP5150_MBUS_FMT; return 0; } @@ -1006,10 +1157,10 @@ static int tvp5150_enum_frame_size(struct v4l2_subdev *sd, { struct tvp5150 *decoder = to_tvp5150(sd); - if (fse->index >= 8 || fse->code != MEDIA_BUS_FMT_UYVY8_2X8) + if (fse->index >= 8 || fse->code != TVP5150_MBUS_FMT) return -EINVAL; - fse->code = MEDIA_BUS_FMT_UYVY8_2X8; + fse->code = TVP5150_MBUS_FMT; fse->min_width = decoder->rect.width; fse->max_width = decoder->rect.width; fse->min_height = decoder->rect.height / 2; @@ -1059,27 +1210,28 @@ static const struct media_entity_operations tvp5150_sd_media_ops = { static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable) { struct tvp5150 *decoder = to_tvp5150(sd); - int val; + unsigned int mask, val = 0, int_val = 0; - /* Enable or disable the video output signals. */ - val = tvp5150_read(sd, TVP5150_MISC_CTL); - if (val < 0) - return val; - - val &= ~(TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_SYNC_OE | - TVP5150_MISC_CTL_CLOCK_OE); + mask = TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_SYNC_OE | + TVP5150_MISC_CTL_CLOCK_OE; if (enable) { - /* - * Enable the YCbCr and clock outputs. In discrete sync mode - * (non-BT.656) additionally enable the the sync outputs. - */ - val |= TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_CLOCK_OE; - if (decoder->mbus_type == V4L2_MBUS_PARALLEL) - val |= TVP5150_MISC_CTL_SYNC_OE; + tvp5150_enable(sd); + + /* Enable outputs if decoder is locked */ + if (decoder->irq) + val = decoder->lock ? decoder->oe : 0; + else + val = decoder->oe; + int_val = TVP5150_INT_A_LOCK; + v4l2_subdev_notify_event(&decoder->sd, &tvp5150_ev_fmt); } - tvp5150_write(sd, TVP5150_MISC_CTL, val); + regmap_update_bits(decoder->regmap, TVP5150_MISC_CTL, mask, val); + if (decoder->irq) + /* Enable / Disable lock interrupt */ + regmap_update_bits(decoder->regmap, TVP5150_INT_ENABLE_REG_A, + TVP5150_INT_A_LOCK, int_val); return 0; } @@ -1103,6 +1255,8 @@ static int tvp5150_s_routing(struct v4l2_subdev *sd, static int tvp5150_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt) { + struct tvp5150 *decoder = to_tvp5150(sd); + /* * this is for capturing 36 raw vbi lines * if there's a way to cut off the beginning 2 vbi lines @@ -1112,16 +1266,18 @@ static int tvp5150_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt */ if (fmt->sample_format == V4L2_PIX_FMT_GREY) - tvp5150_write(sd, TVP5150_LUMA_PROC_CTL_1, 0x70); + regmap_write(decoder->regmap, TVP5150_LUMA_PROC_CTL_1, 0x70); if (fmt->count[0] == 18 && fmt->count[1] == 18) { - tvp5150_write(sd, TVP5150_VERT_BLANKING_START, 0x00); - tvp5150_write(sd, TVP5150_VERT_BLANKING_STOP, 0x01); + regmap_write(decoder->regmap, TVP5150_VERT_BLANKING_START, + 0x00); + regmap_write(decoder->regmap, TVP5150_VERT_BLANKING_STOP, 0x01); } return 0; } static int tvp5150_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi) { + struct tvp5150 *decoder = to_tvp5150(sd); int i; if (svbi->service_set != 0) { @@ -1132,17 +1288,17 @@ static int tvp5150_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f 0xf0, i, 3); } /* Enables FIFO */ - tvp5150_write(sd, TVP5150_FIFO_OUT_CTRL, 1); + regmap_write(decoder->regmap, TVP5150_FIFO_OUT_CTRL, 1); } else { /* Disables FIFO*/ - tvp5150_write(sd, TVP5150_FIFO_OUT_CTRL, 0); + regmap_write(decoder->regmap, TVP5150_FIFO_OUT_CTRL, 0); /* Disable Full Field */ - tvp5150_write(sd, TVP5150_FULL_FIELD_ENA, 0); + regmap_write(decoder->regmap, TVP5150_FULL_FIELD_ENA, 0); /* Disable Line modes */ for (i = TVP5150_LINE_MODE_INI; i <= TVP5150_LINE_MODE_END; i++) - tvp5150_write(sd, i, 0xff); + regmap_write(decoder->regmap, i, 0xff); } return 0; } @@ -1180,7 +1336,9 @@ static int tvp5150_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register * static int tvp5150_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { - return tvp5150_write(sd, reg->reg & 0xff, reg->val & 0xff); + struct tvp5150 *decoder = to_tvp5150(sd); + + return regmap_write(decoder->regmap, reg->reg & 0xff, reg->val & 0xff); } #endif @@ -1217,7 +1375,7 @@ static int tvp5150_registered(struct v4l2_subdev *sd) return ret; ret = media_create_pad_link(input, 0, &sd->entity, - DEMOD_PAD_IF_INPUT, 0); + TVP5150_PAD_IF_INPUT, 0); if (ret < 0) { media_device_unregister_entity(input); return ret; @@ -1249,6 +1407,8 @@ static const struct v4l2_subdev_tuner_ops tvp5150_tuner_ops = { static const struct v4l2_subdev_video_ops tvp5150_video_ops = { .s_std = tvp5150_s_std, + .g_std = tvp5150_g_std, + .querystd = tvp5150_querystd, .s_stream = tvp5150_s_stream, .s_routing = tvp5150_s_routing, .g_mbus_config = tvp5150_g_mbus_config, @@ -1262,6 +1422,7 @@ static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = { }; static const struct v4l2_subdev_pad_ops tvp5150_pad_ops = { + .init_cfg = tvp5150_init_cfg, .enum_mbus_code = tvp5150_enum_mbus_code, .enum_frame_size = tvp5150_enum_frame_size, .set_fmt = tvp5150_fill_fmt, @@ -1282,16 +1443,87 @@ static const struct v4l2_subdev_internal_ops tvp5150_internal_ops = { .registered = tvp5150_registered, }; - /**************************************************************************** I2C Client & Driver ****************************************************************************/ +static const struct regmap_range tvp5150_readable_ranges[] = { + { + .range_min = TVP5150_VD_IN_SRC_SEL_1, + .range_max = TVP5150_AUTOSW_MSK, + }, { + .range_min = TVP5150_COLOR_KIL_THSH_CTL, + .range_max = TVP5150_CONF_SHARED_PIN, + }, { + .range_min = TVP5150_ACT_VD_CROP_ST_MSB, + .range_max = TVP5150_HORIZ_SYNC_START, + }, { + .range_min = TVP5150_VERT_BLANKING_START, + .range_max = TVP5150_INTT_CONFIG_REG_B, + }, { + .range_min = TVP5150_VIDEO_STD, + .range_max = TVP5150_VIDEO_STD, + }, { + .range_min = TVP5150_CB_GAIN_FACT, + .range_max = TVP5150_REV_SELECT, + }, { + .range_min = TVP5150_MSB_DEV_ID, + .range_max = TVP5150_STATUS_REG_5, + }, { + .range_min = TVP5150_CC_DATA_INI, + .range_max = TVP5150_TELETEXT_FIL_ENA, + }, { + .range_min = TVP5150_INT_STATUS_REG_A, + .range_max = TVP5150_FIFO_OUT_CTRL, + }, { + .range_min = TVP5150_FULL_FIELD_ENA, + .range_max = TVP5150_FULL_FIELD_MODE_REG, + }, +}; + +static bool tvp5150_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case TVP5150_VERT_LN_COUNT_MSB: + case TVP5150_VERT_LN_COUNT_LSB: + case TVP5150_INT_STATUS_REG_A: + case TVP5150_INT_STATUS_REG_B: + case TVP5150_INT_ACTIVE_REG_B: + case TVP5150_STATUS_REG_1: + case TVP5150_STATUS_REG_2: + case TVP5150_STATUS_REG_3: + case TVP5150_STATUS_REG_4: + case TVP5150_STATUS_REG_5: + /* CC, WSS, VPS, VITC data? */ + case TVP5150_VBI_FIFO_READ_DATA: + case TVP5150_VDP_STATUS_REG: + case TVP5150_FIFO_WORD_COUNT: + return true; + default: + return false; + } +} + +static const struct regmap_access_table tvp5150_readable_table = { + .yes_ranges = tvp5150_readable_ranges, + .n_yes_ranges = ARRAY_SIZE(tvp5150_readable_ranges), +}; + +static struct regmap_config tvp5150_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0xff, + + .cache_type = REGCACHE_RBTREE, + + .rd_table = &tvp5150_readable_table, + .volatile_reg = tvp5150_volatile_reg, +}; + static int tvp5150_detect_version(struct tvp5150 *core) { struct v4l2_subdev *sd = &core->sd; struct i2c_client *c = v4l2_get_subdevdata(sd); - unsigned int i; u8 regs[4]; int res; @@ -1299,11 +1531,10 @@ static int tvp5150_detect_version(struct tvp5150 *core) * Read consequent registers - TVP5150_MSB_DEV_ID, TVP5150_LSB_DEV_ID, * TVP5150_ROM_MAJOR_VER, TVP5150_ROM_MINOR_VER */ - for (i = 0; i < 4; i++) { - res = tvp5150_read(sd, TVP5150_MSB_DEV_ID + i); - if (res < 0) - return res; - regs[i] = res; + res = regmap_bulk_read(core->regmap, TVP5150_MSB_DEV_ID, regs, 4); + if (res < 0) { + dev_err(&c->dev, "reading ID registers failed: %d\n", res); + return res; } core->dev_id = (regs[0] << 8) | regs[1]; @@ -1319,7 +1550,7 @@ static int tvp5150_detect_version(struct tvp5150 *core) dev_info(sd->dev, "tvp5150am1 detected.\n"); /* ITU-T BT.656.4 timing */ - tvp5150_write(sd, TVP5150_REV_SELECT, 0); + regmap_write(core->regmap, TVP5150_REV_SELECT, 0); } else if (core->dev_id == 0x5151 && core->rom_ver == 0x0100) { dev_info(sd->dev, "tvp5151 detected.\n"); } else { @@ -1362,7 +1593,7 @@ static int tvp5150_init(struct i2c_client *c) static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np) { - struct v4l2_fwnode_endpoint bus_cfg; + struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 }; struct device_node *ep; #ifdef CONFIG_MEDIA_CONTROLLER struct device_node *connectors, *child; @@ -1403,8 +1634,8 @@ static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np) ret = of_property_read_u32(child, "input", &input_type); if (ret) { dev_err(decoder->sd.dev, - "missing type property in node %s\n", - child->name); + "missing type property in node %pOFn\n", + child); goto err_connector; } @@ -1439,8 +1670,8 @@ static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np) ret = of_property_read_string(child, "label", &name); if (ret < 0) { dev_err(decoder->sd.dev, - "missing label property in node %s\n", - child->name); + "missing label property in node %pOFn\n", + child); goto err_connector; } @@ -1466,6 +1697,7 @@ static int tvp5150_probe(struct i2c_client *c, struct tvp5150 *core; struct v4l2_subdev *sd; struct device_node *np = c->dev.of_node; + struct regmap *map; int res; /* Check if the adapter supports the needed features */ @@ -1481,6 +1713,11 @@ static int tvp5150_probe(struct i2c_client *c, if (!core) return -ENOMEM; + map = devm_regmap_init_i2c(c, &tvp5150_config); + if (IS_ERR(map)) + return PTR_ERR(map); + + core->regmap = map; sd = &core->sd; if (IS_ENABLED(CONFIG_OF) && np) { @@ -1499,13 +1736,14 @@ static int tvp5150_probe(struct i2c_client *c, sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; #if defined(CONFIG_MEDIA_CONTROLLER) - core->pads[DEMOD_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK; - core->pads[DEMOD_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE; - core->pads[DEMOD_PAD_VBI_OUT].flags = MEDIA_PAD_FL_SOURCE; + core->pads[TVP5150_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK; + core->pads[TVP5150_PAD_IF_INPUT].sig_type = PAD_SIGNAL_ANALOG; + core->pads[TVP5150_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE; + core->pads[TVP5150_PAD_VID_OUT].sig_type = PAD_SIGNAL_DV; sd->entity.function = MEDIA_ENT_F_ATV_DECODER; - res = media_entity_pads_init(&sd->entity, DEMOD_NUM_PADS, core->pads); + res = media_entity_pads_init(&sd->entity, TVP5150_NUM_PADS, core->pads); if (res < 0) return res; @@ -1517,6 +1755,7 @@ static int tvp5150_probe(struct i2c_client *c, return res; core->norm = V4L2_STD_ALL; /* Default is autodetect */ + core->detected_norm = V4L2_STD_UNKNOWN; core->input = TVP5150_COMPOSITE1; core->enable = true; @@ -1534,7 +1773,7 @@ static int tvp5150_probe(struct i2c_client *c, 27000000, 1, 27000000); v4l2_ctrl_new_std_menu_items(&core->hdl, &tvp5150_ctrl_ops, V4L2_CID_TEST_PATTERN, - ARRAY_SIZE(tvp5150_test_patterns), + ARRAY_SIZE(tvp5150_test_patterns) - 1, 0, 0, tvp5150_test_patterns); sd->ctrl_handler = &core->hdl; if (core->hdl.error) { @@ -1542,16 +1781,17 @@ static int tvp5150_probe(struct i2c_client *c, goto err; } - /* Default is no cropping */ - core->rect.top = 0; - if (tvp5150_read_std(sd) & V4L2_STD_525_60) - core->rect.height = TVP5150_V_MAX_525_60; - else - core->rect.height = TVP5150_V_MAX_OTHERS; - core->rect.left = 0; - core->rect.width = TVP5150_H_MAX; + tvp5150_set_default(tvp5150_read_std(sd), &core->rect); + core->irq = c->irq; tvp5150_reset(sd, 0); /* Calls v4l2_ctrl_handler_setup() */ + if (c->irq) { + res = devm_request_threaded_irq(&c->dev, c->irq, NULL, + tvp5150_isr, IRQF_TRIGGER_HIGH | + IRQF_ONESHOT, "tvp5150", core); + if (res) + return res; + } res = v4l2_async_register_subdev(sd); if (res < 0) diff --git a/drivers/media/i2c/tvp5150_reg.h b/drivers/media/i2c/tvp5150_reg.h index d3a764cae1a0..9088186c24d1 100644 --- a/drivers/media/i2c/tvp5150_reg.h +++ b/drivers/media/i2c/tvp5150_reg.h @@ -125,8 +125,11 @@ #define TVP5150_TELETEXT_FIL_ENA 0xbb /* Teletext filter enable */ /* Reserved BCh-BFh */ #define TVP5150_INT_STATUS_REG_A 0xc0 /* Interrupt status register A */ +#define TVP5150_INT_A_LOCK_STATUS BIT(7) +#define TVP5150_INT_A_LOCK BIT(6) #define TVP5150_INT_ENABLE_REG_A 0xc1 /* Interrupt enable register A */ #define TVP5150_INT_CONF 0xc2 /* Interrupt configuration */ +#define TVP5150_VDPOE BIT(2) #define TVP5150_VDP_CONF_RAM_DATA 0xc3 /* VDP configuration RAM data */ #define TVP5150_CONF_RAM_ADDR_LOW 0xc4 /* Configuration RAM address low byte */ #define TVP5150_CONF_RAM_ADDR_HIGH 0xc5 /* Configuration RAM address high byte */ diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c index 4f5c627579c7..cab2f2bd0aa9 100644 --- a/drivers/media/i2c/tvp7002.c +++ b/drivers/media/i2c/tvp7002.c @@ -889,7 +889,7 @@ static const struct v4l2_subdev_ops tvp7002_ops = { static struct tvp7002_config * tvp7002_get_pdata(struct i2c_client *client) { - struct v4l2_fwnode_endpoint bus_cfg; + struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 }; struct tvp7002_config *pdata = NULL; struct device_node *endpoint; unsigned int flags; diff --git a/drivers/media/i2c/video-i2c.c b/drivers/media/i2c/video-i2c.c index 06d29d8f6be8..4d49af86c15e 100644 --- a/drivers/media/i2c/video-i2c.c +++ b/drivers/media/i2c/video-i2c.c @@ -352,8 +352,8 @@ static int video_i2c_querycap(struct file *file, void *priv, struct video_i2c_data *data = video_drvdata(file); struct i2c_client *client = data->client; - strlcpy(vcap->driver, data->v4l2_dev.name, sizeof(vcap->driver)); - strlcpy(vcap->card, data->vdev.name, sizeof(vcap->card)); + strscpy(vcap->driver, data->v4l2_dev.name, sizeof(vcap->driver)); + strscpy(vcap->card, data->vdev.name, sizeof(vcap->card)); sprintf(vcap->bus_info, "I2C:%d-%d", client->adapter->nr, client->addr); @@ -378,7 +378,7 @@ static int video_i2c_enum_input(struct file *file, void *fh, if (vin->index > 0) return -EINVAL; - strlcpy(vin->name, "Camera", sizeof(vin->name)); + strscpy(vin->name, "Camera", sizeof(vin->name)); vin->type = V4L2_INPUT_TYPE_CAMERA; @@ -534,7 +534,7 @@ static int video_i2c_probe(struct i2c_client *client, data->client = client; v4l2_dev = &data->v4l2_dev; - strlcpy(v4l2_dev->name, VIDEO_I2C_DRIVER, sizeof(v4l2_dev->name)); + strscpy(v4l2_dev->name, VIDEO_I2C_DRIVER, sizeof(v4l2_dev->name)); ret = v4l2_device_register(&client->dev, v4l2_dev); if (ret < 0) diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c index 3bae24b15eaa..4c7190db420e 100644 --- a/drivers/media/media-device.c +++ b/drivers/media/media-device.c @@ -69,14 +69,14 @@ static long media_device_get_info(struct media_device *dev, void *arg) memset(info, 0, sizeof(*info)); if (dev->driver_name[0]) - strlcpy(info->driver, dev->driver_name, sizeof(info->driver)); + strscpy(info->driver, dev->driver_name, sizeof(info->driver)); else - strlcpy(info->driver, dev->dev->driver->name, + strscpy(info->driver, dev->dev->driver->name, sizeof(info->driver)); - strlcpy(info->model, dev->model, sizeof(info->model)); - strlcpy(info->serial, dev->serial, sizeof(info->serial)); - strlcpy(info->bus_info, dev->bus_info, sizeof(info->bus_info)); + strscpy(info->model, dev->model, sizeof(info->model)); + strscpy(info->serial, dev->serial, sizeof(info->serial)); + strscpy(info->bus_info, dev->bus_info, sizeof(info->bus_info)); info->media_version = LINUX_VERSION_CODE; info->driver_version = info->media_version; @@ -115,7 +115,7 @@ static long media_device_enum_entities(struct media_device *mdev, void *arg) entd->id = media_entity_id(ent); if (ent->name) - strlcpy(entd->name, ent->name, sizeof(entd->name)); + strscpy(entd->name, ent->name, sizeof(entd->name)); entd->type = ent->function; entd->revision = 0; /* Unused */ entd->flags = ent->flags; @@ -268,7 +268,7 @@ static long media_device_get_topology(struct media_device *mdev, void *arg) kentity.id = entity->graph_obj.id; kentity.function = entity->function; kentity.flags = entity->flags; - strlcpy(kentity.name, entity->name, + strscpy(kentity.name, entity->name, sizeof(kentity.name)); if (copy_to_user(uentity, &kentity, sizeof(kentity))) @@ -836,9 +836,9 @@ void media_device_pci_init(struct media_device *mdev, mdev->dev = &pci_dev->dev; if (name) - strlcpy(mdev->model, name, sizeof(mdev->model)); + strscpy(mdev->model, name, sizeof(mdev->model)); else - strlcpy(mdev->model, pci_name(pci_dev), sizeof(mdev->model)); + strscpy(mdev->model, pci_name(pci_dev), sizeof(mdev->model)); sprintf(mdev->bus_info, "PCI:%s", pci_name(pci_dev)); @@ -859,17 +859,17 @@ void __media_device_usb_init(struct media_device *mdev, mdev->dev = &udev->dev; if (driver_name) - strlcpy(mdev->driver_name, driver_name, + strscpy(mdev->driver_name, driver_name, sizeof(mdev->driver_name)); if (board_name) - strlcpy(mdev->model, board_name, sizeof(mdev->model)); + strscpy(mdev->model, board_name, sizeof(mdev->model)); else if (udev->product) - strlcpy(mdev->model, udev->product, sizeof(mdev->model)); + strscpy(mdev->model, udev->product, sizeof(mdev->model)); else - strlcpy(mdev->model, "unknown model", sizeof(mdev->model)); + strscpy(mdev->model, "unknown model", sizeof(mdev->model)); if (udev->serial) - strlcpy(mdev->serial, udev->serial, sizeof(mdev->serial)); + strscpy(mdev->serial, udev->serial, sizeof(mdev->serial)); usb_make_path(udev, mdev->bus_info, sizeof(mdev->bus_info)); mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c index 3498551e618e..0b1cb3559140 100644 --- a/drivers/media/media-entity.c +++ b/drivers/media/media-entity.c @@ -662,6 +662,32 @@ static void __media_entity_remove_link(struct media_entity *entity, kfree(link); } +int media_get_pad_index(struct media_entity *entity, bool is_sink, + enum media_pad_signal_type sig_type) +{ + int i; + bool pad_is_sink; + + if (!entity) + return -EINVAL; + + for (i = 0; i < entity->num_pads; i++) { + if (entity->pads[i].flags == MEDIA_PAD_FL_SINK) + pad_is_sink = true; + else if (entity->pads[i].flags == MEDIA_PAD_FL_SOURCE) + pad_is_sink = false; + else + continue; /* This is an error! */ + + if (pad_is_sink != is_sink) + continue; + if (entity->pads[i].sig_type == sig_type) + return i; + } + return -EINVAL; +} +EXPORT_SYMBOL_GPL(media_get_pad_index); + int media_create_pad_link(struct media_entity *source, u16 source_pad, struct media_entity *sink, u16 sink_pad, u32 flags) diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c index cf05e11da01b..b2cfcbb0008e 100644 --- a/drivers/media/pci/bt8xx/bttv-driver.c +++ b/drivers/media/pci/bt8xx/bttv-driver.c @@ -2040,7 +2040,6 @@ limit_scaled_size_lock (struct bttv_fh * fh, max_width = max_width & width_mask; /* Max. scale factor is 16:1 for frames, 8:1 for fields. */ - min_height = min_height; /* Min. scale factor is 1:1. */ max_height >>= !V4L2_FIELD_HAS_BOTH(field); @@ -2473,8 +2472,8 @@ static int bttv_querycap(struct file *file, void *priv, if (0 == v4l2) return -EINVAL; - strlcpy(cap->driver, "bttv", sizeof(cap->driver)); - strlcpy(cap->card, btv->video_dev.name, sizeof(cap->card)); + strscpy(cap->driver, "bttv", sizeof(cap->driver)); + strscpy(cap->card, btv->video_dev.name, sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", pci_name(btv->c.pci)); cap->capabilities = @@ -2535,7 +2534,7 @@ static int bttv_enum_fmt_cap_ovr(struct v4l2_fmtdesc *f) return -EINVAL; f->pixelformat = formats[i].fourcc; - strlcpy(f->description, formats[i].name, sizeof(f->description)); + strscpy(f->description, formats[i].name, sizeof(f->description)); return i; } @@ -2782,7 +2781,7 @@ static int bttv_g_tuner(struct file *file, void *priv, t->rxsubchans = V4L2_TUNER_SUB_MONO; t->capability = V4L2_TUNER_CAP_NORM; bttv_call_all(btv, tuner, g_tuner, t); - strcpy(t->name, "Television"); + strscpy(t->name, "Television", sizeof(t->name)); t->type = V4L2_TUNER_ANALOG_TV; if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC) t->signal = 0xffff; @@ -3257,7 +3256,7 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) if (0 != t->index) return -EINVAL; - strcpy(t->name, "Radio"); + strscpy(t->name, "Radio", sizeof(t->name)); t->type = V4L2_TUNER_RADIO; radio_enable(btv); diff --git a/drivers/media/pci/bt8xx/bttv-i2c.c b/drivers/media/pci/bt8xx/bttv-i2c.c index c76823eb399d..15ff7f9d8373 100644 --- a/drivers/media/pci/bt8xx/bttv-i2c.c +++ b/drivers/media/pci/bt8xx/bttv-i2c.c @@ -347,13 +347,13 @@ static void do_i2c_scan(char *name, struct i2c_client *c) /* init + register i2c adapter */ int init_bttv_i2c(struct bttv *btv) { - strlcpy(btv->i2c_client.name, "bttv internal", I2C_NAME_SIZE); + strscpy(btv->i2c_client.name, "bttv internal", I2C_NAME_SIZE); if (i2c_hw) btv->use_i2c_hw = 1; if (btv->use_i2c_hw) { /* bt878 */ - strlcpy(btv->c.i2c_adap.name, "bt878", + strscpy(btv->c.i2c_adap.name, "bt878", sizeof(btv->c.i2c_adap.name)); btv->c.i2c_adap.algo = &bttv_algo; } else { @@ -362,7 +362,7 @@ int init_bttv_i2c(struct bttv *btv) if (i2c_udelay<5) i2c_udelay=5; - strlcpy(btv->c.i2c_adap.name, "bttv", + strscpy(btv->c.i2c_adap.name, "bttv", sizeof(btv->c.i2c_adap.name)); btv->i2c_algo = bttv_i2c_algo_bit_template; btv->i2c_algo.udelay = i2c_udelay; diff --git a/drivers/media/pci/bt8xx/bttv-input.c b/drivers/media/pci/bt8xx/bttv-input.c index 08266b23826e..d34fbaa027c2 100644 --- a/drivers/media/pci/bt8xx/bttv-input.c +++ b/drivers/media/pci/bt8xx/bttv-input.c @@ -370,7 +370,7 @@ static int get_key_pv951(struct IR_i2c *ir, enum rc_proto *protocol, /* Instantiate the I2C IR receiver device, if present */ void init_bttv_i2c_ir(struct bttv *btv) { - const unsigned short addr_list[] = { + static const unsigned short addr_list[] = { 0x1a, 0x18, 0x64, 0x30, 0x71, I2C_CLIENT_END }; @@ -382,7 +382,7 @@ void init_bttv_i2c_ir(struct bttv *btv) memset(&info, 0, sizeof(struct i2c_board_info)); memset(&btv->init_data, 0, sizeof(btv->init_data)); - strlcpy(info.type, "ir_video", I2C_NAME_SIZE); + strscpy(info.type, "ir_video", I2C_NAME_SIZE); switch (btv->c.type) { case BTTV_BOARD_PV951: diff --git a/drivers/media/pci/bt8xx/dvb-bt8xx.c b/drivers/media/pci/bt8xx/dvb-bt8xx.c index 2f810b7130e6..b46fbe557dd9 100644 --- a/drivers/media/pci/bt8xx/dvb-bt8xx.c +++ b/drivers/media/pci/bt8xx/dvb-bt8xx.c @@ -819,7 +819,8 @@ static int dvb_bt8xx_probe(struct bttv_sub_device *sub) mutex_init(&card->lock); card->bttv_nr = sub->core->nr; - strlcpy(card->card_name, sub->core->v4l2_dev.name, sizeof(card->card_name)); + strscpy(card->card_name, sub->core->v4l2_dev.name, + sizeof(card->card_name)); card->i2c_adapter = &sub->core->i2c_adap; switch(sub->core->type) { diff --git a/drivers/media/pci/cobalt/cobalt-alsa-main.c b/drivers/media/pci/cobalt/cobalt-alsa-main.c index e5022b620856..c57f87a68269 100644 --- a/drivers/media/pci/cobalt/cobalt-alsa-main.c +++ b/drivers/media/pci/cobalt/cobalt-alsa-main.c @@ -65,7 +65,7 @@ static int snd_cobalt_card_set_names(struct snd_cobalt_card *cobsc) struct snd_card *sc = cobsc->sc; /* sc->driver is used by alsa-lib's configurator: simple, unique */ - strlcpy(sc->driver, "cobalt", sizeof(sc->driver)); + strscpy(sc->driver, "cobalt", sizeof(sc->driver)); /* sc->shortname is a symlink in /proc/asound: COBALT-M -> cardN */ snprintf(sc->shortname, sizeof(sc->shortname), "cobalt-%d-%d", diff --git a/drivers/media/pci/cobalt/cobalt-alsa-pcm.c b/drivers/media/pci/cobalt/cobalt-alsa-pcm.c index f6a7df13cd04..38d00935a292 100644 --- a/drivers/media/pci/cobalt/cobalt-alsa-pcm.c +++ b/drivers/media/pci/cobalt/cobalt-alsa-pcm.c @@ -557,7 +557,7 @@ int snd_cobalt_pcm_create(struct snd_cobalt_card *cobsc) &snd_cobalt_pcm_capture_ops); sp->info_flags = 0; sp->private_data = cobsc; - strlcpy(sp->name, "cobalt", sizeof(sp->name)); + strscpy(sp->name, "cobalt", sizeof(sp->name)); } else { cobalt_s_bit_sysctrl(cobalt, COBALT_SYS_CTRL_AUDIO_OPP_RESETN_BIT, 0); @@ -581,7 +581,7 @@ int snd_cobalt_pcm_create(struct snd_cobalt_card *cobsc) &snd_cobalt_pcm_playback_ops); sp->info_flags = 0; sp->private_data = cobsc; - strlcpy(sp->name, "cobalt", sizeof(sp->name)); + strscpy(sp->name, "cobalt", sizeof(sp->name)); } return 0; diff --git a/drivers/media/pci/cobalt/cobalt-v4l2.c b/drivers/media/pci/cobalt/cobalt-v4l2.c index e2a4c705d353..0525f5e1565b 100644 --- a/drivers/media/pci/cobalt/cobalt-v4l2.c +++ b/drivers/media/pci/cobalt/cobalt-v4l2.c @@ -479,8 +479,8 @@ static int cobalt_querycap(struct file *file, void *priv_fh, struct cobalt_stream *s = video_drvdata(file); struct cobalt *cobalt = s->cobalt; - strlcpy(vcap->driver, "cobalt", sizeof(vcap->driver)); - strlcpy(vcap->card, "cobalt", sizeof(vcap->card)); + strscpy(vcap->driver, "cobalt", sizeof(vcap->driver)); + strscpy(vcap->card, "cobalt", sizeof(vcap->card)); snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCIe:%s", pci_name(cobalt->pci_dev)); vcap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_READWRITE; @@ -693,15 +693,15 @@ static int cobalt_enum_fmt_vid_cap(struct file *file, void *priv_fh, { switch (f->index) { case 0: - strlcpy(f->description, "YUV 4:2:2", sizeof(f->description)); + strscpy(f->description, "YUV 4:2:2", sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_YUYV; break; case 1: - strlcpy(f->description, "RGB24", sizeof(f->description)); + strscpy(f->description, "RGB24", sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_RGB24; break; case 2: - strlcpy(f->description, "RGB32", sizeof(f->description)); + strscpy(f->description, "RGB32", sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_BGR32; break; default: @@ -898,11 +898,11 @@ static int cobalt_enum_fmt_vid_out(struct file *file, void *priv_fh, { switch (f->index) { case 0: - strlcpy(f->description, "YUV 4:2:2", sizeof(f->description)); + strscpy(f->description, "YUV 4:2:2", sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_YUYV; break; case 1: - strlcpy(f->description, "RGB32", sizeof(f->description)); + strscpy(f->description, "RGB32", sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_BGR32; break; default: @@ -1064,10 +1064,15 @@ static int cobalt_subscribe_event(struct v4l2_fh *fh, static int cobalt_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a) { + struct cobalt_stream *s = video_drvdata(file); + struct v4l2_fract fps; + if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - a->parm.capture.timeperframe.numerator = 1; - a->parm.capture.timeperframe.denominator = 60; + + fps = v4l2_calc_timeperframe(&s->timings); + a->parm.capture.timeperframe.numerator = fps.numerator; + a->parm.capture.timeperframe.denominator = fps.denominator; a->parm.capture.readbuffers = 3; return 0; } diff --git a/drivers/media/pci/cx18/cx18-alsa-main.c b/drivers/media/pci/cx18/cx18-alsa-main.c index 93443d1457c5..687477748fdd 100644 --- a/drivers/media/pci/cx18/cx18-alsa-main.c +++ b/drivers/media/pci/cx18/cx18-alsa-main.c @@ -112,7 +112,7 @@ static int snd_cx18_card_set_names(struct snd_cx18_card *cxsc) struct snd_card *sc = cxsc->sc; /* sc->driver is used by alsa-lib's configurator: simple, unique */ - strlcpy(sc->driver, "CX23418", sizeof(sc->driver)); + strscpy(sc->driver, "CX23418", sizeof(sc->driver)); /* sc->shortname is a symlink in /proc/asound: CX18-M -> cardN */ snprintf(sc->shortname, sizeof(sc->shortname), "CX18-%d", diff --git a/drivers/media/pci/cx18/cx18-alsa-pcm.c b/drivers/media/pci/cx18/cx18-alsa-pcm.c index 4f31042a442a..3eafc27956c2 100644 --- a/drivers/media/pci/cx18/cx18-alsa-pcm.c +++ b/drivers/media/pci/cx18/cx18-alsa-pcm.c @@ -345,7 +345,7 @@ int snd_cx18_pcm_create(struct snd_cx18_card *cxsc) &snd_cx18_pcm_capture_ops); sp->info_flags = 0; sp->private_data = cxsc; - strlcpy(sp->name, cx->card_name, sizeof(sp->name)); + strscpy(sp->name, cx->card_name, sizeof(sp->name)); return 0; diff --git a/drivers/media/pci/cx18/cx18-cards.c b/drivers/media/pci/cx18/cx18-cards.c index c2cf965d639e..2dcbccfbd60d 100644 --- a/drivers/media/pci/cx18/cx18-cards.c +++ b/drivers/media/pci/cx18/cx18-cards.c @@ -602,8 +602,8 @@ int cx18_get_input(struct cx18 *cx, u16 index, struct v4l2_input *input) if (index >= cx->nof_inputs) return -EINVAL; input->index = index; - strlcpy(input->name, input_strs[card_input->video_type - 1], - sizeof(input->name)); + strscpy(input->name, input_strs[card_input->video_type - 1], + sizeof(input->name)); input->type = (card_input->video_type == CX18_CARD_INPUT_VID_TUNER ? V4L2_INPUT_TYPE_TUNER : V4L2_INPUT_TYPE_CAMERA); input->audioset = (1 << cx->nof_audio_inputs) - 1; @@ -625,8 +625,8 @@ int cx18_get_audio_input(struct cx18 *cx, u16 index, struct v4l2_audio *audio) memset(audio, 0, sizeof(*audio)); if (index >= cx->nof_audio_inputs) return -EINVAL; - strlcpy(audio->name, input_strs[aud_input->audio_type - 1], - sizeof(audio->name)); + strscpy(audio->name, input_strs[aud_input->audio_type - 1], + sizeof(audio->name)); audio->index = index; audio->capability = V4L2_AUDCAP_STEREO; return 0; diff --git a/drivers/media/pci/cx18/cx18-driver.c b/drivers/media/pci/cx18/cx18-driver.c index 0c389a3fb4e5..a6ba4ca5aa91 100644 --- a/drivers/media/pci/cx18/cx18-driver.c +++ b/drivers/media/pci/cx18/cx18-driver.c @@ -328,7 +328,7 @@ void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv) if (!c) return; - strlcpy(c->name, "cx18 tveeprom tmp", sizeof(c->name)); + strscpy(c->name, "cx18 tveeprom tmp", sizeof(c->name)); c->adapter = &cx->i2c_adap[0]; c->addr = 0xa0 >> 1; @@ -1252,7 +1252,7 @@ static void cx18_cancel_out_work_orders(struct cx18 *cx) { int i; for (i = 0; i < CX18_MAX_STREAMS; i++) - if (&cx->streams[i].video_dev) + if (cx->streams[i].video_dev.v4l2_dev) cancel_work_sync(&cx->streams[i].out_work_order); } diff --git a/drivers/media/pci/cx18/cx18-i2c.c b/drivers/media/pci/cx18/cx18-i2c.c index f0eb181f2b94..a89c666953f5 100644 --- a/drivers/media/pci/cx18/cx18-i2c.c +++ b/drivers/media/pci/cx18/cx18-i2c.c @@ -83,7 +83,7 @@ static int cx18_i2c_new_ir(struct cx18 *cx, struct i2c_adapter *adap, u32 hw, unsigned short addr_list[2] = { addr, I2C_CLIENT_END }; memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, type, I2C_NAME_SIZE); + strscpy(info.type, type, I2C_NAME_SIZE); /* Our default information for ir-kbd-i2c.c to use */ switch (hw) { diff --git a/drivers/media/pci/cx18/cx18-ioctl.c b/drivers/media/pci/cx18/cx18-ioctl.c index 80b902b12a78..854116375a7c 100644 --- a/drivers/media/pci/cx18/cx18-ioctl.c +++ b/drivers/media/pci/cx18/cx18-ioctl.c @@ -397,8 +397,8 @@ static int cx18_querycap(struct file *file, void *fh, struct cx18_stream *s = video_drvdata(file); struct cx18 *cx = id->cx; - strlcpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver)); - strlcpy(vcap->card, cx->card_name, sizeof(vcap->card)); + strscpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver)); + strscpy(vcap->card, cx->card_name, sizeof(vcap->card)); snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(cx->pci_dev)); vcap->capabilities = cx->v4l2_cap; /* capabilities */ @@ -632,9 +632,9 @@ static int cx18_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) cx18_call_all(cx, tuner, g_tuner, vt); if (vt->type == V4L2_TUNER_RADIO) - strlcpy(vt->name, "cx18 Radio Tuner", sizeof(vt->name)); + strscpy(vt->name, "cx18 Radio Tuner", sizeof(vt->name)); else - strlcpy(vt->name, "cx18 TV Tuner", sizeof(vt->name)); + strscpy(vt->name, "cx18 TV Tuner", sizeof(vt->name)); return 0; } diff --git a/drivers/media/pci/cx23885/altera-ci.c b/drivers/media/pci/cx23885/altera-ci.c index 62bc8049b320..198c05e83f5c 100644 --- a/drivers/media/pci/cx23885/altera-ci.c +++ b/drivers/media/pci/cx23885/altera-ci.c @@ -665,6 +665,10 @@ static int altera_hw_filt_init(struct altera_ci_config *config, int hw_filt_nr) } temp_int = append_internal(inter); + if (!temp_int) { + ret = -ENOMEM; + goto err; + } inter->filts_used = 1; inter->dev = config->dev; inter->fpga_rw = config->fpga_rw; @@ -699,6 +703,7 @@ err: __func__, ret); kfree(pid_filt); + kfree(inter); return ret; } @@ -733,6 +738,10 @@ int altera_ci_init(struct altera_ci_config *config, int ci_nr) } temp_int = append_internal(inter); + if (!temp_int) { + ret = -ENOMEM; + goto err; + } inter->cis_used = 1; inter->dev = config->dev; inter->fpga_rw = config->fpga_rw; @@ -801,6 +810,7 @@ err: ci_dbg_print("%s: Cannot initialize CI: Error %d.\n", __func__, ret); kfree(state); + kfree(inter); return ret; } diff --git a/drivers/media/pci/cx23885/cx23885-417.c b/drivers/media/pci/cx23885/cx23885-417.c index a71f3c7569ce..3083434bb636 100644 --- a/drivers/media/pci/cx23885/cx23885-417.c +++ b/drivers/media/pci/cx23885/cx23885-417.c @@ -1280,7 +1280,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, return -EINVAL; if (0 != t->index) return -EINVAL; - strcpy(t->name, "Television"); + strscpy(t->name, "Television", sizeof(t->name)); call_all(dev, tuner, g_tuner, t); dprintk(1, "VIDIOC_G_TUNER: tuner type %d\n", t->type); @@ -1329,8 +1329,8 @@ static int vidioc_querycap(struct file *file, void *priv, struct cx23885_dev *dev = video_drvdata(file); struct cx23885_tsport *tsport = &dev->ts1; - strlcpy(cap->driver, dev->name, sizeof(cap->driver)); - strlcpy(cap->card, cx23885_boards[tsport->dev->board].name, + strscpy(cap->driver, dev->name, sizeof(cap->driver)); + strscpy(cap->card, cx23885_boards[tsport->dev->board].name, sizeof(cap->card)); sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci)); cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | @@ -1349,7 +1349,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, if (f->index != 0) return -EINVAL; - strlcpy(f->description, "MPEG", sizeof(f->description)); + strscpy(f->description, "MPEG", sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_MPEG; return 0; diff --git a/drivers/media/pci/cx23885/cx23885-alsa.c b/drivers/media/pci/cx23885/cx23885-alsa.c index db1e8ff35474..ee9d329c4038 100644 --- a/drivers/media/pci/cx23885/cx23885-alsa.c +++ b/drivers/media/pci/cx23885/cx23885-alsa.c @@ -526,7 +526,7 @@ static int snd_cx23885_pcm(struct cx23885_audio_dev *chip, int device, if (err < 0) return err; pcm->private_data = chip; - strcpy(pcm->name, name); + strscpy(pcm->name, name, sizeof(pcm->name)); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx23885_pcm_ops); return 0; @@ -571,7 +571,7 @@ struct cx23885_audio_dev *cx23885_audio_register(struct cx23885_dev *dev) if (err < 0) goto error; - strcpy(card->driver, "CX23885"); + strscpy(card->driver, "CX23885", sizeof(card->driver)); sprintf(card->shortname, "Conexant CX23885"); sprintf(card->longname, "%s at %s", card->shortname, dev->name); diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c index 7d52173073d6..0d0929c54f93 100644 --- a/drivers/media/pci/cx23885/cx23885-dvb.c +++ b/drivers/media/pci/cx23885/cx23885-dvb.c @@ -1165,7 +1165,7 @@ static int dvb_register_ci_mac(struct cx23885_tsport *port) sp2_config.priv = port; sp2_config.ci_control = cx23885_sp2_ci_ctrl; memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "sp2", I2C_NAME_SIZE); + strscpy(info.type, "sp2", I2C_NAME_SIZE); info.addr = 0x40; info.platform_data = &sp2_config; request_module(info.type); @@ -1831,7 +1831,7 @@ static int dvb_register(struct cx23885_tsport *port) case 1: /* attach demod + tuner combo */ memset(&info, 0, sizeof(info)); - strlcpy(info.type, "tda10071_cx24118", I2C_NAME_SIZE); + strscpy(info.type, "tda10071_cx24118", I2C_NAME_SIZE); info.addr = 0x05; info.platform_data = &tda10071_pdata; request_module("tda10071"); @@ -1848,7 +1848,7 @@ static int dvb_register(struct cx23885_tsport *port) /* attach SEC */ a8293_pdata.dvb_frontend = fe0->dvb.frontend; memset(&info, 0, sizeof(info)); - strlcpy(info.type, "a8293", I2C_NAME_SIZE); + strscpy(info.type, "a8293", I2C_NAME_SIZE); info.addr = 0x0b; info.platform_data = &a8293_pdata; request_module("a8293"); @@ -1869,7 +1869,7 @@ static int dvb_register(struct cx23885_tsport *port) si2165_pdata.chip_mode = SI2165_MODE_PLL_XTAL; si2165_pdata.ref_freq_hz = 16000000; memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2165", I2C_NAME_SIZE); + strscpy(info.type, "si2165", I2C_NAME_SIZE); info.addr = 0x64; info.platform_data = &si2165_pdata; request_module(info.type); @@ -1903,7 +1903,7 @@ static int dvb_register(struct cx23885_tsport *port) /* attach demod + tuner combo */ memset(&info, 0, sizeof(info)); - strlcpy(info.type, "tda10071_cx24118", I2C_NAME_SIZE); + strscpy(info.type, "tda10071_cx24118", I2C_NAME_SIZE); info.addr = 0x05; info.platform_data = &tda10071_pdata; request_module("tda10071"); @@ -1920,7 +1920,7 @@ static int dvb_register(struct cx23885_tsport *port) /* attach SEC */ a8293_pdata.dvb_frontend = fe0->dvb.frontend; memset(&info, 0, sizeof(info)); - strlcpy(info.type, "a8293", I2C_NAME_SIZE); + strscpy(info.type, "a8293", I2C_NAME_SIZE); info.addr = 0x0b; info.platform_data = &a8293_pdata; request_module("a8293"); @@ -1953,7 +1953,7 @@ static int dvb_register(struct cx23885_tsport *port) ts2020_config.fe = fe0->dvb.frontend; ts2020_config.get_agc_pwm = m88ds3103_get_agc_pwm; memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "ts2020", I2C_NAME_SIZE); + strscpy(info.type, "ts2020", I2C_NAME_SIZE); info.addr = 0x60; info.platform_data = &ts2020_config; request_module(info.type); @@ -1990,7 +1990,7 @@ static int dvb_register(struct cx23885_tsport *port) si2168_config.fe = &fe0->dvb.frontend; si2168_config.ts_mode = SI2168_TS_SERIAL; memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2168", I2C_NAME_SIZE); + strscpy(info.type, "si2168", I2C_NAME_SIZE); info.addr = 0x64; info.platform_data = &si2168_config; request_module(info.type); @@ -2009,7 +2009,7 @@ static int dvb_register(struct cx23885_tsport *port) si2157_config.fe = fe0->dvb.frontend; si2157_config.if_port = 1; memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2157", I2C_NAME_SIZE); + strscpy(info.type, "si2157", I2C_NAME_SIZE); info.addr = 0x60; info.platform_data = &si2157_config; request_module(info.type); @@ -2037,7 +2037,7 @@ static int dvb_register(struct cx23885_tsport *port) si2168_config.fe = &fe0->dvb.frontend; si2168_config.ts_mode = SI2168_TS_PARALLEL; memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2168", I2C_NAME_SIZE); + strscpy(info.type, "si2168", I2C_NAME_SIZE); info.addr = 0x64; info.platform_data = &si2168_config; request_module(info.type); @@ -2055,7 +2055,7 @@ static int dvb_register(struct cx23885_tsport *port) si2157_config.fe = fe0->dvb.frontend; si2157_config.if_port = 1; memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2157", I2C_NAME_SIZE); + strscpy(info.type, "si2157", I2C_NAME_SIZE); info.addr = 0x60; info.platform_data = &si2157_config; request_module(info.type); @@ -2085,7 +2085,7 @@ static int dvb_register(struct cx23885_tsport *port) ts2020_config.fe = fe0->dvb.frontend; ts2020_config.get_agc_pwm = m88ds3103_get_agc_pwm; memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "ts2020", I2C_NAME_SIZE); + strscpy(info.type, "ts2020", I2C_NAME_SIZE); info.addr = 0x60; info.platform_data = &ts2020_config; request_module(info.type); @@ -2134,7 +2134,7 @@ static int dvb_register(struct cx23885_tsport *port) } memset(&info, 0, sizeof(info)); - strlcpy(info.type, "m88ds3103", I2C_NAME_SIZE); + strscpy(info.type, "m88ds3103", I2C_NAME_SIZE); info.addr = 0x68; info.platform_data = &m88ds3103_pdata; request_module(info.type); @@ -2154,7 +2154,7 @@ static int dvb_register(struct cx23885_tsport *port) ts2020_config.fe = fe0->dvb.frontend; ts2020_config.get_agc_pwm = m88ds3103_get_agc_pwm; memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "ts2020", I2C_NAME_SIZE); + strscpy(info.type, "ts2020", I2C_NAME_SIZE); info.addr = 0x60; info.platform_data = &ts2020_config; request_module(info.type); @@ -2199,7 +2199,7 @@ static int dvb_register(struct cx23885_tsport *port) si2168_config.i2c_adapter = &adapter; si2168_config.fe = &fe0->dvb.frontend; memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2168", I2C_NAME_SIZE); + strscpy(info.type, "si2168", I2C_NAME_SIZE); info.addr = 0x64; info.platform_data = &si2168_config; request_module(info.type); @@ -2217,7 +2217,7 @@ static int dvb_register(struct cx23885_tsport *port) si2157_config.fe = fe0->dvb.frontend; si2157_config.if_port = 1; memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2157", I2C_NAME_SIZE); + strscpy(info.type, "si2157", I2C_NAME_SIZE); info.addr = 0x60; info.platform_data = &si2157_config; request_module(info.type); @@ -2250,7 +2250,7 @@ static int dvb_register(struct cx23885_tsport *port) /* attach SEC */ a8293_pdata.dvb_frontend = fe0->dvb.frontend; memset(&info, 0, sizeof(info)); - strlcpy(info.type, "a8293", I2C_NAME_SIZE); + strscpy(info.type, "a8293", I2C_NAME_SIZE); info.addr = 0x0b; info.platform_data = &a8293_pdata; request_module("a8293"); @@ -2267,7 +2267,7 @@ static int dvb_register(struct cx23885_tsport *port) memset(&m88rs6000t_config, 0, sizeof(m88rs6000t_config)); m88rs6000t_config.fe = fe0->dvb.frontend; memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "m88rs6000t", I2C_NAME_SIZE); + strscpy(info.type, "m88rs6000t", I2C_NAME_SIZE); info.addr = 0x21; info.platform_data = &m88rs6000t_config; request_module("%s", info.type); @@ -2292,7 +2292,7 @@ static int dvb_register(struct cx23885_tsport *port) si2168_config.fe = &fe0->dvb.frontend; si2168_config.ts_mode = SI2168_TS_SERIAL; memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2168", I2C_NAME_SIZE); + strscpy(info.type, "si2168", I2C_NAME_SIZE); info.addr = 0x64; info.platform_data = &si2168_config; request_module("%s", info.type); @@ -2310,7 +2310,7 @@ static int dvb_register(struct cx23885_tsport *port) si2157_config.fe = fe0->dvb.frontend; si2157_config.if_port = 1; memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2157", I2C_NAME_SIZE); + strscpy(info.type, "si2157", I2C_NAME_SIZE); info.addr = 0x60; info.platform_data = &si2157_config; request_module("%s", info.type); @@ -2345,7 +2345,7 @@ static int dvb_register(struct cx23885_tsport *port) si2168_config.fe = &fe0->dvb.frontend; si2168_config.ts_mode = SI2168_TS_SERIAL; memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2168", I2C_NAME_SIZE); + strscpy(info.type, "si2168", I2C_NAME_SIZE); info.addr = 0x64; info.platform_data = &si2168_config; request_module("%s", info.type); @@ -2363,7 +2363,7 @@ static int dvb_register(struct cx23885_tsport *port) si2157_config.fe = fe0->dvb.frontend; si2157_config.if_port = 1; memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2157", I2C_NAME_SIZE); + strscpy(info.type, "si2157", I2C_NAME_SIZE); info.addr = 0x60; info.platform_data = &si2157_config; request_module("%s", info.type); @@ -2392,7 +2392,7 @@ static int dvb_register(struct cx23885_tsport *port) si2168_config.fe = &fe0->dvb.frontend; si2168_config.ts_mode = SI2168_TS_SERIAL; memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2168", I2C_NAME_SIZE); + strscpy(info.type, "si2168", I2C_NAME_SIZE); info.addr = 0x66; info.platform_data = &si2168_config; request_module("%s", info.type); @@ -2410,7 +2410,7 @@ static int dvb_register(struct cx23885_tsport *port) si2157_config.fe = fe0->dvb.frontend; si2157_config.if_port = 1; memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2157", I2C_NAME_SIZE); + strscpy(info.type, "si2157", I2C_NAME_SIZE); info.addr = 0x62; info.platform_data = &si2157_config; request_module("%s", info.type); @@ -2452,7 +2452,7 @@ static int dvb_register(struct cx23885_tsport *port) si2157_config.if_port = 1; si2157_config.inversion = 1; memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2157", I2C_NAME_SIZE); + strscpy(info.type, "si2157", I2C_NAME_SIZE); info.addr = 0x60; info.platform_data = &si2157_config; request_module("%s", info.type); @@ -2488,7 +2488,7 @@ static int dvb_register(struct cx23885_tsport *port) si2157_config.if_port = 1; si2157_config.inversion = 1; memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2157", I2C_NAME_SIZE); + strscpy(info.type, "si2157", I2C_NAME_SIZE); info.addr = 0x62; info.platform_data = &si2157_config; request_module("%s", info.type); @@ -2528,7 +2528,7 @@ static int dvb_register(struct cx23885_tsport *port) si2157_config.if_port = 1; si2157_config.inversion = 1; memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2157", I2C_NAME_SIZE); + strscpy(info.type, "si2157", I2C_NAME_SIZE); info.addr = 0x60; info.platform_data = &si2157_config; request_module("%s", info.type); diff --git a/drivers/media/pci/cx23885/cx23885-i2c.c b/drivers/media/pci/cx23885/cx23885-i2c.c index ef863492c0ac..d0df3dfff694 100644 --- a/drivers/media/pci/cx23885/cx23885-i2c.c +++ b/drivers/media/pci/cx23885/cx23885-i2c.c @@ -317,7 +317,7 @@ int cx23885_i2c_register(struct cx23885_i2c *bus) bus->i2c_client = cx23885_i2c_client_template; bus->i2c_adap.dev.parent = &dev->pci->dev; - strlcpy(bus->i2c_adap.name, bus->dev->name, + strscpy(bus->i2c_adap.name, bus->dev->name, sizeof(bus->i2c_adap.name)); bus->i2c_adap.algo_data = bus; @@ -340,12 +340,12 @@ int cx23885_i2c_register(struct cx23885_i2c *bus) /* Instantiate the IR receiver device, if present */ if (0 == bus->i2c_rc) { struct i2c_board_info info; - const unsigned short addr_list[] = { + static const unsigned short addr_list[] = { 0x6b, I2C_CLIENT_END }; memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "ir_video", I2C_NAME_SIZE); + strscpy(info.type, "ir_video", I2C_NAME_SIZE); /* Use quick read command for probe, some IR chips don't * support writes */ i2c_new_probed_device(&bus->i2c_adap, &info, addr_list, diff --git a/drivers/media/pci/cx23885/cx23885-ioctl.c b/drivers/media/pci/cx23885/cx23885-ioctl.c index d2cdd40f79f5..d162bf4b4800 100644 --- a/drivers/media/pci/cx23885/cx23885-ioctl.c +++ b/drivers/media/pci/cx23885/cx23885-ioctl.c @@ -31,9 +31,9 @@ int cx23885_g_chip_info(struct file *file, void *fh, if (chip->match.addr == 1) { if (dev->v4l_device == NULL) return -EINVAL; - strlcpy(chip->name, "cx23417", sizeof(chip->name)); + strscpy(chip->name, "cx23417", sizeof(chip->name)); } else { - strlcpy(chip->name, dev->v4l2_dev.name, sizeof(chip->name)); + strscpy(chip->name, dev->v4l2_dev.name, sizeof(chip->name)); } return 0; } diff --git a/drivers/media/pci/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c index f8a3deadc77a..92d32a733f1b 100644 --- a/drivers/media/pci/cx23885/cx23885-video.c +++ b/drivers/media/pci/cx23885/cx23885-video.c @@ -639,8 +639,8 @@ static int vidioc_querycap(struct file *file, void *priv, struct cx23885_dev *dev = video_drvdata(file); struct video_device *vdev = video_devdata(file); - strcpy(cap->driver, "cx23885"); - strlcpy(cap->card, cx23885_boards[dev->board].name, + strscpy(cap->driver, "cx23885", sizeof(cap->driver)); + strscpy(cap->card, cx23885_boards[dev->board].name, sizeof(cap->card)); sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci)); cap->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | V4L2_CAP_AUDIO; @@ -661,7 +661,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, if (unlikely(f->index >= ARRAY_SIZE(formats))) return -EINVAL; - strlcpy(f->description, formats[f->index].name, + strscpy(f->description, formats[f->index].name, sizeof(f->description)); f->pixelformat = formats[f->index].fourcc; @@ -731,7 +731,7 @@ int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i) i->index = n; i->type = V4L2_INPUT_TYPE_CAMERA; - strcpy(i->name, iname[INPUT(n)->type]); + strscpy(i->name, iname[INPUT(n)->type], sizeof(i->name)); i->std = CX23885_NORMS; if ((CX23885_VMUX_TELEVISION == INPUT(n)->type) || (CX23885_VMUX_CABLE == INPUT(n)->type)) { @@ -828,7 +828,7 @@ static int cx23885_query_audinput(struct file *file, void *priv, memset(i, 0, sizeof(*i)); i->index = n; - strcpy(i->name, iname[n]); + strscpy(i->name, iname[n], sizeof(i->name)); i->capability = V4L2_AUDCAP_STEREO; return 0; @@ -887,7 +887,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, if (0 != t->index) return -EINVAL; - strcpy(t->name, "Television"); + strscpy(t->name, "Television", sizeof(t->name)); call_all(dev, tuner, g_tuner, t); return 0; @@ -1186,7 +1186,8 @@ int cx23885_video_register(struct cx23885_dev *dev) /* Initialize VBI template */ cx23885_vbi_template = cx23885_video_template; - strcpy(cx23885_vbi_template.name, "cx23885-vbi"); + strscpy(cx23885_vbi_template.name, "cx23885-vbi", + sizeof(cx23885_vbi_template.name)); dev->tvnorm = V4L2_STD_NTSC_M; dev->fmt = format_by_fourcc(V4L2_PIX_FMT_YUYV); diff --git a/drivers/media/pci/cx23885/cx23888-ir.c b/drivers/media/pci/cx23885/cx23888-ir.c index 00329f668b59..1d775c90df51 100644 --- a/drivers/media/pci/cx23885/cx23888-ir.c +++ b/drivers/media/pci/cx23885/cx23888-ir.c @@ -696,10 +696,8 @@ static int cx23888_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count, if (v > IR_MAX_DURATION) v = IR_MAX_DURATION; - init_ir_raw_event(&p->ir_core_data); - p->ir_core_data.pulse = u; - p->ir_core_data.duration = v; - p->ir_core_data.timeout = w; + p->ir_core_data = (struct ir_raw_event) + { .pulse = u, .duration = v, .timeout = w }; v4l2_dbg(2, ir_888_debug, sd, "rx read: %10u ns %s %s\n", v, u ? "mark" : "space", w ? "(timed out)" : ""); diff --git a/drivers/media/pci/cx25821/cx25821-alsa.c b/drivers/media/pci/cx25821/cx25821-alsa.c index ef6380651c10..0a6c90e92557 100644 --- a/drivers/media/pci/cx25821/cx25821-alsa.c +++ b/drivers/media/pci/cx25821/cx25821-alsa.c @@ -674,7 +674,7 @@ static int snd_cx25821_pcm(struct cx25821_audio_dev *chip, int device, } pcm->private_data = chip; pcm->info_flags = 0; - strcpy(pcm->name, name); + strscpy(pcm->name, name, sizeof(pcm->name)); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx25821_pcm_ops); return 0; @@ -725,7 +725,7 @@ static int cx25821_audio_initdev(struct cx25821_dev *dev) return err; } - strcpy(card->driver, "cx25821"); + strscpy(card->driver, "cx25821", sizeof(card->driver)); /* Card "creation" */ chip = card->private_data; @@ -754,10 +754,10 @@ static int cx25821_audio_initdev(struct cx25821_dev *dev) goto error; } - strcpy(card->shortname, "cx25821"); + strscpy(card->shortname, "cx25821", sizeof(card->shortname)); sprintf(card->longname, "%s at 0x%lx irq %d", chip->dev->name, chip->iobase, chip->irq); - strcpy(card->mixername, "CX25821"); + strscpy(card->mixername, "CX25821", sizeof(card->mixername)); pr_info("%s/%i: ALSA support for cx25821 boards\n", card->driver, devno); diff --git a/drivers/media/pci/cx25821/cx25821-i2c.c b/drivers/media/pci/cx25821/cx25821-i2c.c index 31479a41f359..67d2f7610011 100644 --- a/drivers/media/pci/cx25821/cx25821-i2c.c +++ b/drivers/media/pci/cx25821/cx25821-i2c.c @@ -306,7 +306,7 @@ int cx25821_i2c_register(struct cx25821_i2c *bus) bus->i2c_client = cx25821_i2c_client_template; bus->i2c_adap.dev.parent = &dev->pci->dev; - strlcpy(bus->i2c_adap.name, bus->dev->name, sizeof(bus->i2c_adap.name)); + strscpy(bus->i2c_adap.name, bus->dev->name, sizeof(bus->i2c_adap.name)); bus->i2c_adap.algo_data = bus; i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev); diff --git a/drivers/media/pci/cx25821/cx25821-video.c b/drivers/media/pci/cx25821/cx25821-video.c index dbaf42ec26cd..3d23c2e64102 100644 --- a/drivers/media/pci/cx25821/cx25821-video.c +++ b/drivers/media/pci/cx25821/cx25821-video.c @@ -322,7 +322,7 @@ static int cx25821_vidioc_enum_fmt_vid_cap(struct file *file, void *priv, if (unlikely(f->index >= ARRAY_SIZE(formats))) return -EINVAL; - strlcpy(f->description, formats[f->index].name, sizeof(f->description)); + strscpy(f->description, formats[f->index].name, sizeof(f->description)); f->pixelformat = formats[f->index].fourcc; return 0; @@ -441,8 +441,8 @@ static int cx25821_vidioc_querycap(struct file *file, void *priv, V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; const u32 cap_output = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_READWRITE; - strcpy(cap->driver, "cx25821"); - strlcpy(cap->card, cx25821_boards[dev->board].name, sizeof(cap->card)); + strscpy(cap->driver, "cx25821", sizeof(cap->driver)); + strscpy(cap->card, cx25821_boards[dev->board].name, sizeof(cap->card)); sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci)); if (chan->id >= VID_CHANNEL_NUM) cap->device_caps = cap_output; @@ -486,7 +486,7 @@ static int cx25821_vidioc_enum_input(struct file *file, void *priv, i->type = V4L2_INPUT_TYPE_CAMERA; i->std = CX25821_NORMS; - strcpy(i->name, "Composite"); + strscpy(i->name, "Composite", sizeof(i->name)); return 0; } @@ -534,7 +534,7 @@ static int cx25821_vidioc_enum_output(struct file *file, void *priv, o->type = V4L2_INPUT_TYPE_CAMERA; o->std = CX25821_NORMS; - strcpy(o->name, "Composite"); + strscpy(o->name, "Composite", sizeof(o->name)); return 0; } diff --git a/drivers/media/pci/cx88/cx88-alsa.c b/drivers/media/pci/cx88/cx88-alsa.c index 89a65478ae36..b683cbe13dee 100644 --- a/drivers/media/pci/cx88/cx88-alsa.c +++ b/drivers/media/pci/cx88/cx88-alsa.c @@ -616,7 +616,7 @@ static int snd_cx88_pcm(struct cx88_audio_dev *chip, int device, if (err < 0) return err; pcm->private_data = chip; - strcpy(pcm->name, name); + strscpy(pcm->name, name, sizeof(pcm->name)); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx88_pcm_ops); return 0; @@ -968,12 +968,12 @@ static int cx88_audio_initdev(struct pci_dev *pci, goto error; } - strcpy(card->driver, "CX88x"); + strscpy(card->driver, "CX88x", sizeof(card->driver)); sprintf(card->shortname, "Conexant CX%x", pci->device); sprintf(card->longname, "%s at %#llx", card->shortname, (unsigned long long)pci_resource_start(pci, 0)); - strcpy(card->mixername, "CX88"); + strscpy(card->mixername, "CX88", sizeof(card->mixername)); dprintk(0, "%s/%i: ALSA support for cx2388x boards\n", card->driver, devno); diff --git a/drivers/media/pci/cx88/cx88-blackbird.c b/drivers/media/pci/cx88/cx88-blackbird.c index 7a4876cf9f08..199756547f03 100644 --- a/drivers/media/pci/cx88/cx88-blackbird.c +++ b/drivers/media/pci/cx88/cx88-blackbird.c @@ -803,7 +803,7 @@ static int vidioc_querycap(struct file *file, void *priv, struct cx8802_dev *dev = video_drvdata(file); struct cx88_core *core = dev->core; - strcpy(cap->driver, "cx88_blackbird"); + strscpy(cap->driver, "cx88_blackbird", sizeof(cap->driver)); sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci)); return cx88_querycap(file, core, cap); } @@ -814,7 +814,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, if (f->index != 0) return -EINVAL; - strlcpy(f->description, "MPEG", sizeof(f->description)); + strscpy(f->description, "MPEG", sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_MPEG; f->flags = V4L2_FMT_FLAG_COMPRESSED; return 0; @@ -995,7 +995,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, if (t->index != 0) return -EINVAL; - strcpy(t->name, "Television"); + strscpy(t->name, "Television", sizeof(t->name)); t->capability = V4L2_TUNER_CAP_NORM; t->rangehigh = 0xffffffffUL; call_all(core, tuner, g_tuner, t); diff --git a/drivers/media/pci/cx88/cx88-cards.c b/drivers/media/pci/cx88/cx88-cards.c index 07e1483e987d..382af90fd4a9 100644 --- a/drivers/media/pci/cx88/cx88-cards.c +++ b/drivers/media/pci/cx88/cx88-cards.c @@ -3693,7 +3693,7 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) core->height = 240; core->field = V4L2_FIELD_INTERLACED; - strcpy(core->v4l2_dev.name, core->name); + strscpy(core->v4l2_dev.name, core->name, sizeof(core->v4l2_dev.name)); if (v4l2_device_register(NULL, &core->v4l2_dev)) { kfree(core); return NULL; diff --git a/drivers/media/pci/cx88/cx88-i2c.c b/drivers/media/pci/cx88/cx88-i2c.c index 99f88a05a7c9..48be0b0ad680 100644 --- a/drivers/media/pci/cx88/cx88-i2c.c +++ b/drivers/media/pci/cx88/cx88-i2c.c @@ -140,14 +140,14 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) core->i2c_algo = cx8800_i2c_algo_template; core->i2c_adap.dev.parent = &pci->dev; - strlcpy(core->i2c_adap.name, core->name, sizeof(core->i2c_adap.name)); + strscpy(core->i2c_adap.name, core->name, sizeof(core->i2c_adap.name)); core->i2c_adap.owner = THIS_MODULE; core->i2c_algo.udelay = i2c_udelay; core->i2c_algo.data = core; i2c_set_adapdata(&core->i2c_adap, &core->v4l2_dev); core->i2c_adap.algo_data = &core->i2c_algo; core->i2c_client.adapter = &core->i2c_adap; - strlcpy(core->i2c_client.name, "cx88xx internal", I2C_NAME_SIZE); + strscpy(core->i2c_client.name, "cx88xx internal", I2C_NAME_SIZE); cx8800_bit_setscl(core, 1); cx8800_bit_setsda(core, 1); diff --git a/drivers/media/pci/cx88/cx88-input.c b/drivers/media/pci/cx88/cx88-input.c index 2f5debce4905..ca76da04b476 100644 --- a/drivers/media/pci/cx88/cx88-input.c +++ b/drivers/media/pci/cx88/cx88-input.c @@ -535,7 +535,7 @@ void cx88_ir_irq(struct cx88_core *core) struct cx88_IR *ir = core->ir; u32 samples; unsigned int todo, bits; - struct ir_raw_event ev; + struct ir_raw_event ev = {}; if (!ir || !ir->sampling) return; @@ -550,7 +550,6 @@ void cx88_ir_irq(struct cx88_core *core) if (samples == 0xff && ir->dev->idle) return; - init_ir_raw_event(&ev); for (todo = 32; todo > 0; todo -= bits) { ev.pulse = samples & 0x80000000 ? false : true; bits = min(todo, 32U - fls(ev.pulse ? samples : ~samples)); @@ -610,7 +609,7 @@ void cx88_i2c_init_ir(struct cx88_core *core) return; memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "ir_video", I2C_NAME_SIZE); + strscpy(info.type, "ir_video", I2C_NAME_SIZE); switch (core->boardnr) { case CX88_BOARD_LEADTEK_PVR2000: @@ -635,7 +634,7 @@ void cx88_i2c_init_ir(struct cx88_core *core) if (*addrp == 0x71) { /* Hauppauge Z8F0811 */ - strlcpy(info.type, "ir_z8f0811_haup", I2C_NAME_SIZE); + strscpy(info.type, "ir_z8f0811_haup", I2C_NAME_SIZE); core->init_data.name = core->board.name; core->init_data.ir_codes = RC_MAP_HAUPPAUGE; core->init_data.type = RC_PROTO_BIT_RC5 | diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c index 7b113bad70d2..df4e7a0686e0 100644 --- a/drivers/media/pci/cx88/cx88-video.c +++ b/drivers/media/pci/cx88/cx88-video.c @@ -811,7 +811,7 @@ int cx88_querycap(struct file *file, struct cx88_core *core, { struct video_device *vdev = video_devdata(file); - strlcpy(cap->card, core->board.name, sizeof(cap->card)); + strscpy(cap->card, core->board.name, sizeof(cap->card)); cap->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; if (core->board.tuner_type != UNSET) cap->device_caps |= V4L2_CAP_TUNER; @@ -842,7 +842,7 @@ static int vidioc_querycap(struct file *file, void *priv, struct cx8800_dev *dev = video_drvdata(file); struct cx88_core *core = dev->core; - strcpy(cap->driver, "cx8800"); + strscpy(cap->driver, "cx8800", sizeof(cap->driver)); sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci)); return cx88_querycap(file, core, cap); } @@ -853,7 +853,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, if (unlikely(f->index >= ARRAY_SIZE(formats))) return -EINVAL; - strlcpy(f->description, formats[f->index].name, sizeof(f->description)); + strscpy(f->description, formats[f->index].name, sizeof(f->description)); f->pixelformat = formats[f->index].fourcc; return 0; @@ -897,7 +897,7 @@ int cx88_enum_input(struct cx88_core *core, struct v4l2_input *i) if (!INPUT(n).type) return -EINVAL; i->type = V4L2_INPUT_TYPE_CAMERA; - strcpy(i->name, iname[INPUT(n).type]); + strscpy(i->name, iname[INPUT(n).type], sizeof(i->name)); if ((INPUT(n).type == CX88_VMUX_TELEVISION) || (INPUT(n).type == CX88_VMUX_CABLE)) i->type = V4L2_INPUT_TYPE_TUNER; @@ -952,7 +952,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, if (t->index != 0) return -EINVAL; - strcpy(t->name, "Television"); + strscpy(t->name, "Television", sizeof(t->name)); t->capability = V4L2_TUNER_CAP_NORM; t->rangehigh = 0xffffffffUL; call_all(core, tuner, g_tuner, t); @@ -1065,7 +1065,7 @@ static int radio_g_tuner(struct file *file, void *priv, if (unlikely(t->index > 0)) return -EINVAL; - strcpy(t->name, "Radio"); + strscpy(t->name, "Radio", sizeof(t->name)); call_all(core, tuner, g_tuner, t); return 0; diff --git a/drivers/media/pci/cx88/cx88-vp3054-i2c.c b/drivers/media/pci/cx88/cx88-vp3054-i2c.c index 92876de3841c..e4db636e9fad 100644 --- a/drivers/media/pci/cx88/cx88-vp3054-i2c.c +++ b/drivers/media/pci/cx88/cx88-vp3054-i2c.c @@ -114,7 +114,7 @@ int vp3054_i2c_probe(struct cx8802_dev *dev) vp3054_i2c->algo = vp3054_i2c_algo_template; vp3054_i2c->adap.dev.parent = &dev->pci->dev; - strlcpy(vp3054_i2c->adap.name, core->name, + strscpy(vp3054_i2c->adap.name, core->name, sizeof(vp3054_i2c->adap.name)); vp3054_i2c->adap.owner = THIS_MODULE; vp3054_i2c->algo.data = dev; diff --git a/drivers/media/pci/ddbridge/ddbridge-ci.c b/drivers/media/pci/ddbridge/ddbridge-ci.c index cfe23d02e561..377991095aba 100644 --- a/drivers/media/pci/ddbridge/ddbridge-ci.c +++ b/drivers/media/pci/ddbridge/ddbridge-ci.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * ddbridge-ci.c: Digital Devices bridge CI (DuoFlex, CI Bridge) support * @@ -13,9 +14,6 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * - * To obtain the license, point your browser to - * http://www.gnu.org/copyleft/gpl.html */ #include "ddbridge.h" diff --git a/drivers/media/pci/ddbridge/ddbridge-ci.h b/drivers/media/pci/ddbridge/ddbridge-ci.h index 35a39182dd83..cc98656af349 100644 --- a/drivers/media/pci/ddbridge/ddbridge-ci.h +++ b/drivers/media/pci/ddbridge/ddbridge-ci.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * ddbridge-ci.h: Digital Devices bridge CI (DuoFlex, CI Bridge) support * @@ -13,9 +14,6 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * - * To obtain the license, point your browser to - * http://www.gnu.org/copyleft/gpl.html */ #ifndef __DDBRIDGE_CI_H__ diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c index c1b982e8e6c9..7a2d19682fe3 100644 --- a/drivers/media/pci/ddbridge/ddbridge-core.c +++ b/drivers/media/pci/ddbridge/ddbridge-core.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * ddbridge-core.c: Digital Devices bridge core functions * @@ -5,19 +6,14 @@ * Marcus Metzler <mocm@metzlerbros.de> * Ralph Metzler <rjkm@metzlerbros.de> * - * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 only, as published by the Free Software Foundation. * - * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * - * To obtain the license, point your browser to - * http://www.gnu.org/copyleft/gpl.html */ #include <linux/module.h> diff --git a/drivers/media/pci/ddbridge/ddbridge-hw.c b/drivers/media/pci/ddbridge/ddbridge-hw.c index f3cbac07b41f..f9c91bdbd041 100644 --- a/drivers/media/pci/ddbridge/ddbridge-hw.c +++ b/drivers/media/pci/ddbridge/ddbridge-hw.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * ddbridge-hw.c: Digital Devices bridge hardware maps * @@ -13,7 +14,6 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * */ #include "ddbridge.h" diff --git a/drivers/media/pci/ddbridge/ddbridge-hw.h b/drivers/media/pci/ddbridge/ddbridge-hw.h index 7c142419419c..e34bd94c266b 100644 --- a/drivers/media/pci/ddbridge/ddbridge-hw.h +++ b/drivers/media/pci/ddbridge/ddbridge-hw.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * ddbridge-hw.h: Digital Devices bridge hardware maps * @@ -13,7 +14,6 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * */ #ifndef _DDBRIDGE_HW_H_ diff --git a/drivers/media/pci/ddbridge/ddbridge-i2c.c b/drivers/media/pci/ddbridge/ddbridge-i2c.c index 5a28d7611713..aafa6030c8cc 100644 --- a/drivers/media/pci/ddbridge/ddbridge-i2c.c +++ b/drivers/media/pci/ddbridge/ddbridge-i2c.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * ddbridge-i2c.c: Digital Devices bridge i2c driver * @@ -13,7 +14,6 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * */ #include <linux/module.h> diff --git a/drivers/media/pci/ddbridge/ddbridge-i2c.h b/drivers/media/pci/ddbridge/ddbridge-i2c.h index 7ed220506c05..90830f7b1638 100644 --- a/drivers/media/pci/ddbridge/ddbridge-i2c.h +++ b/drivers/media/pci/ddbridge/ddbridge-i2c.h @@ -1,5 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* - * ddbridge-i2c.c: Digital Devices bridge i2c driver + * ddbridge-i2c.h: Digital Devices bridge i2c driver * * Copyright (C) 2010-2017 Digital Devices GmbH * Ralph Metzler <rjkm@metzlerbros.de> @@ -13,7 +14,6 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * */ #ifndef __DDBRIDGE_I2C_H__ diff --git a/drivers/media/pci/ddbridge/ddbridge-io.h b/drivers/media/pci/ddbridge/ddbridge-io.h index b3646c04f1a7..1a5b31b52494 100644 --- a/drivers/media/pci/ddbridge/ddbridge-io.h +++ b/drivers/media/pci/ddbridge/ddbridge-io.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * ddbridge-io.h: Digital Devices bridge I/O inline functions * @@ -13,7 +14,6 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * */ #ifndef __DDBRIDGE_IO_H__ diff --git a/drivers/media/pci/ddbridge/ddbridge-main.c b/drivers/media/pci/ddbridge/ddbridge-main.c index f4748cfd904b..03dc9924fa2c 100644 --- a/drivers/media/pci/ddbridge/ddbridge-main.c +++ b/drivers/media/pci/ddbridge/ddbridge-main.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * ddbridge.c: Digital Devices PCIe bridge driver * @@ -13,7 +14,6 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -318,5 +318,5 @@ module_exit(module_exit_ddbridge); MODULE_DESCRIPTION("Digital Devices PCIe Bridge"); MODULE_AUTHOR("Ralph and Marcus Metzler, Metzler Brothers Systementwicklung GbR"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); MODULE_VERSION(DDBRIDGE_VERSION); diff --git a/drivers/media/pci/ddbridge/ddbridge-max.c b/drivers/media/pci/ddbridge/ddbridge-max.c index 8da1c7b91577..576dd2318e4d 100644 --- a/drivers/media/pci/ddbridge/ddbridge-max.c +++ b/drivers/media/pci/ddbridge/ddbridge-max.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * ddbridge-max.c: Digital Devices bridge MAX card support * @@ -13,7 +14,6 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * */ #include <linux/module.h> diff --git a/drivers/media/pci/ddbridge/ddbridge-max.h b/drivers/media/pci/ddbridge/ddbridge-max.h index 9838c73973b6..6543dfc77138 100644 --- a/drivers/media/pci/ddbridge/ddbridge-max.h +++ b/drivers/media/pci/ddbridge/ddbridge-max.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * ddbridge-max.h: Digital Devices bridge MAX card support * @@ -13,7 +14,6 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * */ #ifndef _DDBRIDGE_MAX_H_ diff --git a/drivers/media/pci/ddbridge/ddbridge-regs.h b/drivers/media/pci/ddbridge/ddbridge-regs.h index f9e1cbb99b53..2942a7f35099 100644 --- a/drivers/media/pci/ddbridge/ddbridge-regs.h +++ b/drivers/media/pci/ddbridge/ddbridge-regs.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * ddbridge-regs.h: Digital Devices PCIe bridge driver * @@ -7,14 +8,10 @@ * modify it under the terms of the GNU General Public License * version 2 only, as published by the Free Software Foundation. * - * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * - * To obtain the license, point your browser to - * http://www.gnu.org/copyleft/gpl.html */ #ifndef __DDBRIDGE_REGS_H__ diff --git a/drivers/media/pci/ddbridge/ddbridge-sx8.c b/drivers/media/pci/ddbridge/ddbridge-sx8.c index 64f05f5ee039..374fcee94960 100644 --- a/drivers/media/pci/ddbridge/ddbridge-sx8.c +++ b/drivers/media/pci/ddbridge/ddbridge-sx8.c @@ -398,9 +398,7 @@ static int set_parameters(struct dvb_frontend *fe) } stat = start(fe, 3, mask, ts_config); } else { - u32 flags = (iq_mode == 2) ? 1 : 0; - - stat = start_iq(fe, flags, 4, ts_config); + stat = start_iq(fe, 0, 4, ts_config); } if (!stat) { state->started = 1; diff --git a/drivers/media/pci/ddbridge/ddbridge.h b/drivers/media/pci/ddbridge/ddbridge.h index 8a354dfb6c22..f137155bf79e 100644 --- a/drivers/media/pci/ddbridge/ddbridge.h +++ b/drivers/media/pci/ddbridge/ddbridge.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * ddbridge.h: Digital Devices PCIe bridge driver * @@ -8,14 +9,10 @@ * modify it under the terms of the GNU General Public License * version 2 only, as published by the Free Software Foundation. * - * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * - * To obtain the license, point your browser to - * http://www.gnu.org/copyleft/gpl.html */ #ifndef _DDBRIDGE_H_ diff --git a/drivers/media/pci/dm1105/dm1105.c b/drivers/media/pci/dm1105/dm1105.c index 1ddb0576fb7b..a84c8270ea13 100644 --- a/drivers/media/pci/dm1105/dm1105.c +++ b/drivers/media/pci/dm1105/dm1105.c @@ -1046,7 +1046,7 @@ static int dm1105_probe(struct pci_dev *pdev, /* i2c */ i2c_set_adapdata(&dev->i2c_adap, dev); - strcpy(dev->i2c_adap.name, DRIVER_NAME); + strscpy(dev->i2c_adap.name, DRIVER_NAME, sizeof(dev->i2c_adap.name)); dev->i2c_adap.owner = THIS_MODULE; dev->i2c_adap.dev.parent = &pdev->dev; dev->i2c_adap.algo = &dm1105_algo; @@ -1057,7 +1057,8 @@ static int dm1105_probe(struct pci_dev *pdev, goto err_dm1105_hw_exit; i2c_set_adapdata(&dev->i2c_bb_adap, dev); - strcpy(dev->i2c_bb_adap.name, DM1105_I2C_GPIO_NAME); + strscpy(dev->i2c_bb_adap.name, DM1105_I2C_GPIO_NAME, + sizeof(dev->i2c_bb_adap.name)); dev->i2c_bb_adap.owner = THIS_MODULE; dev->i2c_bb_adap.dev.parent = &pdev->dev; dev->i2c_bb_adap.algo_data = &dev->i2c_bit; diff --git a/drivers/media/pci/dt3155/dt3155.c b/drivers/media/pci/dt3155/dt3155.c index 1775c36891ae..17d69bd5d7f1 100644 --- a/drivers/media/pci/dt3155/dt3155.c +++ b/drivers/media/pci/dt3155/dt3155.c @@ -307,8 +307,8 @@ static int dt3155_querycap(struct file *filp, void *p, { struct dt3155_priv *pd = video_drvdata(filp); - strcpy(cap->driver, DT3155_NAME); - strcpy(cap->card, DT3155_NAME " frame grabber"); + strscpy(cap->driver, DT3155_NAME, sizeof(cap->driver)); + strscpy(cap->card, DT3155_NAME " frame grabber", sizeof(cap->card)); sprintf(cap->bus_info, "PCI:%s", pci_name(pd->pdev)); cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | V4L2_CAP_READWRITE; @@ -322,7 +322,7 @@ static int dt3155_enum_fmt_vid_cap(struct file *filp, if (f->index) return -EINVAL; f->pixelformat = V4L2_PIX_FMT_GREY; - strcpy(f->description, "8-bit Greyscale"); + strscpy(f->description, "8-bit Greyscale", sizeof(f->description)); return 0; } @@ -378,7 +378,7 @@ static int dt3155_enum_input(struct file *filp, void *p, snprintf(input->name, sizeof(input->name), "VID%d", input->index); else - strlcpy(input->name, "J2/VID0", sizeof(input->name)); + strscpy(input->name, "J2/VID0", sizeof(input->name)); input->type = V4L2_INPUT_TYPE_CAMERA; input->std = V4L2_STD_ALL; input->status = 0; diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2.c index 29027159eced..452eb9b42140 100644 --- a/drivers/media/pci/intel/ipu3/ipu3-cio2.c +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.c @@ -218,13 +218,11 @@ static int cio2_fbpt_init(struct cio2_device *cio2, struct cio2_queue *q) { struct device *dev = &cio2->pci_dev->dev; - q->fbpt = dma_alloc_coherent(dev, CIO2_FBPT_SIZE, &q->fbpt_bus_addr, - GFP_KERNEL); + q->fbpt = dma_zalloc_coherent(dev, CIO2_FBPT_SIZE, &q->fbpt_bus_addr, + GFP_KERNEL); if (!q->fbpt) return -ENOMEM; - memset(q->fbpt, 0, CIO2_FBPT_SIZE); - return 0; } @@ -1066,8 +1064,8 @@ static int cio2_v4l2_querycap(struct file *file, void *fh, { struct cio2_device *cio2 = video_drvdata(file); - strlcpy(cap->driver, CIO2_NAME, sizeof(cap->driver)); - strlcpy(cap->card, CIO2_DEVICE_NAME, sizeof(cap->card)); + strscpy(cap->driver, CIO2_NAME, sizeof(cap->driver)); + strscpy(cap->card, CIO2_DEVICE_NAME, sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", pci_name(cio2->pci_dev)); @@ -1145,7 +1143,7 @@ cio2_video_enum_input(struct file *file, void *fh, struct v4l2_input *input) if (input->index > 0) return -EINVAL; - strlcpy(input->name, "camera", sizeof(input->name)); + strscpy(input->name, "camera", sizeof(input->name)); input->type = V4L2_INPUT_TYPE_CAMERA; return 0; @@ -1435,13 +1433,13 @@ static int cio2_notifier_complete(struct v4l2_async_notifier *notifier) struct cio2_device *cio2 = container_of(notifier, struct cio2_device, notifier); struct sensor_async_subdev *s_asd; + struct v4l2_async_subdev *asd; struct cio2_queue *q; - unsigned int i, pad; + unsigned int pad; int ret; - for (i = 0; i < notifier->num_subdevs; i++) { - s_asd = container_of(cio2->notifier.subdevs[i], - struct sensor_async_subdev, asd); + list_for_each_entry(asd, &cio2->notifier.asd_list, asd_list) { + s_asd = container_of(asd, struct sensor_async_subdev, asd); q = &cio2->queue[s_asd->csi2.port]; for (pad = 0; pad < q->sensor->entity.num_pads; pad++) @@ -1463,7 +1461,7 @@ static int cio2_notifier_complete(struct v4l2_async_notifier *notifier) if (ret) { dev_err(&cio2->pci_dev->dev, "failed to create link for %s\n", - cio2->queue[i].sensor->name); + q->sensor->name); return ret; } } @@ -1484,7 +1482,7 @@ static int cio2_fwnode_parse(struct device *dev, struct sensor_async_subdev *s_asd = container_of(asd, struct sensor_async_subdev, asd); - if (vep->bus_type != V4L2_MBUS_CSI2) { + if (vep->bus_type != V4L2_MBUS_CSI2_DPHY) { dev_err(dev, "Only CSI2 bus type is currently supported\n"); return -EINVAL; } @@ -1499,6 +1497,8 @@ static int cio2_notifier_init(struct cio2_device *cio2) { int ret; + v4l2_async_notifier_init(&cio2->notifier); + ret = v4l2_async_notifier_parse_fwnode_endpoints( &cio2->pci_dev->dev, &cio2->notifier, sizeof(struct sensor_async_subdev), @@ -1506,7 +1506,7 @@ static int cio2_notifier_init(struct cio2_device *cio2) if (ret < 0) return ret; - if (!cio2->notifier.num_subdevs) + if (list_empty(&cio2->notifier.asd_list)) return -ENODEV; /* no endpoint */ cio2->notifier.ops = &cio2_async_ops; @@ -1785,7 +1785,7 @@ static int cio2_pci_probe(struct pci_dev *pci_dev, mutex_init(&cio2->lock); cio2->media_dev.dev = &cio2->pci_dev->dev; - strlcpy(cio2->media_dev.model, CIO2_DEVICE_NAME, + strscpy(cio2->media_dev.model, CIO2_DEVICE_NAME, sizeof(cio2->media_dev.model)); snprintf(cio2->media_dev.bus_info, sizeof(cio2->media_dev.bus_info), "PCI:%s", pci_name(cio2->pci_dev)); diff --git a/drivers/media/pci/ivtv/ivtv-alsa-main.c b/drivers/media/pci/ivtv/ivtv-alsa-main.c index c1856f609d2c..0de8a9f5011a 100644 --- a/drivers/media/pci/ivtv/ivtv-alsa-main.c +++ b/drivers/media/pci/ivtv/ivtv-alsa-main.c @@ -109,7 +109,7 @@ static int snd_ivtv_card_set_names(struct snd_ivtv_card *itvsc) struct snd_card *sc = itvsc->sc; /* sc->driver is used by alsa-lib's configurator: simple, unique */ - strlcpy(sc->driver, "CX2341[56]", sizeof(sc->driver)); + strscpy(sc->driver, "CX2341[56]", sizeof(sc->driver)); /* sc->shortname is a symlink in /proc/asound: IVTV-M -> cardN */ snprintf(sc->shortname, sizeof(sc->shortname), "IVTV-%d", diff --git a/drivers/media/pci/ivtv/ivtv-alsa-pcm.c b/drivers/media/pci/ivtv/ivtv-alsa-pcm.c index 5326d86fa375..737c52de7558 100644 --- a/drivers/media/pci/ivtv/ivtv-alsa-pcm.c +++ b/drivers/media/pci/ivtv/ivtv-alsa-pcm.c @@ -350,7 +350,7 @@ int snd_ivtv_pcm_create(struct snd_ivtv_card *itvsc) &snd_ivtv_pcm_capture_ops); sp->info_flags = 0; sp->private_data = itvsc; - strlcpy(sp->name, itv->card_name, sizeof(sp->name)); + strscpy(sp->name, itv->card_name, sizeof(sp->name)); return 0; diff --git a/drivers/media/pci/ivtv/ivtv-cards.c b/drivers/media/pci/ivtv/ivtv-cards.c index c63792964a03..4ff46a6d0503 100644 --- a/drivers/media/pci/ivtv/ivtv-cards.c +++ b/drivers/media/pci/ivtv/ivtv-cards.c @@ -1317,8 +1317,8 @@ int ivtv_get_input(struct ivtv *itv, u16 index, struct v4l2_input *input) if (index >= itv->nof_inputs) return -EINVAL; input->index = index; - strlcpy(input->name, input_strs[card_input->video_type - 1], - sizeof(input->name)); + strscpy(input->name, input_strs[card_input->video_type - 1], + sizeof(input->name)); input->type = (card_input->video_type == IVTV_CARD_INPUT_VID_TUNER ? V4L2_INPUT_TYPE_TUNER : V4L2_INPUT_TYPE_CAMERA); input->audioset = (1 << itv->nof_audio_inputs) - 1; @@ -1334,7 +1334,7 @@ int ivtv_get_output(struct ivtv *itv, u16 index, struct v4l2_output *output) if (index >= itv->card->nof_outputs) return -EINVAL; output->index = index; - strlcpy(output->name, card_output->name, sizeof(output->name)); + strscpy(output->name, card_output->name, sizeof(output->name)); output->type = V4L2_OUTPUT_TYPE_ANALOG; output->audioset = 1; output->std = V4L2_STD_ALL; @@ -1353,8 +1353,8 @@ int ivtv_get_audio_input(struct ivtv *itv, u16 index, struct v4l2_audio *audio) memset(audio, 0, sizeof(*audio)); if (index >= itv->nof_audio_inputs) return -EINVAL; - strlcpy(audio->name, input_strs[aud_input->audio_type - 1], - sizeof(audio->name)); + strscpy(audio->name, input_strs[aud_input->audio_type - 1], + sizeof(audio->name)); audio->index = index; audio->capability = V4L2_AUDCAP_STEREO; return 0; @@ -1365,6 +1365,6 @@ int ivtv_get_audio_output(struct ivtv *itv, u16 index, struct v4l2_audioout *aud memset(aud_output, 0, sizeof(*aud_output)); if (itv->card->video_outputs == NULL || index != 0) return -EINVAL; - strlcpy(aud_output->name, "A/V Audio Out", sizeof(aud_output->name)); + strscpy(aud_output->name, "A/V Audio Out", sizeof(aud_output->name)); return 0; } diff --git a/drivers/media/pci/ivtv/ivtv-i2c.c b/drivers/media/pci/ivtv/ivtv-i2c.c index e9ce54dd5e01..55ef1385519e 100644 --- a/drivers/media/pci/ivtv/ivtv-i2c.c +++ b/drivers/media/pci/ivtv/ivtv-i2c.c @@ -218,7 +218,7 @@ static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr) memset(&info, 0, sizeof(struct i2c_board_info)); info.platform_data = init_data; - strlcpy(info.type, type, I2C_NAME_SIZE); + strscpy(info.type, type, I2C_NAME_SIZE); return i2c_new_probed_device(adap, &info, addr_list, NULL) == NULL ? -1 : 0; @@ -239,14 +239,14 @@ struct i2c_client *ivtv_i2c_new_ir_legacy(struct ivtv *itv) * allocations, so this function must be called after all other i2c * devices we care about are registered. */ - const unsigned short addr_list[] = { + static const unsigned short addr_list[] = { 0x1a, /* Hauppauge IR external - collides with WM8739 */ 0x18, /* Hauppauge IR internal */ I2C_CLIENT_END }; memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "ir_video", I2C_NAME_SIZE); + strscpy(info.type, "ir_video", I2C_NAME_SIZE); return i2c_new_probed_device(&itv->i2c_adap, &info, addr_list, NULL); } diff --git a/drivers/media/pci/ivtv/ivtv-ioctl.c b/drivers/media/pci/ivtv/ivtv-ioctl.c index 4cdc6d2be85d..a66f8b872520 100644 --- a/drivers/media/pci/ivtv/ivtv-ioctl.c +++ b/drivers/media/pci/ivtv/ivtv-ioctl.c @@ -36,6 +36,7 @@ #include <media/tveeprom.h> #include <media/v4l2-event.h> #ifdef CONFIG_VIDEO_IVTV_DEPRECATED_IOCTLS +#include <linux/compat.h> #include <linux/dvb/audio.h> #include <linux/dvb/video.h> #endif @@ -747,8 +748,8 @@ static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vc struct ivtv *itv = id->itv; struct ivtv_stream *s = &itv->streams[id->type]; - strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver)); - strlcpy(vcap->card, itv->card_name, sizeof(vcap->card)); + strscpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver)); + strscpy(vcap->card, itv->card_name, sizeof(vcap->card)); snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(itv->pdev)); vcap->capabilities = itv->v4l2_cap | V4L2_CAP_DEVICE_CAPS; vcap->device_caps = s->caps; @@ -1227,9 +1228,9 @@ static int ivtv_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) ivtv_call_all(itv, tuner, g_tuner, vt); if (vt->type == V4L2_TUNER_RADIO) - strlcpy(vt->name, "ivtv Radio Tuner", sizeof(vt->name)); + strscpy(vt->name, "ivtv Radio Tuner", sizeof(vt->name)); else - strlcpy(vt->name, "ivtv TV Tuner", sizeof(vt->name)); + strscpy(vt->name, "ivtv TV Tuner", sizeof(vt->name)); return 0; } @@ -1627,6 +1628,21 @@ static __inline__ void warn_deprecated_ioctl(const char *name) pr_warn_once("warning: the %s ioctl is deprecated. Don't use it, as it will be removed soon\n", name); } + +#ifdef CONFIG_COMPAT +struct compat_video_event { + __s32 type; + /* unused, make sure to use atomic time for y2038 if it ever gets used */ + compat_long_t timestamp; + union { + video_size_t size; + unsigned int frame_rate; /* in frames per 1000sec */ + unsigned char vsync_field; /* unknown/odd/even/progressive */ + } u; +}; +#define VIDEO_GET_EVENT32 _IOR('o', 28, struct compat_video_event) +#endif + #endif static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) @@ -1749,7 +1765,13 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) return ivtv_video_command(itv, id, dc, try); } +#ifdef CONFIG_COMPAT + case VIDEO_GET_EVENT32: +#endif case VIDEO_GET_EVENT: { +#ifdef CONFIG_COMPAT + struct compat_video_event *ev32 = arg; +#endif struct video_event *ev = arg; DEFINE_WAIT(wait); @@ -1763,14 +1785,22 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) if (test_and_clear_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags)) ev->type = VIDEO_EVENT_DECODER_STOPPED; else if (test_and_clear_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags)) { + unsigned char vsync_field; + ev->type = VIDEO_EVENT_VSYNC; - ev->u.vsync_field = test_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags) ? + vsync_field = test_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags) ? VIDEO_VSYNC_FIELD_ODD : VIDEO_VSYNC_FIELD_EVEN; if (itv->output_mode == OUT_UDMA_YUV && (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) == IVTV_YUV_MODE_PROGRESSIVE) { - ev->u.vsync_field = VIDEO_VSYNC_FIELD_PROGRESSIVE; + vsync_field = VIDEO_VSYNC_FIELD_PROGRESSIVE; } +#ifdef CONFIG_COMPAT + if (cmd == VIDEO_GET_EVENT32) + ev32->u.vsync_field = vsync_field; + else +#endif + ev->u.vsync_field = vsync_field; } if (ev->type) return 0; diff --git a/drivers/media/pci/ivtv/ivtv-streams.c b/drivers/media/pci/ivtv/ivtv-streams.c index d27c6df97566..a641f20e3f86 100644 --- a/drivers/media/pci/ivtv/ivtv-streams.c +++ b/drivers/media/pci/ivtv/ivtv-streams.c @@ -51,6 +51,9 @@ static const struct v4l2_file_operations ivtv_v4l2_enc_fops = { .write = ivtv_v4l2_write, .open = ivtv_v4l2_open, .unlocked_ioctl = video_ioctl2, +#ifdef CONFIG_COMPAT + .compat_ioctl32 = video_ioctl2, /* for ivtv_default() */ +#endif .release = ivtv_v4l2_close, .poll = ivtv_v4l2_enc_poll, }; @@ -61,6 +64,9 @@ static const struct v4l2_file_operations ivtv_v4l2_dec_fops = { .write = ivtv_v4l2_write, .open = ivtv_v4l2_open, .unlocked_ioctl = video_ioctl2, +#ifdef CONFIG_COMPAT + .compat_ioctl32 = video_ioctl2, /* for ivtv_default() */ +#endif .release = ivtv_v4l2_close, .poll = ivtv_v4l2_dec_poll, }; @@ -69,6 +75,9 @@ static const struct v4l2_file_operations ivtv_v4l2_radio_fops = { .owner = THIS_MODULE, .open = ivtv_v4l2_open, .unlocked_ioctl = video_ioctl2, +#ifdef CONFIG_COMPAT + .compat_ioctl32 = video_ioctl2, /* for ivtv_default() */ +#endif .release = ivtv_v4l2_close, .poll = ivtv_v4l2_enc_poll, }; diff --git a/drivers/media/pci/ivtv/ivtv-yuv.c b/drivers/media/pci/ivtv/ivtv-yuv.c index 44936d6d7c39..1380474519f2 100644 --- a/drivers/media/pci/ivtv/ivtv-yuv.c +++ b/drivers/media/pci/ivtv/ivtv-yuv.c @@ -935,7 +935,7 @@ static void ivtv_yuv_init(struct ivtv *itv) } /* We need a buffer for blanking when Y plane is offset - non-fatal if we can't get one */ - yi->blanking_ptr = kzalloc(720 * 16, GFP_KERNEL|__GFP_NOWARN); + yi->blanking_ptr = kzalloc(720 * 16, GFP_ATOMIC|__GFP_NOWARN); if (yi->blanking_ptr) { yi->blanking_dmaptr = pci_map_single(itv->pdev, yi->blanking_ptr, 720*16, PCI_DMA_TODEVICE); } else { diff --git a/drivers/media/pci/ivtv/ivtvfb.c b/drivers/media/pci/ivtv/ivtvfb.c index 5ddaa8ed11a5..3e02de02ffdd 100644 --- a/drivers/media/pci/ivtv/ivtvfb.c +++ b/drivers/media/pci/ivtv/ivtvfb.c @@ -624,7 +624,7 @@ static int ivtvfb_get_fix(struct ivtv *itv, struct fb_fix_screeninfo *fix) IVTVFB_DEBUG_INFO("ivtvfb_get_fix\n"); memset(fix, 0, sizeof(struct fb_fix_screeninfo)); - strlcpy(fix->id, "cx23415 TV out", sizeof(fix->id)); + strscpy(fix->id, "cx23415 TV out", sizeof(fix->id)); fix->smem_start = oi->video_pbase; fix->smem_len = oi->video_buffer_size; fix->type = FB_TYPE_PACKED_PIXELS; diff --git a/drivers/media/pci/meye/meye.c b/drivers/media/pci/meye/meye.c index 8001d3e9134e..bd870e60c32b 100644 --- a/drivers/media/pci/meye/meye.c +++ b/drivers/media/pci/meye/meye.c @@ -1019,8 +1019,8 @@ static int meyeioc_stilljcapt(int *len) static int vidioc_querycap(struct file *file, void *fh, struct v4l2_capability *cap) { - strcpy(cap->driver, "meye"); - strcpy(cap->card, "meye"); + strscpy(cap->driver, "meye", sizeof(cap->driver)); + strscpy(cap->card, "meye", sizeof(cap->card)); sprintf(cap->bus_info, "PCI:%s", pci_name(meye.mchip_dev)); cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | @@ -1035,7 +1035,7 @@ static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i) if (i->index != 0) return -EINVAL; - strcpy(i->name, "Camera"); + strscpy(i->name, "Camera", sizeof(i->name)); i->type = V4L2_INPUT_TYPE_CAMERA; return 0; @@ -1118,12 +1118,12 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh, if (f->index == 0) { /* standard YUV 422 capture */ f->flags = 0; - strcpy(f->description, "YUV422"); + strscpy(f->description, "YUV422", sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_YUYV; } else { /* compressed MJPEG capture */ f->flags = V4L2_FMT_FLAG_COMPRESSED; - strcpy(f->description, "MJPEG"); + strscpy(f->description, "MJPEG", sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_MJPEG; } @@ -1460,7 +1460,7 @@ static int meye_mmap(struct file *file, struct vm_area_struct *vma) unsigned long page, pos; mutex_lock(&meye.lock); - if (size > gbuffers * gbufsize) { + if (size > gbuffers * gbufsize || offset > gbuffers * gbufsize - size) { mutex_unlock(&meye.lock); return -EINVAL; } diff --git a/drivers/media/pci/ngene/ngene-i2c.c b/drivers/media/pci/ngene/ngene-i2c.c index 092d46c2a3a9..02a06f6c97f8 100644 --- a/drivers/media/pci/ngene/ngene-i2c.c +++ b/drivers/media/pci/ngene/ngene-i2c.c @@ -161,7 +161,7 @@ int ngene_i2c_init(struct ngene *dev, int dev_nr) i2c_set_adapdata(adap, &(dev->channel[dev_nr])); - strcpy(adap->name, "nGene"); + strscpy(adap->name, "nGene", sizeof(adap->name)); adap->algo = &ngene_i2c_algo; adap->algo_data = (void *)&(dev->channel[dev_nr]); diff --git a/drivers/media/pci/pluto2/pluto2.c b/drivers/media/pci/pluto2/pluto2.c index 5e6fe686f420..872c796621d2 100644 --- a/drivers/media/pci/pluto2/pluto2.c +++ b/drivers/media/pci/pluto2/pluto2.c @@ -633,7 +633,7 @@ static int pluto2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* i2c */ i2c_set_adapdata(&pluto->i2c_adap, pluto); - strcpy(pluto->i2c_adap.name, DRIVER_NAME); + strscpy(pluto->i2c_adap.name, DRIVER_NAME, sizeof(pluto->i2c_adap.name)); pluto->i2c_adap.owner = THIS_MODULE; pluto->i2c_adap.dev.parent = &pdev->dev; pluto->i2c_adap.algo_data = &pluto->i2c_bit; diff --git a/drivers/media/pci/pt1/pt1.c b/drivers/media/pci/pt1/pt1.c index 7f878fc41b7e..f4b8030e2369 100644 --- a/drivers/media/pci/pt1/pt1.c +++ b/drivers/media/pci/pt1/pt1.c @@ -1354,7 +1354,7 @@ static int pt1_probe(struct pci_dev *pdev, const struct pci_device_id *ent) i2c_adap->algo = &pt1_i2c_algo; i2c_adap->algo_data = NULL; i2c_adap->dev.parent = &pdev->dev; - strcpy(i2c_adap->name, DRIVER_NAME); + strscpy(i2c_adap->name, DRIVER_NAME, sizeof(i2c_adap->name)); i2c_set_adapdata(i2c_adap, pt1); ret = i2c_add_adapter(i2c_adap); if (ret < 0) diff --git a/drivers/media/pci/pt3/pt3.c b/drivers/media/pci/pt3/pt3.c index 90273b4d772f..7a7afae4c84c 100644 --- a/drivers/media/pci/pt3/pt3.c +++ b/drivers/media/pci/pt3/pt3.c @@ -765,7 +765,7 @@ static int pt3_probe(struct pci_dev *pdev, const struct pci_device_id *ent) i2c->algo = &pt3_i2c_algo; i2c->algo_data = NULL; i2c->dev.parent = &pdev->dev; - strlcpy(i2c->name, DRV_NAME, sizeof(i2c->name)); + strscpy(i2c->name, DRV_NAME, sizeof(i2c->name)); i2c_set_adapdata(i2c, pt3); ret = i2c_add_adapter(i2c); if (ret < 0) diff --git a/drivers/media/pci/saa7134/saa7134-alsa.c b/drivers/media/pci/saa7134/saa7134-alsa.c index b90cfde6e301..dc9cdaaee1fb 100644 --- a/drivers/media/pci/saa7134/saa7134-alsa.c +++ b/drivers/media/pci/saa7134/saa7134-alsa.c @@ -901,7 +901,7 @@ static int snd_card_saa7134_pcm(snd_card_saa7134_t *saa7134, int device) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_card_saa7134_capture_ops); pcm->private_data = saa7134; pcm->info_flags = 0; - strcpy(pcm->name, "SAA7134 PCM"); + strscpy(pcm->name, "SAA7134 PCM", sizeof(pcm->name)); return 0; } @@ -1074,7 +1074,7 @@ static int snd_card_saa7134_new_mixer(snd_card_saa7134_t * chip) unsigned int idx; int err, addr; - strcpy(card->mixername, "SAA7134 Mixer"); + strscpy(card->mixername, "SAA7134 Mixer", sizeof(card->mixername)); for (idx = 0; idx < ARRAY_SIZE(snd_saa7134_volume_controls); idx++) { kcontrol = snd_ctl_new1(&snd_saa7134_volume_controls[idx], @@ -1138,7 +1138,7 @@ static int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum) if (err < 0) return err; - strcpy(card->driver, "SAA7134"); + strscpy(card->driver, "SAA7134", sizeof(card->driver)); /* Card "creation" */ @@ -1178,7 +1178,7 @@ static int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum) /* End of "creation" */ - strcpy(card->shortname, "SAA7134"); + strscpy(card->shortname, "SAA7134", sizeof(card->shortname)); sprintf(card->longname, "%s at 0x%lx irq %d", chip->dev->name, chip->iobase, chip->irq); diff --git a/drivers/media/pci/saa7134/saa7134-cards.c b/drivers/media/pci/saa7134/saa7134-cards.c index 9d6688a82b50..40ce033cb884 100644 --- a/drivers/media/pci/saa7134/saa7134-cards.c +++ b/drivers/media/pci/saa7134/saa7134-cards.c @@ -3628,6 +3628,21 @@ struct saa7134_board saa7134_boards[] = { .vmux = 1, .amux = TV, .gpio = 0x0200000, + },{ + .type = SAA7134_INPUT_COMPOSITE1, + .vmux = 3, + .amux = LINE2, + .gpio = 0x0200000, + },{ + .type = SAA7134_INPUT_COMPOSITE2, + .vmux = 0, + .amux = LINE2, + .gpio = 0x0200000, + },{ + .type = SAA7134_INPUT_SVIDEO, + .vmux = 8, + .amux = LINE2, + .gpio = 0x0200000, }}, }, [SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA] = { diff --git a/drivers/media/pci/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c index 9e76de2411ae..8984b1bf57a5 100644 --- a/drivers/media/pci/saa7134/saa7134-core.c +++ b/drivers/media/pci/saa7134/saa7134-core.c @@ -845,12 +845,13 @@ static void saa7134_create_entities(struct saa7134_dev *dev) */ if (!decoder) { dev->demod.name = "saa713x"; - dev->demod_pad[DEMOD_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK; - dev->demod_pad[DEMOD_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE; - dev->demod_pad[DEMOD_PAD_VBI_OUT].flags = MEDIA_PAD_FL_SOURCE; + dev->demod_pad[SAA7134_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK; + dev->demod_pad[SAA7134_PAD_IF_INPUT].sig_type = PAD_SIGNAL_ANALOG; + dev->demod_pad[SAA7134_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE; + dev->demod_pad[SAA7134_PAD_VID_OUT].sig_type = PAD_SIGNAL_DV; dev->demod.function = MEDIA_ENT_F_ATV_DECODER; - ret = media_entity_pads_init(&dev->demod, DEMOD_NUM_PADS, + ret = media_entity_pads_init(&dev->demod, SAA7134_NUM_PADS, dev->demod_pad); if (ret < 0) pr_err("failed to initialize demod pad!\n"); diff --git a/drivers/media/pci/saa7134/saa7134-empress.c b/drivers/media/pci/saa7134/saa7134-empress.c index 66acfd35ffc6..747a082229dc 100644 --- a/drivers/media/pci/saa7134/saa7134-empress.c +++ b/drivers/media/pci/saa7134/saa7134-empress.c @@ -100,7 +100,7 @@ static int empress_enum_fmt_vid_cap(struct file *file, void *priv, if (f->index != 0) return -EINVAL; - strlcpy(f->description, "MPEG TS", sizeof(f->description)); + strscpy(f->description, "MPEG TS", sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_MPEG; f->flags = V4L2_FMT_FLAG_COMPRESSED; return 0; diff --git a/drivers/media/pci/saa7134/saa7134-go7007.c b/drivers/media/pci/saa7134/saa7134-go7007.c index 2799538e2d7e..275c5e151818 100644 --- a/drivers/media/pci/saa7134/saa7134-go7007.c +++ b/drivers/media/pci/saa7134/saa7134-go7007.c @@ -435,7 +435,7 @@ static int saa7134_go7007_init(struct saa7134_dev *dev) go->board_id = GO7007_BOARDID_PCI_VOYAGER; snprintf(go->bus_info, sizeof(go->bus_info), "PCI:%s", pci_name(dev->pci)); - strlcpy(go->name, saa7134_boards[dev->board].name, sizeof(go->name)); + strscpy(go->name, saa7134_boards[dev->board].name, sizeof(go->name)); go->hpi_ops = &saa7134_go7007_hpi_ops; go->hpi_context = saa; saa->dev = dev; diff --git a/drivers/media/pci/saa7134/saa7134-i2c.c b/drivers/media/pci/saa7134/saa7134-i2c.c index cf1e526de56a..51af3310654c 100644 --- a/drivers/media/pci/saa7134/saa7134-i2c.c +++ b/drivers/media/pci/saa7134/saa7134-i2c.c @@ -437,7 +437,7 @@ int saa7134_i2c_register(struct saa7134_dev *dev) { dev->i2c_adap = saa7134_adap_template; dev->i2c_adap.dev.parent = &dev->pci->dev; - strcpy(dev->i2c_adap.name,dev->name); + strscpy(dev->i2c_adap.name, dev->name, sizeof(dev->i2c_adap.name)); dev->i2c_adap.algo_data = dev; i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev); i2c_add_adapter(&dev->i2c_adap); diff --git a/drivers/media/pci/saa7134/saa7134-input.c b/drivers/media/pci/saa7134/saa7134-input.c index 0e28c5021ac4..999b2774b220 100644 --- a/drivers/media/pci/saa7134/saa7134-input.c +++ b/drivers/media/pci/saa7134/saa7134-input.c @@ -953,7 +953,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) memset(&info, 0, sizeof(struct i2c_board_info)); memset(&dev->init_data, 0, sizeof(dev->init_data)); - strlcpy(info.type, "ir_video", I2C_NAME_SIZE); + strscpy(info.type, "ir_video", I2C_NAME_SIZE); switch (dev->board) { case SAA7134_BOARD_PINNACLE_PCTV_110i: diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index 1a50ec9d084f..1a22ae7cbdd9 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -1445,7 +1445,8 @@ int saa7134_enum_input(struct file *file, void *priv, struct v4l2_input *i) if (card_in(dev, i->index).type == SAA7134_NO_INPUT) return -EINVAL; i->index = n; - strcpy(i->name, saa7134_input_name[card_in(dev, n).type]); + strscpy(i->name, saa7134_input_name[card_in(dev, n).type], + sizeof(i->name)); switch (card_in(dev, n).type) { case SAA7134_INPUT_TV: case SAA7134_INPUT_TV_MONO: @@ -1502,8 +1503,8 @@ int saa7134_querycap(struct file *file, void *priv, unsigned int tuner_type = dev->tuner_type; - strcpy(cap->driver, "saa7134"); - strlcpy(cap->card, saa7134_boards[dev->board].name, + strscpy(cap->driver, "saa7134", sizeof(cap->driver)); + strscpy(cap->card, saa7134_boards[dev->board].name, sizeof(cap->card)); sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci)); @@ -1747,7 +1748,7 @@ int saa7134_g_tuner(struct file *file, void *priv, if (n == SAA7134_INPUT_MAX) return -EINVAL; if (card_in(dev, n).type != SAA7134_NO_INPUT) { - strcpy(t->name, "Television"); + strscpy(t->name, "Television", sizeof(t->name)); t->type = V4L2_TUNER_ANALOG_TV; saa_call_all(dev, tuner, g_tuner, t); t->capability = V4L2_TUNER_CAP_NORM | @@ -1819,7 +1820,7 @@ static int saa7134_enum_fmt_vid_cap(struct file *file, void *priv, if (f->index >= FORMATS) return -EINVAL; - strlcpy(f->description, formats[f->index].name, + strscpy(f->description, formats[f->index].name, sizeof(f->description)); f->pixelformat = formats[f->index].fourcc; @@ -1838,7 +1839,7 @@ static int saa7134_enum_fmt_vid_overlay(struct file *file, void *priv, if ((f->index >= FORMATS) || formats[f->index].planar) return -EINVAL; - strlcpy(f->description, formats[f->index].name, + strscpy(f->description, formats[f->index].name, sizeof(f->description)); f->pixelformat = formats[f->index].fourcc; @@ -1939,7 +1940,7 @@ static int radio_g_tuner(struct file *file, void *priv, if (0 != t->index) return -EINVAL; - strcpy(t->name, "Radio"); + strscpy(t->name, "Radio", sizeof(t->name)); saa_call_all(dev, tuner, g_tuner, t); t->audmode &= V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO; diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h index d99e937a98c1..480228456014 100644 --- a/drivers/media/pci/saa7134/saa7134.h +++ b/drivers/media/pci/saa7134/saa7134.h @@ -547,6 +547,12 @@ struct saa7134_mpeg_ops { unsigned long status); }; +enum saa7134_pads { + SAA7134_PAD_IF_INPUT, + SAA7134_PAD_VID_OUT, + SAA7134_NUM_PADS +}; + /* global device status */ struct saa7134_dev { struct list_head devlist; @@ -674,7 +680,7 @@ struct saa7134_dev { struct media_pad input_pad[SAA7134_INPUT_MAX + 1]; struct media_entity demod; - struct media_pad demod_pad[DEMOD_NUM_PADS]; + struct media_pad demod_pad[SAA7134_NUM_PADS]; struct media_pad video_pad, vbi_pad; struct media_entity *decoder; diff --git a/drivers/media/pci/saa7146/mxb.c b/drivers/media/pci/saa7146/mxb.c index 6b5582b7c595..44440c6208df 100644 --- a/drivers/media/pci/saa7146/mxb.c +++ b/drivers/media/pci/saa7146/mxb.c @@ -553,7 +553,7 @@ static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *t) DEB_EE("VIDIOC_G_TUNER: %d\n", t->index); memset(t, 0, sizeof(*t)); - strlcpy(t->name, "TV Tuner", sizeof(t->name)); + strscpy(t->name, "TV Tuner", sizeof(t->name)); t->type = V4L2_TUNER_ANALOG_TV; t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; diff --git a/drivers/media/pci/saa7164/saa7164-core.c b/drivers/media/pci/saa7164/saa7164-core.c index d697e1ad929c..f33349e16359 100644 --- a/drivers/media/pci/saa7164/saa7164-core.c +++ b/drivers/media/pci/saa7164/saa7164-core.c @@ -179,7 +179,7 @@ static void saa7164_histogram_reset(struct saa7164_histogram *hg, char *name) int i; memset(hg, 0, sizeof(struct saa7164_histogram)); - strcpy(hg->name, name); + strscpy(hg->name, name, sizeof(hg->name)); /* First 30ms x 1ms */ for (i = 0; i < 30; i++) diff --git a/drivers/media/pci/saa7164/saa7164-dvb.c b/drivers/media/pci/saa7164/saa7164-dvb.c index 4f9f03c3b252..dfb118d7d1ec 100644 --- a/drivers/media/pci/saa7164/saa7164-dvb.c +++ b/drivers/media/pci/saa7164/saa7164-dvb.c @@ -120,7 +120,7 @@ static int si2157_attach(struct saa7164_port *port, struct i2c_adapter *adapter, memset(&bi, 0, sizeof(bi)); - strlcpy(bi.type, "si2157", I2C_NAME_SIZE); + strscpy(bi.type, "si2157", I2C_NAME_SIZE); bi.platform_data = cfg; bi.addr = addr8bit >> 1; @@ -643,7 +643,7 @@ int saa7164_dvb_register(struct saa7164_port *port) si2168_config.fe = &port->dvb.frontend; si2168_config.ts_mode = SI2168_TS_SERIAL; memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2168", I2C_NAME_SIZE); + strscpy(info.type, "si2168", I2C_NAME_SIZE); info.addr = 0xc8 >> 1; info.platform_data = &si2168_config; request_module(info.type); @@ -663,7 +663,7 @@ int saa7164_dvb_register(struct saa7164_port *port) si2157_config.if_port = 1; si2157_config.fe = port->dvb.frontend; memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2157", I2C_NAME_SIZE); + strscpy(info.type, "si2157", I2C_NAME_SIZE); info.addr = 0xc0 >> 1; info.platform_data = &si2157_config; request_module(info.type); @@ -688,7 +688,7 @@ int saa7164_dvb_register(struct saa7164_port *port) si2168_config.fe = &port->dvb.frontend; si2168_config.ts_mode = SI2168_TS_SERIAL; memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2168", I2C_NAME_SIZE); + strscpy(info.type, "si2168", I2C_NAME_SIZE); info.addr = 0xcc >> 1; info.platform_data = &si2168_config; request_module(info.type); @@ -708,7 +708,7 @@ int saa7164_dvb_register(struct saa7164_port *port) si2157_config.fe = port->dvb.frontend; si2157_config.if_port = 1; memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2157", I2C_NAME_SIZE); + strscpy(info.type, "si2157", I2C_NAME_SIZE); info.addr = 0xc0 >> 1; info.platform_data = &si2157_config; request_module(info.type); diff --git a/drivers/media/pci/saa7164/saa7164-encoder.c b/drivers/media/pci/saa7164/saa7164-encoder.c index 32136ebe4f61..adec2bab8352 100644 --- a/drivers/media/pci/saa7164/saa7164-encoder.c +++ b/drivers/media/pci/saa7164/saa7164-encoder.c @@ -258,7 +258,7 @@ int saa7164_enum_input(struct file *file, void *priv, struct v4l2_input *i) if (i->index >= 7) return -EINVAL; - strcpy(i->name, inputs[i->index]); + strscpy(i->name, inputs[i->index], sizeof(i->name)); if (i->index == 0) i->type = V4L2_INPUT_TYPE_TUNER; @@ -325,7 +325,7 @@ int saa7164_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) if (0 != t->index) return -EINVAL; - strcpy(t->name, "tuner"); + strscpy(t->name, "tuner", sizeof(t->name)); t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO; t->rangelow = SAA7164_TV_MIN_FREQ; t->rangehigh = SAA7164_TV_MAX_FREQ; @@ -497,8 +497,8 @@ static int vidioc_querycap(struct file *file, void *priv, struct saa7164_port *port = fh->port; struct saa7164_dev *dev = port->dev; - strcpy(cap->driver, dev->name); - strlcpy(cap->card, saa7164_boards[dev->board].name, + strscpy(cap->driver, dev->name, sizeof(cap->driver)); + strscpy(cap->card, saa7164_boards[dev->board].name, sizeof(cap->card)); sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci)); @@ -520,7 +520,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, if (f->index != 0) return -EINVAL; - strlcpy(f->description, "MPEG", sizeof(f->description)); + strscpy(f->description, "MPEG", sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_MPEG; return 0; diff --git a/drivers/media/pci/saa7164/saa7164-i2c.c b/drivers/media/pci/saa7164/saa7164-i2c.c index 6d13cbb9d010..317f48bc6506 100644 --- a/drivers/media/pci/saa7164/saa7164-i2c.c +++ b/drivers/media/pci/saa7164/saa7164-i2c.c @@ -99,7 +99,7 @@ int saa7164_i2c_register(struct saa7164_i2c *bus) bus->i2c_adap.dev.parent = &dev->pci->dev; - strlcpy(bus->i2c_adap.name, bus->dev->name, + strscpy(bus->i2c_adap.name, bus->dev->name, sizeof(bus->i2c_adap.name)); bus->i2c_adap.algo_data = bus; diff --git a/drivers/media/pci/saa7164/saa7164-vbi.c b/drivers/media/pci/saa7164/saa7164-vbi.c index 221de91a8bae..841c7e94405d 100644 --- a/drivers/media/pci/saa7164/saa7164-vbi.c +++ b/drivers/media/pci/saa7164/saa7164-vbi.c @@ -208,8 +208,8 @@ static int vidioc_querycap(struct file *file, void *priv, struct saa7164_port *port = fh->port; struct saa7164_dev *dev = port->dev; - strcpy(cap->driver, dev->name); - strlcpy(cap->card, saa7164_boards[dev->board].name, + strscpy(cap->driver, dev->name, sizeof(cap->driver)); + strscpy(cap->card, saa7164_boards[dev->board].name, sizeof(cap->card)); sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci)); diff --git a/drivers/media/pci/smipcie/smipcie-main.c b/drivers/media/pci/smipcie/smipcie-main.c index 6dbe3b4d09ce..4d5ddbcb3514 100644 --- a/drivers/media/pci/smipcie/smipcie-main.c +++ b/drivers/media/pci/smipcie/smipcie-main.c @@ -191,7 +191,7 @@ static int smi_i2c_init(struct smi_dev *dev) /* i2c bus 0 */ smi_i2c_cfg(dev, I2C_A_SW_CTL); i2c_set_adapdata(&dev->i2c_bus[0], dev); - strcpy(dev->i2c_bus[0].name, "SMI-I2C0"); + strscpy(dev->i2c_bus[0].name, "SMI-I2C0", sizeof(dev->i2c_bus[0].name)); dev->i2c_bus[0].owner = THIS_MODULE; dev->i2c_bus[0].dev.parent = &dev->pci_dev->dev; dev->i2c_bus[0].algo_data = &dev->i2c_bit[0]; @@ -213,7 +213,7 @@ static int smi_i2c_init(struct smi_dev *dev) /* i2c bus 1 */ smi_i2c_cfg(dev, I2C_B_SW_CTL); i2c_set_adapdata(&dev->i2c_bus[1], dev); - strcpy(dev->i2c_bus[1].name, "SMI-I2C1"); + strscpy(dev->i2c_bus[1].name, "SMI-I2C1", sizeof(dev->i2c_bus[1].name)); dev->i2c_bus[1].owner = THIS_MODULE; dev->i2c_bus[1].dev.parent = &dev->pci_dev->dev; dev->i2c_bus[1].algo_data = &dev->i2c_bit[1]; @@ -549,7 +549,7 @@ static int smi_dvbsky_m88ds3103_fe_attach(struct smi_port *port) } /* attach tuner */ ts2020_config.fe = port->fe; - strlcpy(tuner_info.type, "ts2020", I2C_NAME_SIZE); + strscpy(tuner_info.type, "ts2020", I2C_NAME_SIZE); tuner_info.addr = 0x60; tuner_info.platform_data = &ts2020_config; tuner_client = smi_add_i2c_client(tuner_i2c_adapter, &tuner_info); @@ -605,7 +605,7 @@ static int smi_dvbsky_m88rs6000_fe_attach(struct smi_port *port) } /* attach tuner */ m88rs6000t_config.fe = port->fe; - strlcpy(tuner_info.type, "m88rs6000t", I2C_NAME_SIZE); + strscpy(tuner_info.type, "m88rs6000t", I2C_NAME_SIZE); tuner_info.addr = 0x21; tuner_info.platform_data = &m88rs6000t_config; tuner_client = smi_add_i2c_client(tuner_i2c_adapter, &tuner_info); @@ -647,7 +647,7 @@ static int smi_dvbsky_sit2_fe_attach(struct smi_port *port) si2168_config.ts_mode = SI2168_TS_PARALLEL; memset(&client_info, 0, sizeof(struct i2c_board_info)); - strlcpy(client_info.type, "si2168", I2C_NAME_SIZE); + strscpy(client_info.type, "si2168", I2C_NAME_SIZE); client_info.addr = 0x64; client_info.platform_data = &si2168_config; @@ -664,7 +664,7 @@ static int smi_dvbsky_sit2_fe_attach(struct smi_port *port) si2157_config.if_port = 1; memset(&client_info, 0, sizeof(struct i2c_board_info)); - strlcpy(client_info.type, "si2157", I2C_NAME_SIZE); + strscpy(client_info.type, "si2157", I2C_NAME_SIZE); client_info.addr = 0x60; client_info.platform_data = &si2157_config; diff --git a/drivers/media/pci/solo6x10/solo6x10-g723.c b/drivers/media/pci/solo6x10/solo6x10-g723.c index 2ac33b5cc454..2cc05a9d57ac 100644 --- a/drivers/media/pci/solo6x10/solo6x10-g723.c +++ b/drivers/media/pci/solo6x10/solo6x10-g723.c @@ -354,7 +354,7 @@ static int solo_snd_pcm_init(struct solo_dev *solo_dev) snd_pcm_chip(pcm) = solo_dev; pcm->info_flags = 0; - strcpy(pcm->name, card->shortname); + strscpy(pcm->name, card->shortname, sizeof(pcm->name)); for (i = 0, ss = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; ss; ss = ss->next, i++) @@ -394,8 +394,8 @@ int solo_g723_init(struct solo_dev *solo_dev) card = solo_dev->snd_card; - strcpy(card->driver, SOLO6X10_NAME); - strcpy(card->shortname, "SOLO-6x10 Audio"); + strscpy(card->driver, SOLO6X10_NAME, sizeof(card->driver)); + strscpy(card->shortname, "SOLO-6x10 Audio", sizeof(card->shortname)); sprintf(card->longname, "%s on %s IRQ %d", card->shortname, pci_name(solo_dev->pdev), solo_dev->pdev->irq); @@ -404,7 +404,7 @@ int solo_g723_init(struct solo_dev *solo_dev) goto snd_error; /* Mixer controls */ - strcpy(card->mixername, "SOLO-6x10"); + strscpy(card->mixername, "SOLO-6x10", sizeof(card->mixername)); kctl = snd_solo_capture_volume; kctl.count = solo_dev->nr_chans; diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c index 25f9f2ebff1d..9d27e7463070 100644 --- a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c +++ b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c @@ -775,7 +775,7 @@ static int solo_enc_querycap(struct file *file, void *priv, struct solo_enc_dev *solo_enc = video_drvdata(file); struct solo_dev *solo_dev = solo_enc->solo_dev; - strcpy(cap->driver, SOLO6X10_NAME); + strscpy(cap->driver, SOLO6X10_NAME, sizeof(cap->driver)); snprintf(cap->card, sizeof(cap->card), "Softlogic 6x10 Enc %d", solo_enc->ch); snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", @@ -834,17 +834,18 @@ static int solo_enc_enum_fmt_cap(struct file *file, void *priv, switch (dev_type) { case SOLO_DEV_6010: f->pixelformat = V4L2_PIX_FMT_MPEG4; - strcpy(f->description, "MPEG-4 part 2"); + strscpy(f->description, "MPEG-4 part 2", + sizeof(f->description)); break; case SOLO_DEV_6110: f->pixelformat = V4L2_PIX_FMT_H264; - strcpy(f->description, "H.264"); + strscpy(f->description, "H.264", sizeof(f->description)); break; } break; case 1: f->pixelformat = V4L2_PIX_FMT_MJPEG; - strcpy(f->description, "MJPEG"); + strscpy(f->description, "MJPEG", sizeof(f->description)); break; default: return -EINVAL; @@ -1126,7 +1127,8 @@ static int solo_s_ctrl(struct v4l2_ctrl *ctrl) solo_enc->md_thresholds->p_new.p_u16); break; case V4L2_CID_OSD_TEXT: - strcpy(solo_enc->osd_text, ctrl->p_new.p_char); + strscpy(solo_enc->osd_text, ctrl->p_new.p_char, + sizeof(solo_enc->osd_text)); return solo_osd_print(solo_enc); default: return -EINVAL; diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2.c b/drivers/media/pci/solo6x10/solo6x10-v4l2.c index 99ffd1ed4a73..69fc939fd3d9 100644 --- a/drivers/media/pci/solo6x10/solo6x10-v4l2.c +++ b/drivers/media/pci/solo6x10/solo6x10-v4l2.c @@ -383,8 +383,8 @@ static int solo_querycap(struct file *file, void *priv, { struct solo_dev *solo_dev = video_drvdata(file); - strcpy(cap->driver, SOLO6X10_NAME); - strcpy(cap->card, "Softlogic 6x10"); + strscpy(cap->driver, SOLO6X10_NAME, sizeof(cap->driver)); + strscpy(cap->card, "Softlogic 6x10", sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", pci_name(solo_dev->pdev)); cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | @@ -470,7 +470,7 @@ static int solo_enum_fmt_cap(struct file *file, void *priv, return -EINVAL; f->pixelformat = V4L2_PIX_FMT_UYVY; - strlcpy(f->description, "UYUV 4:2:2 Packed", sizeof(f->description)); + strscpy(f->description, "UYUV 4:2:2 Packed", sizeof(f->description)); return 0; } diff --git a/drivers/media/pci/sta2x11/sta2x11_vip.c b/drivers/media/pci/sta2x11/sta2x11_vip.c index 1858efedaf1a..411177ec4d72 100644 --- a/drivers/media/pci/sta2x11/sta2x11_vip.c +++ b/drivers/media/pci/sta2x11/sta2x11_vip.c @@ -419,8 +419,8 @@ static int vidioc_querycap(struct file *file, void *priv, { struct sta2x11_vip *vip = video_drvdata(file); - strcpy(cap->driver, KBUILD_MODNAME); - strcpy(cap->card, KBUILD_MODNAME); + strscpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver)); + strscpy(cap->card, KBUILD_MODNAME, sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", pci_name(vip->pdev)); cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | @@ -580,7 +580,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, if (f->index != 0) return -EINVAL; - strcpy(f->description, "4:2:2, packed, UYVY"); + strscpy(f->description, "4:2:2, packed, UYVY", sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_UYVY; f->flags = 0; return 0; diff --git a/drivers/media/pci/ttpci/av7110.c b/drivers/media/pci/ttpci/av7110.c index d6816effb878..409defc75c05 100644 --- a/drivers/media/pci/ttpci/av7110.c +++ b/drivers/media/pci/ttpci/av7110.c @@ -2482,7 +2482,8 @@ static int av7110_attach(struct saa7146_dev* dev, get recognized before the main driver is fully loaded */ saa7146_write(dev, GPIO_CTRL, 0x500000); - strlcpy(av7110->i2c_adap.name, pci_ext->ext_priv, sizeof(av7110->i2c_adap.name)); + strscpy(av7110->i2c_adap.name, pci_ext->ext_priv, + sizeof(av7110->i2c_adap.name)); saa7146_i2c_adapter_prepare(dev, &av7110->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120); /* 275 kHz */ diff --git a/drivers/media/pci/ttpci/av7110_av.c b/drivers/media/pci/ttpci/av7110_av.c index ef1bc17cdc4d..1073e4671b68 100644 --- a/drivers/media/pci/ttpci/av7110_av.c +++ b/drivers/media/pci/ttpci/av7110_av.c @@ -932,7 +932,6 @@ static int dvb_video_get_event (struct av7110 *av7110, struct video_event *event return 0; } - /****************************************************************************** * DVB device file operations ******************************************************************************/ @@ -1095,6 +1094,42 @@ static int play_iframe(struct av7110 *av7110, char __user *buf, unsigned int len return 0; } +#ifdef CONFIG_COMPAT +struct compat_video_still_picture { + compat_uptr_t iFrame; + int32_t size; +}; +#define VIDEO_STILLPICTURE32 _IOW('o', 30, struct compat_video_still_picture) + +struct compat_video_event { + __s32 type; + /* unused, make sure to use atomic time for y2038 if it ever gets used */ + compat_long_t timestamp; + union { + video_size_t size; + unsigned int frame_rate; /* in frames per 1000sec */ + unsigned char vsync_field; /* unknown/odd/even/progressive */ + } u; +}; +#define VIDEO_GET_EVENT32 _IOR('o', 28, struct compat_video_event) + +static int dvb_compat_video_get_event(struct av7110 *av7110, + struct compat_video_event *event, int flags) +{ + struct video_event ev; + int ret; + + ret = dvb_video_get_event(av7110, &ev, flags); + + *event = (struct compat_video_event) { + .type = ev.type, + .timestamp = ev.timestamp, + .u.size = ev.u.size, + }; + + return ret; +} +#endif static int dvb_video_ioctl(struct file *file, unsigned int cmd, void *parg) @@ -1184,6 +1219,12 @@ static int dvb_video_ioctl(struct file *file, memcpy(parg, &av7110->videostate, sizeof(struct video_status)); break; +#ifdef CONFIG_COMPAT + case VIDEO_GET_EVENT32: + ret = dvb_compat_video_get_event(av7110, parg, file->f_flags); + break; +#endif + case VIDEO_GET_EVENT: ret = dvb_video_get_event(av7110, parg, file->f_flags); break; @@ -1226,6 +1267,19 @@ static int dvb_video_ioctl(struct file *file, 1, (u16) arg); break; +#ifdef CONFIG_COMPAT + case VIDEO_STILLPICTURE32: + { + struct compat_video_still_picture *pic = + (struct compat_video_still_picture *) parg; + av7110->videostate.stream_source = VIDEO_SOURCE_MEMORY; + dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout); + ret = play_iframe(av7110, compat_ptr(pic->iFrame), + pic->size, file->f_flags & O_NONBLOCK); + break; + } +#endif + case VIDEO_STILLPICTURE: { struct video_still_picture *pic = @@ -1533,6 +1587,7 @@ static const struct file_operations dvb_video_fops = { .owner = THIS_MODULE, .write = dvb_video_write, .unlocked_ioctl = dvb_generic_ioctl, + .compat_ioctl = dvb_generic_ioctl, .open = dvb_video_open, .release = dvb_video_release, .poll = dvb_video_poll, @@ -1552,6 +1607,7 @@ static const struct file_operations dvb_audio_fops = { .owner = THIS_MODULE, .write = dvb_audio_write, .unlocked_ioctl = dvb_generic_ioctl, + .compat_ioctl = dvb_generic_ioctl, .open = dvb_audio_open, .release = dvb_audio_release, .poll = dvb_audio_poll, diff --git a/drivers/media/pci/ttpci/av7110_v4l.c b/drivers/media/pci/ttpci/av7110_v4l.c index e4cf42c32284..d1fe15365f4a 100644 --- a/drivers/media/pci/ttpci/av7110_v4l.c +++ b/drivers/media/pci/ttpci/av7110_v4l.c @@ -332,7 +332,7 @@ static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *t) return -EINVAL; memset(t, 0, sizeof(*t)); - strcpy((char *)t->name, "Television"); + strscpy((char *)t->name, "Television", sizeof(t->name)); t->type = V4L2_TUNER_ANALOG_TV; t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | diff --git a/drivers/media/pci/ttpci/budget-core.c b/drivers/media/pci/ttpci/budget-core.c index b3dc45b91101..35b696bdb2df 100644 --- a/drivers/media/pci/ttpci/budget-core.c +++ b/drivers/media/pci/ttpci/budget-core.c @@ -504,10 +504,12 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, if (bi->type != BUDGET_FS_ACTIVY) saa7146_write(dev, GPIO_CTRL, 0x500000); /* GPIO 3 = 1 */ - strlcpy(budget->i2c_adap.name, budget->card->name, sizeof(budget->i2c_adap.name)); + strscpy(budget->i2c_adap.name, budget->card->name, + sizeof(budget->i2c_adap.name)); saa7146_i2c_adapter_prepare(dev, &budget->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120); - strcpy(budget->i2c_adap.name, budget->card->name); + strscpy(budget->i2c_adap.name, budget->card->name, + sizeof(budget->i2c_adap.name)); if (i2c_add_adapter(&budget->i2c_adap) < 0) { ret = -ENOMEM; diff --git a/drivers/media/pci/tw5864/tw5864-video.c b/drivers/media/pci/tw5864/tw5864-video.c index ff2b7da90c08..5a1f3aa4101a 100644 --- a/drivers/media/pci/tw5864/tw5864-video.c +++ b/drivers/media/pci/tw5864/tw5864-video.c @@ -610,7 +610,7 @@ static int tw5864_querycap(struct file *file, void *priv, { struct tw5864_input *input = video_drvdata(file); - strcpy(cap->driver, "tw5864"); + strscpy(cap->driver, "tw5864", sizeof(cap->driver)); snprintf(cap->card, sizeof(cap->card), "TW5864 Encoder %d", input->nr); sprintf(cap->bus_info, "PCI:%s", pci_name(input->root->pci)); diff --git a/drivers/media/pci/tw68/tw68-video.c b/drivers/media/pci/tw68/tw68-video.c index 8c1f4a049764..d3f727045ae8 100644 --- a/drivers/media/pci/tw68/tw68-video.c +++ b/drivers/media/pci/tw68/tw68-video.c @@ -734,8 +734,8 @@ static int tw68_querycap(struct file *file, void *priv, { struct tw68_dev *dev = video_drvdata(file); - strcpy(cap->driver, "tw68"); - strlcpy(cap->card, "Techwell Capture Card", + strscpy(cap->driver, "tw68", sizeof(cap->driver)); + strscpy(cap->card, "Techwell Capture Card", sizeof(cap->card)); sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci)); cap->device_caps = @@ -789,7 +789,7 @@ static int tw68_enum_fmt_vid_cap(struct file *file, void *priv, if (f->index >= FORMATS) return -EINVAL; - strlcpy(f->description, formats[f->index].name, + strscpy(f->description, formats[f->index].name, sizeof(f->description)); f->pixelformat = formats[f->index].fourcc; diff --git a/drivers/media/pci/tw686x/tw686x-audio.c b/drivers/media/pci/tw686x/tw686x-audio.c index 77190768622a..a28329698e20 100644 --- a/drivers/media/pci/tw686x/tw686x-audio.c +++ b/drivers/media/pci/tw686x/tw686x-audio.c @@ -295,7 +295,7 @@ static int tw686x_snd_pcm_init(struct tw686x_dev *dev) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &tw686x_pcm_ops); snd_pcm_chip(pcm) = dev; pcm->info_flags = 0; - strlcpy(pcm->name, "tw686x PCM", sizeof(pcm->name)); + strscpy(pcm->name, "tw686x PCM", sizeof(pcm->name)); for (i = 0, ss = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; ss; ss = ss->next, i++) @@ -390,9 +390,9 @@ int tw686x_audio_init(struct tw686x_dev *dev) return err; dev->snd_card = card; - strlcpy(card->driver, "tw686x", sizeof(card->driver)); - strlcpy(card->shortname, "tw686x", sizeof(card->shortname)); - strlcpy(card->longname, pci_name(pci_dev), sizeof(card->longname)); + strscpy(card->driver, "tw686x", sizeof(card->driver)); + strscpy(card->shortname, "tw686x", sizeof(card->shortname)); + strscpy(card->longname, pci_name(pci_dev), sizeof(card->longname)); snd_card_set_dev(card, &pci_dev->dev); for (ch = 0; ch < max_channels(dev); ch++) { diff --git a/drivers/media/pci/tw686x/tw686x-video.c b/drivers/media/pci/tw686x/tw686x-video.c index 3a06c000f97b..4890b7f1248b 100644 --- a/drivers/media/pci/tw686x/tw686x-video.c +++ b/drivers/media/pci/tw686x/tw686x-video.c @@ -765,8 +765,8 @@ static int tw686x_querycap(struct file *file, void *priv, struct tw686x_video_channel *vc = video_drvdata(file); struct tw686x_dev *dev = vc->dev; - strlcpy(cap->driver, "tw686x", sizeof(cap->driver)); - strlcpy(cap->card, dev->name, sizeof(cap->card)); + strscpy(cap->driver, "tw686x", sizeof(cap->driver)); + strscpy(cap->card, dev->name, sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", pci_name(dev->pci_dev)); cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 54fe90acb5b2..70c4f6c54881 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -58,6 +58,7 @@ config VIDEO_MUX select MULTIPLEXER depends on VIDEO_V4L2 && OF && VIDEO_V4L2_SUBDEV_API && MEDIA_CONTROLLER select REGMAP + select V4L2_FWNODE help This driver provides support for N:1 video bus multiplexers. @@ -181,6 +182,15 @@ config VIDEO_CODA config VIDEO_IMX_VDOA def_tristate VIDEO_CODA if SOC_IMX6Q || COMPILE_TEST +config VIDEO_IMX_PXP + tristate "i.MX Pixel Pipeline (PXP)" + depends on VIDEO_DEV && VIDEO_V4L2 && (ARCH_MXC || COMPILE_TEST) + select VIDEOBUF2_DMA_CONTIG + select V4L2_MEM2MEM_DEV + help + The i.MX Pixel Pipeline is a memory-to-memory engine for scaling, + color space conversion, and rotation. + config VIDEO_MEDIATEK_JPEG tristate "Mediatek JPEG Codec driver" depends on MTK_IOMMU_V1 || COMPILE_TEST diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile index 41322ab65802..6ab6200dd9c9 100644 --- a/drivers/media/platform/Makefile +++ b/drivers/media/platform/Makefile @@ -25,6 +25,8 @@ obj-$(CONFIG_VIDEO_TI_CAL) += ti-vpe/ obj-$(CONFIG_VIDEO_MX2_EMMAPRP) += mx2_emmaprp.o obj-$(CONFIG_VIDEO_CODA) += coda/ +obj-$(CONFIG_VIDEO_IMX_PXP) += imx-pxp.o + obj-$(CONFIG_VIDEO_SH_VEU) += sh_veu.o obj-$(CONFIG_CEC_GPIO) += cec-gpio/ diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c index b05738a95e55..e13d2b3a7168 100644 --- a/drivers/media/platform/am437x/am437x-vpfe.c +++ b/drivers/media/platform/am437x/am437x-vpfe.c @@ -1408,8 +1408,8 @@ static int vpfe_querycap(struct file *file, void *priv, vpfe_dbg(2, vpfe, "vpfe_querycap\n"); - strlcpy(cap->driver, VPFE_MODULE_NAME, sizeof(cap->driver)); - strlcpy(cap->card, "TI AM437x VPFE", sizeof(cap->card)); + strscpy(cap->driver, VPFE_MODULE_NAME, sizeof(cap->driver)); + strscpy(cap->card, "TI AM437x VPFE", sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", vpfe->v4l2_dev.name); cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | @@ -2386,7 +2386,7 @@ static int vpfe_probe_complete(struct vpfe_device *vpfe) INIT_LIST_HEAD(&vpfe->dma_queue); vdev = &vpfe->video_dev; - strlcpy(vdev->name, VPFE_MODULE_NAME, sizeof(vdev->name)); + strscpy(vdev->name, VPFE_MODULE_NAME, sizeof(vdev->name)); vdev->release = video_device_release_empty; vdev->fops = &vpfe_fops; vdev->ioctl_ops = &vpfe_ioctl_ops; @@ -2423,30 +2423,32 @@ static const struct v4l2_async_notifier_operations vpfe_async_ops = { }; static struct vpfe_config * -vpfe_get_pdata(struct platform_device *pdev) +vpfe_get_pdata(struct vpfe_device *vpfe) { struct device_node *endpoint = NULL; - struct v4l2_fwnode_endpoint bus_cfg; + struct device *dev = vpfe->pdev; struct vpfe_subdev_info *sdinfo; struct vpfe_config *pdata; unsigned int flags; unsigned int i; int err; - dev_dbg(&pdev->dev, "vpfe_get_pdata\n"); + dev_dbg(dev, "vpfe_get_pdata\n"); - if (!IS_ENABLED(CONFIG_OF) || !pdev->dev.of_node) - return pdev->dev.platform_data; + v4l2_async_notifier_init(&vpfe->notifier); - pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!IS_ENABLED(CONFIG_OF) || !dev->of_node) + return dev->platform_data; + + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return NULL; for (i = 0; ; i++) { + struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 }; struct device_node *rem; - endpoint = of_graph_get_next_endpoint(pdev->dev.of_node, - endpoint); + endpoint = of_graph_get_next_endpoint(dev->of_node, endpoint); if (!endpoint) break; @@ -2455,7 +2457,8 @@ vpfe_get_pdata(struct platform_device *pdev) /* we only support camera */ sdinfo->inputs[0].index = i; - strcpy(sdinfo->inputs[0].name, "Camera"); + strscpy(sdinfo->inputs[0].name, "Camera", + sizeof(sdinfo->inputs[0].name)); sdinfo->inputs[0].type = V4L2_INPUT_TYPE_CAMERA; sdinfo->inputs[0].std = V4L2_STD_ALL; sdinfo->inputs[0].capabilities = V4L2_IN_CAP_STD; @@ -2473,16 +2476,16 @@ vpfe_get_pdata(struct platform_device *pdev) err = v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint), &bus_cfg); if (err) { - dev_err(&pdev->dev, "Could not parse the endpoint\n"); - goto done; + dev_err(dev, "Could not parse the endpoint\n"); + goto cleanup; } sdinfo->vpfe_param.bus_width = bus_cfg.bus.parallel.bus_width; if (sdinfo->vpfe_param.bus_width < 8 || sdinfo->vpfe_param.bus_width > 16) { - dev_err(&pdev->dev, "Invalid bus width.\n"); - goto done; + dev_err(dev, "Invalid bus width.\n"); + goto cleanup; } flags = bus_cfg.bus.parallel.flags; @@ -2495,29 +2498,25 @@ vpfe_get_pdata(struct platform_device *pdev) rem = of_graph_get_remote_port_parent(endpoint); if (!rem) { - dev_err(&pdev->dev, "Remote device at %pOF not found\n", + dev_err(dev, "Remote device at %pOF not found\n", endpoint); - goto done; + goto cleanup; } - pdata->asd[i] = devm_kzalloc(&pdev->dev, - sizeof(struct v4l2_async_subdev), - GFP_KERNEL); - if (!pdata->asd[i]) { + pdata->asd[i] = v4l2_async_notifier_add_fwnode_subdev( + &vpfe->notifier, of_fwnode_handle(rem), + sizeof(struct v4l2_async_subdev)); + if (IS_ERR(pdata->asd[i])) { of_node_put(rem); - pdata = NULL; - goto done; + goto cleanup; } - - pdata->asd[i]->match_type = V4L2_ASYNC_MATCH_FWNODE; - pdata->asd[i]->match.fwnode = of_fwnode_handle(rem); - of_node_put(rem); } of_node_put(endpoint); return pdata; -done: +cleanup: + v4l2_async_notifier_cleanup(&vpfe->notifier); of_node_put(endpoint); return NULL; } @@ -2529,34 +2528,39 @@ done: */ static int vpfe_probe(struct platform_device *pdev) { - struct vpfe_config *vpfe_cfg = vpfe_get_pdata(pdev); + struct vpfe_config *vpfe_cfg; struct vpfe_device *vpfe; struct vpfe_ccdc *ccdc; struct resource *res; int ret; - if (!vpfe_cfg) { - dev_err(&pdev->dev, "No platform data\n"); - return -EINVAL; - } - vpfe = devm_kzalloc(&pdev->dev, sizeof(*vpfe), GFP_KERNEL); if (!vpfe) return -ENOMEM; vpfe->pdev = &pdev->dev; + + vpfe_cfg = vpfe_get_pdata(vpfe); + if (!vpfe_cfg) { + dev_err(&pdev->dev, "No platform data\n"); + return -EINVAL; + } + vpfe->cfg = vpfe_cfg; ccdc = &vpfe->ccdc; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ccdc->ccdc_cfg.base_addr = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(ccdc->ccdc_cfg.base_addr)) - return PTR_ERR(ccdc->ccdc_cfg.base_addr); + if (IS_ERR(ccdc->ccdc_cfg.base_addr)) { + ret = PTR_ERR(ccdc->ccdc_cfg.base_addr); + goto probe_out_cleanup; + } ret = platform_get_irq(pdev, 0); if (ret <= 0) { dev_err(&pdev->dev, "No IRQ resource\n"); - return -ENODEV; + ret = -ENODEV; + goto probe_out_cleanup; } vpfe->irq = ret; @@ -2564,14 +2568,15 @@ static int vpfe_probe(struct platform_device *pdev) "vpfe_capture0", vpfe); if (ret) { dev_err(&pdev->dev, "Unable to request interrupt\n"); - return -EINVAL; + ret = -EINVAL; + goto probe_out_cleanup; } ret = v4l2_device_register(&pdev->dev, &vpfe->v4l2_dev); if (ret) { vpfe_err(vpfe, "Unable to register v4l2 device.\n"); - return ret; + goto probe_out_cleanup; } /* set the driver data in platform device */ @@ -2595,11 +2600,8 @@ static int vpfe_probe(struct platform_device *pdev) goto probe_out_v4l2_unregister; } - vpfe->notifier.subdevs = vpfe->cfg->asd; - vpfe->notifier.num_subdevs = ARRAY_SIZE(vpfe->cfg->asd); vpfe->notifier.ops = &vpfe_async_ops; - ret = v4l2_async_notifier_register(&vpfe->v4l2_dev, - &vpfe->notifier); + ret = v4l2_async_notifier_register(&vpfe->v4l2_dev, &vpfe->notifier); if (ret) { vpfe_err(vpfe, "Error registering async notifier\n"); ret = -EINVAL; @@ -2610,6 +2612,8 @@ static int vpfe_probe(struct platform_device *pdev) probe_out_v4l2_unregister: v4l2_device_unregister(&vpfe->v4l2_dev); +probe_out_cleanup: + v4l2_async_notifier_cleanup(&vpfe->notifier); return ret; } @@ -2625,6 +2629,7 @@ static int vpfe_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); v4l2_async_notifier_unregister(&vpfe->notifier); + v4l2_async_notifier_cleanup(&vpfe->notifier); v4l2_device_unregister(&vpfe->v4l2_dev); video_unregister_device(&vpfe->video_dev); diff --git a/drivers/media/platform/atmel/atmel-isc.c b/drivers/media/platform/atmel/atmel-isc.c index d89e14524d42..50178968b8a6 100644 --- a/drivers/media/platform/atmel/atmel-isc.c +++ b/drivers/media/platform/atmel/atmel-isc.c @@ -1238,8 +1238,8 @@ static int isc_querycap(struct file *file, void *priv, { struct isc_device *isc = video_drvdata(file); - strcpy(cap->driver, ATMEL_ISC_NAME); - strcpy(cap->card, "Atmel Image Sensor Controller"); + strscpy(cap->driver, ATMEL_ISC_NAME, sizeof(cap->driver)); + strscpy(cap->card, "Atmel Image Sensor Controller", sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", isc->v4l2_dev.name); @@ -1393,7 +1393,7 @@ static int isc_enum_input(struct file *file, void *priv, inp->type = V4L2_INPUT_TYPE_CAMERA; inp->std = 0; - strcpy(inp->name, "Camera"); + strscpy(inp->name, "Camera", sizeof(inp->name)); return 0; } @@ -1951,7 +1951,7 @@ static int isc_async_complete(struct v4l2_async_notifier *notifier) INIT_WORK(&isc->awb_work, isc_awb_work); /* Register video device */ - strlcpy(vdev->name, ATMEL_ISC_NAME, sizeof(vdev->name)); + strscpy(vdev->name, ATMEL_ISC_NAME, sizeof(vdev->name)); vdev->release = video_device_release_empty; vdev->fops = &isc_fops; vdev->ioctl_ops = &isc_ioctl_ops; @@ -1983,8 +1983,10 @@ static void isc_subdev_cleanup(struct isc_device *isc) { struct isc_subdev_entity *subdev_entity; - list_for_each_entry(subdev_entity, &isc->subdev_entities, list) + list_for_each_entry(subdev_entity, &isc->subdev_entities, list) { v4l2_async_notifier_unregister(&subdev_entity->notifier); + v4l2_async_notifier_cleanup(&subdev_entity->notifier); + } INIT_LIST_HEAD(&isc->subdev_entities); } @@ -2026,7 +2028,6 @@ static int isc_parse_dt(struct device *dev, struct isc_device *isc) { struct device_node *np = dev->of_node; struct device_node *epn = NULL, *rem; - struct v4l2_fwnode_endpoint v4l2_epn; struct isc_subdev_entity *subdev_entity; unsigned int flags; int ret; @@ -2034,6 +2035,8 @@ static int isc_parse_dt(struct device *dev, struct isc_device *isc) INIT_LIST_HEAD(&isc->subdev_entities); while (1) { + struct v4l2_fwnode_endpoint v4l2_epn = { .bus_type = 0 }; + epn = of_graph_get_next_endpoint(np, epn); if (!epn) return 0; @@ -2201,8 +2204,15 @@ static int atmel_isc_probe(struct platform_device *pdev) } list_for_each_entry(subdev_entity, &isc->subdev_entities, list) { - subdev_entity->notifier.subdevs = &subdev_entity->asd; - subdev_entity->notifier.num_subdevs = 1; + v4l2_async_notifier_init(&subdev_entity->notifier); + + ret = v4l2_async_notifier_add_subdev(&subdev_entity->notifier, + subdev_entity->asd); + if (ret) { + fwnode_handle_put(subdev_entity->asd->match.fwnode); + goto cleanup_subdev; + } + subdev_entity->notifier.ops = &isc_async_ops; ret = v4l2_async_notifier_register(&isc->v4l2_dev, diff --git a/drivers/media/platform/atmel/atmel-isi.c b/drivers/media/platform/atmel/atmel-isi.c index e8db4df1e7c4..fdb255e4a956 100644 --- a/drivers/media/platform/atmel/atmel-isi.c +++ b/drivers/media/platform/atmel/atmel-isi.c @@ -655,9 +655,9 @@ static int isi_enum_fmt_vid_cap(struct file *file, void *priv, static int isi_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - strlcpy(cap->driver, "atmel-isi", sizeof(cap->driver)); - strlcpy(cap->card, "Atmel Image Sensor Interface", sizeof(cap->card)); - strlcpy(cap->bus_info, "platform:isi", sizeof(cap->bus_info)); + strscpy(cap->driver, "atmel-isi", sizeof(cap->driver)); + strscpy(cap->card, "Atmel Image Sensor Interface", sizeof(cap->card)); + strscpy(cap->bus_info, "platform:isi", sizeof(cap->bus_info)); return 0; } @@ -668,7 +668,7 @@ static int isi_enum_input(struct file *file, void *priv, return -EINVAL; i->type = V4L2_INPUT_TYPE_CAMERA; - strlcpy(i->name, "Camera", sizeof(i->name)); + strscpy(i->name, "Camera", sizeof(i->name)); return 0; } @@ -790,7 +790,7 @@ static int atmel_isi_parse_dt(struct atmel_isi *isi, struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; - struct v4l2_fwnode_endpoint ep; + struct v4l2_fwnode_endpoint ep = { .bus_type = 0 }; int err; /* Default settings for ISI */ @@ -1124,7 +1124,6 @@ static int isi_graph_parse(struct atmel_isi *isi, struct device_node *node) static int isi_graph_init(struct atmel_isi *isi) { - struct v4l2_async_subdev **subdevs = NULL; int ret; /* Parse the graph to extract a list of subdevice DT nodes. */ @@ -1134,23 +1133,20 @@ static int isi_graph_init(struct atmel_isi *isi) return ret; } - /* Register the subdevices notifier. */ - subdevs = devm_kzalloc(isi->dev, sizeof(*subdevs), GFP_KERNEL); - if (!subdevs) { + v4l2_async_notifier_init(&isi->notifier); + + ret = v4l2_async_notifier_add_subdev(&isi->notifier, &isi->entity.asd); + if (ret) { of_node_put(isi->entity.node); - return -ENOMEM; + return ret; } - subdevs[0] = &isi->entity.asd; - - isi->notifier.subdevs = subdevs; - isi->notifier.num_subdevs = 1; isi->notifier.ops = &isi_graph_notify_ops; ret = v4l2_async_notifier_register(&isi->v4l2_dev, &isi->notifier); if (ret < 0) { dev_err(isi->dev, "Notifier registration failed\n"); - of_node_put(isi->entity.node); + v4l2_async_notifier_cleanup(&isi->notifier); return ret; } @@ -1202,7 +1198,7 @@ static int atmel_isi_probe(struct platform_device *pdev) isi->vdev->fops = &isi_fops; isi->vdev->v4l2_dev = &isi->v4l2_dev; isi->vdev->queue = &isi->queue; - strlcpy(isi->vdev->name, KBUILD_MODNAME, sizeof(isi->vdev->name)); + strscpy(isi->vdev->name, KBUILD_MODNAME, sizeof(isi->vdev->name)); isi->vdev->release = video_device_release; isi->vdev->ioctl_ops = &isi_ioctl_ops; isi->vdev->lock = &isi->lock; @@ -1303,6 +1299,7 @@ static int atmel_isi_remove(struct platform_device *pdev) isi->fb_descriptors_phys); pm_runtime_disable(&pdev->dev); v4l2_async_notifier_unregister(&isi->notifier); + v4l2_async_notifier_cleanup(&isi->notifier); v4l2_device_unregister(&isi->v4l2_dev); return 0; diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c index 43e43c7b3e98..31ace114eda1 100644 --- a/drivers/media/platform/cadence/cdns-csi2rx.c +++ b/drivers/media/platform/cadence/cdns-csi2rx.c @@ -361,7 +361,7 @@ static int csi2rx_get_resources(struct csi2rx_priv *csi2rx, static int csi2rx_parse_dt(struct csi2rx_priv *csi2rx) { - struct v4l2_fwnode_endpoint v4l2_ep; + struct v4l2_fwnode_endpoint v4l2_ep = { .bus_type = 0 }; struct fwnode_handle *fwh; struct device_node *ep; int ret; @@ -378,7 +378,7 @@ static int csi2rx_parse_dt(struct csi2rx_priv *csi2rx) return ret; } - if (v4l2_ep.bus_type != V4L2_MBUS_CSI2) { + if (v4l2_ep.bus_type != V4L2_MBUS_CSI2_DPHY) { dev_err(csi2rx->dev, "Unsupported media bus type: 0x%x\n", v4l2_ep.bus_type); of_node_put(ep); @@ -399,18 +399,22 @@ static int csi2rx_parse_dt(struct csi2rx_priv *csi2rx) csi2rx->asd.match_type = V4L2_ASYNC_MATCH_FWNODE; of_node_put(ep); - csi2rx->notifier.subdevs = devm_kzalloc(csi2rx->dev, - sizeof(*csi2rx->notifier.subdevs), - GFP_KERNEL); - if (!csi2rx->notifier.subdevs) - return -ENOMEM; + v4l2_async_notifier_init(&csi2rx->notifier); + + ret = v4l2_async_notifier_add_subdev(&csi2rx->notifier, &csi2rx->asd); + if (ret) { + fwnode_handle_put(csi2rx->asd.match.fwnode); + return ret; + } - csi2rx->notifier.subdevs[0] = &csi2rx->asd; - csi2rx->notifier.num_subdevs = 1; csi2rx->notifier.ops = &csi2rx_notifier_ops; - return v4l2_async_subdev_notifier_register(&csi2rx->subdev, - &csi2rx->notifier); + ret = v4l2_async_subdev_notifier_register(&csi2rx->subdev, + &csi2rx->notifier); + if (ret) + v4l2_async_notifier_cleanup(&csi2rx->notifier); + + return ret; } static int csi2rx_probe(struct platform_device *pdev) @@ -450,11 +454,11 @@ static int csi2rx_probe(struct platform_device *pdev) ret = media_entity_pads_init(&csi2rx->subdev.entity, CSI2RX_PAD_MAX, csi2rx->pads); if (ret) - goto err_free_priv; + goto err_cleanup; ret = v4l2_async_register_subdev(&csi2rx->subdev); if (ret < 0) - goto err_free_priv; + goto err_cleanup; dev_info(&pdev->dev, "Probed CSI2RX with %u/%u lanes, %u streams, %s D-PHY\n", @@ -463,6 +467,8 @@ static int csi2rx_probe(struct platform_device *pdev) return 0; +err_cleanup: + v4l2_async_notifier_cleanup(&csi2rx->notifier); err_free_priv: kfree(csi2rx); return ret; diff --git a/drivers/media/platform/cadence/cdns-csi2tx.c b/drivers/media/platform/cadence/cdns-csi2tx.c index 40d0de690ff4..5042d053b94e 100644 --- a/drivers/media/platform/cadence/cdns-csi2tx.c +++ b/drivers/media/platform/cadence/cdns-csi2tx.c @@ -432,7 +432,7 @@ static int csi2tx_get_resources(struct csi2tx_priv *csi2tx, static int csi2tx_check_lanes(struct csi2tx_priv *csi2tx) { - struct v4l2_fwnode_endpoint v4l2_ep; + struct v4l2_fwnode_endpoint v4l2_ep = { .bus_type = 0 }; struct device_node *ep; int ret; @@ -446,7 +446,7 @@ static int csi2tx_check_lanes(struct csi2tx_priv *csi2tx) goto out; } - if (v4l2_ep.bus_type != V4L2_MBUS_CSI2) { + if (v4l2_ep.bus_type != V4L2_MBUS_CSI2_DPHY) { dev_err(csi2tx->dev, "Unsupported media bus type: 0x%x\n", v4l2_ep.bus_type); ret = -EINVAL; diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c index 726b3b93a486..2848ea5f464d 100644 --- a/drivers/media/platform/coda/coda-common.c +++ b/drivers/media/platform/coda/coda-common.c @@ -376,8 +376,7 @@ static struct vdoa_data *coda_get_vdoa_data(void) vdoa_data = ERR_PTR(-EPROBE_DEFER); out: - if (vdoa_node) - of_node_put(vdoa_node); + of_node_put(vdoa_node); return vdoa_data; } @@ -390,10 +389,10 @@ static int coda_querycap(struct file *file, void *priv, { struct coda_ctx *ctx = fh_to_ctx(priv); - strlcpy(cap->driver, CODA_NAME, sizeof(cap->driver)); - strlcpy(cap->card, coda_product_name(ctx->dev->devtype->product), + strscpy(cap->driver, CODA_NAME, sizeof(cap->driver)); + strscpy(cap->card, coda_product_name(ctx->dev->devtype->product), sizeof(cap->card)); - strlcpy(cap->bus_info, "platform:" CODA_NAME, sizeof(cap->bus_info)); + strscpy(cap->bus_info, "platform:" CODA_NAME, sizeof(cap->bus_info)); cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; @@ -1804,7 +1803,8 @@ static int coda_s_ctrl(struct v4l2_ctrl *ctrl) break; case V4L2_CID_MPEG_VIDEO_H264_PROFILE: /* TODO: switch between baseline and constrained baseline */ - ctx->params.h264_profile_idc = 66; + if (ctx->inst_type == CODA_INST_ENCODER) + ctx->params.h264_profile_idc = 66; break; case V4L2_CID_MPEG_VIDEO_H264_LEVEL: /* nothing to do, this is set by the encoder */ @@ -2408,7 +2408,7 @@ static int coda_register_device(struct coda_dev *dev, int i) if (i >= dev->devtype->num_vdevs) return -EINVAL; - strlcpy(vfd->name, dev->devtype->vdevs[i]->name, sizeof(vfd->name)); + strscpy(vfd->name, dev->devtype->vdevs[i]->name, sizeof(vfd->name)); vfd->fops = &coda_fops; vfd->ioctl_ops = &coda_ioctl_ops; vfd->release = video_device_release_empty, diff --git a/drivers/media/platform/davinci/isif.c b/drivers/media/platform/davinci/isif.c index f924e76e2fbf..340f8218f54d 100644 --- a/drivers/media/platform/davinci/isif.c +++ b/drivers/media/platform/davinci/isif.c @@ -1100,7 +1100,8 @@ fail_nobase_res: while (i >= 0) { res = platform_get_resource(pdev, IORESOURCE_MEM, i); - release_mem_region(res->start, resource_size(res)); + if (res) + release_mem_region(res->start, resource_size(res)); i--; } vpfe_unregister_ccdc_device(&isif_hw_dev); diff --git a/drivers/media/platform/davinci/vpbe_display.c b/drivers/media/platform/davinci/vpbe_display.c index b0eb3d899eb4..5c235898af7b 100644 --- a/drivers/media/platform/davinci/vpbe_display.c +++ b/drivers/media/platform/davinci/vpbe_display.c @@ -521,7 +521,7 @@ vpbe_disp_calculate_scale_factor(struct vpbe_display *disp_dev, else if (v_scale == 4) layer_info->v_zoom = ZOOM_X4; if (v_exp) - layer_info->h_exp = V_EXP_6_OVER_5; + layer_info->v_exp = V_EXP_6_OVER_5; } else { /* no scaling, only cropping. Set display area to crop area */ cfg->ysize = expected_ysize; @@ -647,7 +647,7 @@ static int vpbe_display_querycap(struct file *file, void *priv, dev_name(vpbe_dev->pdev)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", dev_name(vpbe_dev->pdev)); - strlcpy(cap->card, vpbe_dev->cfg->module_name, sizeof(cap->card)); + strscpy(cap->card, vpbe_dev->cfg->module_name, sizeof(cap->card)); return 0; } @@ -816,10 +816,12 @@ static int vpbe_display_enum_fmt(struct file *file, void *priv, fmt->index = index; fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; if (index == 0) { - strcpy(fmt->description, "YUV 4:2:2 - UYVY"); + strscpy(fmt->description, "YUV 4:2:2 - UYVY", + sizeof(fmt->description)); fmt->pixelformat = V4L2_PIX_FMT_UYVY; } else { - strcpy(fmt->description, "Y/CbCr 4:2:0"); + strscpy(fmt->description, "Y/CbCr 4:2:0", + sizeof(fmt->description)); fmt->pixelformat = V4L2_PIX_FMT_NV12; } diff --git a/drivers/media/platform/davinci/vpbe_venc.c b/drivers/media/platform/davinci/vpbe_venc.c index ddcad7b3e76c..ca78eb29641a 100644 --- a/drivers/media/platform/davinci/vpbe_venc.c +++ b/drivers/media/platform/davinci/vpbe_venc.c @@ -616,7 +616,7 @@ struct v4l2_subdev *venc_sub_dev_init(struct v4l2_device *v4l2_dev, v4l2_subdev_init(&venc->sd, &venc_ops); - strcpy(venc->sd.name, venc_name); + strscpy(venc->sd.name, venc_name, sizeof(venc->sd.name)); if (v4l2_device_register_subdev(v4l2_dev, &venc->sd) < 0) { v4l2_err(v4l2_dev, "vpbe unable to register venc sub device\n"); diff --git a/drivers/media/platform/davinci/vpfe_capture.c b/drivers/media/platform/davinci/vpfe_capture.c index 8613358ed245..ea3ddd5a42bd 100644 --- a/drivers/media/platform/davinci/vpfe_capture.c +++ b/drivers/media/platform/davinci/vpfe_capture.c @@ -889,9 +889,9 @@ static int vpfe_querycap(struct file *file, void *priv, cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; - strlcpy(cap->driver, CAPTURE_DRV_NAME, sizeof(cap->driver)); - strlcpy(cap->bus_info, "VPFE", sizeof(cap->bus_info)); - strlcpy(cap->card, vpfe_dev->cfg->card_name, sizeof(cap->card)); + strscpy(cap->driver, CAPTURE_DRV_NAME, sizeof(cap->driver)); + strscpy(cap->bus_info, "VPFE", sizeof(cap->bus_info)); + strscpy(cap->card, vpfe_dev->cfg->card_name, sizeof(cap->card)); return 0; } diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c index a96f53ce8088..6216b7ac6875 100644 --- a/drivers/media/platform/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c @@ -949,11 +949,13 @@ static int vpif_enum_fmt_vid_cap(struct file *file, void *priv, /* Fill in the information about format */ if (ch->vpifparams.iface.if_type == VPIF_IF_RAW_BAYER) { fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - strcpy(fmt->description, "Raw Mode -Bayer Pattern GrRBGb"); + strscpy(fmt->description, "Raw Mode -Bayer Pattern GrRBGb", + sizeof(fmt->description)); fmt->pixelformat = V4L2_PIX_FMT_SBGGR8; } else { fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - strcpy(fmt->description, "YCbCr4:2:2 Semi-Planar"); + strscpy(fmt->description, "YCbCr4:2:2 Semi-Planar", + sizeof(fmt->description)); fmt->pixelformat = V4L2_PIX_FMT_NV16; } return 0; @@ -1094,10 +1096,10 @@ static int vpif_querycap(struct file *file, void *priv, cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; - strlcpy(cap->driver, VPIF_DRIVER_NAME, sizeof(cap->driver)); + strscpy(cap->driver, VPIF_DRIVER_NAME, sizeof(cap->driver)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", dev_name(vpif_dev)); - strlcpy(cap->card, config->card_name, sizeof(cap->card)); + strscpy(cap->card, config->card_name, sizeof(cap->card)); return 0; } @@ -1463,7 +1465,7 @@ static int vpif_probe_complete(void) /* Initialize the video_device structure */ vdev = &ch->video_dev; - strlcpy(vdev->name, VPIF_DRIVER_NAME, sizeof(vdev->name)); + strscpy(vdev->name, VPIF_DRIVER_NAME, sizeof(vdev->name)); vdev->release = video_device_release_empty; vdev->fops = &vpif_fops; vdev->ioctl_ops = &vpif_ioctl_ops; @@ -1509,12 +1511,13 @@ static struct vpif_capture_config * vpif_capture_get_pdata(struct platform_device *pdev) { struct device_node *endpoint = NULL; - struct v4l2_fwnode_endpoint bus_cfg; struct vpif_capture_config *pdata; struct vpif_subdev_info *sdinfo; struct vpif_capture_chan_config *chan; unsigned int i; + v4l2_async_notifier_init(&vpif_obj.notifier); + /* * DT boot: OF node from parent device contains * video ports & endpoints data. @@ -1537,6 +1540,7 @@ vpif_capture_get_pdata(struct platform_device *pdev) return NULL; for (i = 0; i < VPIF_CAPTURE_NUM_CHANNELS; i++) { + struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 }; struct device_node *rem; unsigned int flags; int err; @@ -1546,14 +1550,25 @@ vpif_capture_get_pdata(struct platform_device *pdev) if (!endpoint) break; + rem = of_graph_get_remote_port_parent(endpoint); + if (!rem) { + dev_dbg(&pdev->dev, "Remote device at %pOF not found\n", + endpoint); + of_node_put(endpoint); + goto done; + } + sdinfo = &pdata->subdev_info[i]; chan = &pdata->chan_config[i]; chan->inputs = devm_kcalloc(&pdev->dev, VPIF_CAPTURE_NUM_CHANNELS, sizeof(*chan->inputs), GFP_KERNEL); - if (!chan->inputs) - return NULL; + if (!chan->inputs) { + of_node_put(rem); + of_node_put(endpoint); + goto err_cleanup; + } chan->input_count++; chan->inputs[i].input.type = V4L2_INPUT_TYPE_CAMERA; @@ -1562,12 +1577,16 @@ vpif_capture_get_pdata(struct platform_device *pdev) err = v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint), &bus_cfg); + of_node_put(endpoint); if (err) { dev_err(&pdev->dev, "Could not parse the endpoint\n"); + of_node_put(rem); goto done; } + dev_dbg(&pdev->dev, "Endpoint %pOF, bus_width = %d\n", endpoint, bus_cfg.bus.parallel.bus_width); + flags = bus_cfg.bus.parallel.flags; if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) @@ -1576,39 +1595,29 @@ vpif_capture_get_pdata(struct platform_device *pdev) if (flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) chan->vpif_if.vd_pol = 1; - rem = of_graph_get_remote_port_parent(endpoint); - if (!rem) { - dev_dbg(&pdev->dev, "Remote device at %pOF not found\n", - endpoint); - goto done; - } - - dev_dbg(&pdev->dev, "Remote device %s, %pOF found\n", - rem->name, rem); + dev_dbg(&pdev->dev, "Remote device %pOF found\n", rem); sdinfo->name = rem->full_name; - pdata->asd[i] = devm_kzalloc(&pdev->dev, - sizeof(struct v4l2_async_subdev), - GFP_KERNEL); - if (!pdata->asd[i]) { + pdata->asd[i] = v4l2_async_notifier_add_fwnode_subdev( + &vpif_obj.notifier, of_fwnode_handle(rem), + sizeof(struct v4l2_async_subdev)); + if (IS_ERR(pdata->asd[i])) { of_node_put(rem); - pdata = NULL; - goto done; + goto err_cleanup; } - - pdata->asd[i]->match_type = V4L2_ASYNC_MATCH_FWNODE; - pdata->asd[i]->match.fwnode = of_fwnode_handle(rem); - of_node_put(rem); } done: - if (pdata) { - pdata->asd_sizes[0] = i; - pdata->subdev_count = i; - pdata->card_name = "DA850/OMAP-L138 Video Capture"; - } + pdata->asd_sizes[0] = i; + pdata->subdev_count = i; + pdata->card_name = "DA850/OMAP-L138 Video Capture"; return pdata; + +err_cleanup: + v4l2_async_notifier_cleanup(&vpif_obj.notifier); + + return NULL; } /** @@ -1633,23 +1642,18 @@ static __init int vpif_probe(struct platform_device *pdev) return -EINVAL; } - if (!pdev->dev.platform_data) { - dev_warn(&pdev->dev, "Missing platform data. Giving up.\n"); - return -EINVAL; - } - vpif_dev = &pdev->dev; err = initialize_vpif(); if (err) { v4l2_err(vpif_dev->driver, "Error initializing vpif\n"); - return err; + goto cleanup; } err = v4l2_device_register(vpif_dev, &vpif_obj.v4l2_dev); if (err) { v4l2_err(vpif_dev->driver, "Error registering v4l2 device\n"); - return err; + goto cleanup; } while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, res_idx))) { @@ -1698,8 +1702,6 @@ static __init int vpif_probe(struct platform_device *pdev) } vpif_probe_complete(); } else { - vpif_obj.notifier.subdevs = vpif_obj.config->asd; - vpif_obj.notifier.num_subdevs = vpif_obj.config->asd_sizes[0]; vpif_obj.notifier.ops = &vpif_async_ops; err = v4l2_async_notifier_register(&vpif_obj.v4l2_dev, &vpif_obj.notifier); @@ -1717,6 +1719,8 @@ probe_subdev_out: kfree(vpif_obj.sd); vpif_unregister: v4l2_device_unregister(&vpif_obj.v4l2_dev); +cleanup: + v4l2_async_notifier_cleanup(&vpif_obj.notifier); return err; } @@ -1732,6 +1736,8 @@ static int vpif_remove(struct platform_device *device) struct channel_obj *ch; int i; + v4l2_async_notifier_unregister(&vpif_obj.notifier); + v4l2_async_notifier_cleanup(&vpif_obj.notifier); v4l2_device_unregister(&vpif_obj.v4l2_dev); kfree(vpif_obj.sd); diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c index 0f324055cc9f..3517487d9760 100644 --- a/drivers/media/platform/davinci/vpif_display.c +++ b/drivers/media/platform/davinci/vpif_display.c @@ -586,10 +586,10 @@ static int vpif_querycap(struct file *file, void *priv, cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; - strlcpy(cap->driver, VPIF_DRIVER_NAME, sizeof(cap->driver)); + strscpy(cap->driver, VPIF_DRIVER_NAME, sizeof(cap->driver)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", dev_name(vpif_dev)); - strlcpy(cap->card, config->card_name, sizeof(cap->card)); + strscpy(cap->card, config->card_name, sizeof(cap->card)); return 0; } @@ -602,7 +602,8 @@ static int vpif_enum_fmt_vid_out(struct file *file, void *priv, /* Fill in the information about format */ fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - strcpy(fmt->description, "YCbCr4:2:2 YC Planar"); + strscpy(fmt->description, "YCbCr4:2:2 YC Planar", + sizeof(fmt->description)); fmt->pixelformat = V4L2_PIX_FMT_YUV422P; fmt->flags = 0; return 0; @@ -1209,7 +1210,7 @@ static int vpif_probe_complete(void) /* Initialize the video_device structure */ vdev = &ch->video_dev; - strlcpy(vdev->name, VPIF_DRIVER_NAME, sizeof(vdev->name)); + strscpy(vdev->name, VPIF_DRIVER_NAME, sizeof(vdev->name)); vdev->release = video_device_release_empty; vdev->fops = &vpif_fops; vdev->ioctl_ops = &vpif_ioctl_ops; @@ -1299,6 +1300,8 @@ static __init int vpif_probe(struct platform_device *pdev) goto vpif_unregister; } + v4l2_async_notifier_init(&vpif_obj.notifier); + if (!vpif_obj.config->asd_sizes) { i2c_adap = i2c_get_adapter(vpif_obj.config->i2c_adapter_id); for (i = 0; i < subdev_count; i++) { @@ -1322,20 +1325,27 @@ static __init int vpif_probe(struct platform_device *pdev) goto probe_subdev_out; } } else { - vpif_obj.notifier.subdevs = vpif_obj.config->asd; - vpif_obj.notifier.num_subdevs = vpif_obj.config->asd_sizes[0]; + for (i = 0; i < vpif_obj.config->asd_sizes[0]; i++) { + err = v4l2_async_notifier_add_subdev( + &vpif_obj.notifier, vpif_obj.config->asd[i]); + if (err) + goto probe_cleanup; + } + vpif_obj.notifier.ops = &vpif_async_ops; err = v4l2_async_notifier_register(&vpif_obj.v4l2_dev, &vpif_obj.notifier); if (err) { vpif_err("Error registering async notifier\n"); err = -EINVAL; - goto probe_subdev_out; + goto probe_cleanup; } } return 0; +probe_cleanup: + v4l2_async_notifier_cleanup(&vpif_obj.notifier); probe_subdev_out: kfree(vpif_obj.sd); vpif_unregister: @@ -1354,6 +1364,11 @@ static int vpif_remove(struct platform_device *device) struct channel_obj *ch; int i; + if (vpif_obj.config->asd_sizes) { + v4l2_async_notifier_unregister(&vpif_obj.notifier); + v4l2_async_notifier_cleanup(&vpif_obj.notifier); + } + v4l2_device_unregister(&vpif_obj.v4l2_dev); kfree(vpif_obj.sd); diff --git a/drivers/media/platform/exynos-gsc/gsc-core.c b/drivers/media/platform/exynos-gsc/gsc-core.c index 17854a379243..838c5c53de37 100644 --- a/drivers/media/platform/exynos-gsc/gsc-core.c +++ b/drivers/media/platform/exynos-gsc/gsc-core.c @@ -339,7 +339,7 @@ int gsc_enum_fmt_mplane(struct v4l2_fmtdesc *f) if (!fmt) return -EINVAL; - strlcpy(f->description, fmt->name, sizeof(f->description)); + strscpy(f->description, fmt->name, sizeof(f->description)); f->pixelformat = fmt->pixelformat; return 0; diff --git a/drivers/media/platform/exynos-gsc/gsc-m2m.c b/drivers/media/platform/exynos-gsc/gsc-m2m.c index c9d2f6c5311a..cc5d690818e1 100644 --- a/drivers/media/platform/exynos-gsc/gsc-m2m.c +++ b/drivers/media/platform/exynos-gsc/gsc-m2m.c @@ -294,8 +294,8 @@ static int gsc_m2m_querycap(struct file *file, void *fh, struct gsc_ctx *ctx = fh_to_ctx(fh); struct gsc_dev *gsc = ctx->gsc_dev; - strlcpy(cap->driver, GSC_MODULE_NAME, sizeof(cap->driver)); - strlcpy(cap->card, GSC_MODULE_NAME " gscaler", sizeof(cap->card)); + strscpy(cap->driver, GSC_MODULE_NAME, sizeof(cap->driver)); + strscpy(cap->card, GSC_MODULE_NAME " gscaler", sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", dev_name(&gsc->pdev->dev)); cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE; diff --git a/drivers/media/platform/exynos4-is/common.c b/drivers/media/platform/exynos4-is/common.c index b90f5bb15517..76f557548dfc 100644 --- a/drivers/media/platform/exynos4-is/common.c +++ b/drivers/media/platform/exynos4-is/common.c @@ -40,8 +40,8 @@ EXPORT_SYMBOL(fimc_find_remote_sensor); void __fimc_vidioc_querycap(struct device *dev, struct v4l2_capability *cap, unsigned int caps) { - strlcpy(cap->driver, dev->driver->name, sizeof(cap->driver)); - strlcpy(cap->card, dev->driver->name, sizeof(cap->card)); + strscpy(cap->driver, dev->driver->name, sizeof(cap->driver)); + strscpy(cap->card, dev->driver->name, sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", dev_name(dev)); cap->device_caps = caps; diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c index a3cdac188190..f56220e549bb 100644 --- a/drivers/media/platform/exynos4-is/fimc-capture.c +++ b/drivers/media/platform/exynos4-is/fimc-capture.c @@ -1087,7 +1087,7 @@ static int fimc_cap_enum_input(struct file *file, void *priv, fimc_md_graph_unlock(ve); if (sd) - strlcpy(i->name, sd->name, sizeof(i->name)); + strscpy(i->name, sd->name, sizeof(i->name)); return 0; } diff --git a/drivers/media/platform/exynos4-is/fimc-is-i2c.c b/drivers/media/platform/exynos4-is/fimc-is-i2c.c index 70dd4852b2b9..be937caf7645 100644 --- a/drivers/media/platform/exynos4-is/fimc-is-i2c.c +++ b/drivers/media/platform/exynos4-is/fimc-is-i2c.c @@ -57,7 +57,7 @@ static int fimc_is_i2c_probe(struct platform_device *pdev) i2c_adap = &isp_i2c->adapter; i2c_adap->dev.of_node = node; i2c_adap->dev.parent = &pdev->dev; - strlcpy(i2c_adap->name, "exynos4x12-isp-i2c", sizeof(i2c_adap->name)); + strscpy(i2c_adap->name, "exynos4x12-isp-i2c", sizeof(i2c_adap->name)); i2c_adap->owner = THIS_MODULE; i2c_adap->algo = &fimc_is_i2c_algorithm; i2c_adap->class = I2C_CLASS_SPD; diff --git a/drivers/media/platform/exynos4-is/fimc-is.c b/drivers/media/platform/exynos4-is/fimc-is.c index 5ddb2321e9e4..f5fc54de19da 100644 --- a/drivers/media/platform/exynos4-is/fimc-is.c +++ b/drivers/media/platform/exynos4-is/fimc-is.c @@ -656,7 +656,7 @@ static int fimc_is_hw_open_sensor(struct fimc_is *is, int fimc_is_hw_initialize(struct fimc_is *is) { - const int config_ids[] = { + static const int config_ids[] = { IS_SC_PREVIEW_STILL, IS_SC_PREVIEW_VIDEO, IS_SC_CAPTURE_STILL, IS_SC_CAPTURE_VIDEO }; diff --git a/drivers/media/platform/exynos4-is/fimc-isp-video.c b/drivers/media/platform/exynos4-is/fimc-isp-video.c index a920164f53f1..de6bd28f7e31 100644 --- a/drivers/media/platform/exynos4-is/fimc-isp-video.c +++ b/drivers/media/platform/exynos4-is/fimc-isp-video.c @@ -365,7 +365,7 @@ static int isp_video_enum_fmt_mplane(struct file *file, void *priv, if (WARN_ON(fmt == NULL)) return -EINVAL; - strlcpy(f->description, fmt->name, sizeof(f->description)); + strscpy(f->description, fmt->name, sizeof(f->description)); f->pixelformat = fmt->fourcc; return 0; diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c index 70d5f5586a5d..96f0a8a0dcae 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite.c +++ b/drivers/media/platform/exynos4-is/fimc-lite.c @@ -654,8 +654,8 @@ static int fimc_lite_querycap(struct file *file, void *priv, { struct fimc_lite *fimc = video_drvdata(file); - strlcpy(cap->driver, FIMC_LITE_DRV_NAME, sizeof(cap->driver)); - strlcpy(cap->card, FIMC_LITE_DRV_NAME, sizeof(cap->card)); + strscpy(cap->driver, FIMC_LITE_DRV_NAME, sizeof(cap->driver)); + strscpy(cap->card, FIMC_LITE_DRV_NAME, sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", dev_name(&fimc->pdev->dev)); @@ -673,7 +673,7 @@ static int fimc_lite_enum_fmt_mplane(struct file *file, void *priv, return -EINVAL; fmt = &fimc_lite_formats[f->index]; - strlcpy(f->description, fmt->name, sizeof(f->description)); + strscpy(f->description, fmt->name, sizeof(f->description)); f->pixelformat = fmt->fourcc; return 0; diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index deb499f76412..870501b0f351 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c @@ -390,7 +390,7 @@ static int fimc_md_parse_port_node(struct fimc_md *fmd, { struct fimc_source_info *pd = &fmd->sensor[index].pdata; struct device_node *rem, *ep, *np; - struct v4l2_fwnode_endpoint endpoint; + struct v4l2_fwnode_endpoint endpoint = { .bus_type = 0 }; int ret; /* Assume here a port node can have only one endpoint node. */ @@ -457,11 +457,16 @@ static int fimc_md_parse_port_node(struct fimc_md *fmd, fmd->sensor[index].asd.match_type = V4L2_ASYNC_MATCH_FWNODE; fmd->sensor[index].asd.match.fwnode = of_fwnode_handle(rem); - fmd->async_subdevs[index] = &fmd->sensor[index].asd; + + ret = v4l2_async_notifier_add_subdev(&fmd->subdev_notifier, + &fmd->sensor[index].asd); + if (ret) { + of_node_put(rem); + return ret; + } fmd->num_sensors++; - of_node_put(rem); return 0; } @@ -500,7 +505,7 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd) ret = fimc_md_parse_port_node(fmd, port, index); if (ret < 0) { of_node_put(node); - goto rpm_put; + goto cleanup; } index++; } @@ -514,12 +519,18 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd) ret = fimc_md_parse_port_node(fmd, node, index); if (ret < 0) { of_node_put(node); - break; + goto cleanup; } index++; } + rpm_put: pm_runtime_put(fmd->pmf); + return 0; + +cleanup: + v4l2_async_notifier_cleanup(&fmd->subdev_notifier); + pm_runtime_put(fmd->pmf); return ret; } @@ -1204,9 +1215,9 @@ static ssize_t fimc_md_sysfs_show(struct device *dev, struct fimc_md *fmd = dev_get_drvdata(dev); if (fmd->user_subdev_api) - return strlcpy(buf, "Sub-device API (sub-dev)\n", PAGE_SIZE); + return strscpy(buf, "Sub-device API (sub-dev)\n", PAGE_SIZE); - return strlcpy(buf, "V4L2 video node only API (vid-dev)\n", PAGE_SIZE); + return strscpy(buf, "V4L2 video node only API (vid-dev)\n", PAGE_SIZE); } static ssize_t fimc_md_sysfs_store(struct device *dev, @@ -1426,7 +1437,7 @@ static int fimc_md_probe(struct platform_device *pdev) INIT_LIST_HEAD(&fmd->pipelines); fmd->pdev = pdev; - strlcpy(fmd->media_dev.model, "SAMSUNG S5P FIMC", + strscpy(fmd->media_dev.model, "SAMSUNG S5P FIMC", sizeof(fmd->media_dev.model)); fmd->media_dev.ops = &fimc_md_ops; fmd->media_dev.dev = dev; @@ -1434,7 +1445,7 @@ static int fimc_md_probe(struct platform_device *pdev) v4l2_dev = &fmd->v4l2_dev; v4l2_dev->mdev = &fmd->media_dev; v4l2_dev->notify = fimc_sensor_notify; - strlcpy(v4l2_dev->name, "s5p-fimc-md", sizeof(v4l2_dev->name)); + strscpy(v4l2_dev->name, "s5p-fimc-md", sizeof(v4l2_dev->name)); fmd->use_isp = fimc_md_is_isp_available(dev->of_node); fmd->user_subdev_api = true; @@ -1460,6 +1471,8 @@ static int fimc_md_probe(struct platform_device *pdev) platform_set_drvdata(pdev, fmd); + v4l2_async_notifier_init(&fmd->subdev_notifier); + ret = fimc_md_register_platform_entities(fmd, dev->of_node); if (ret) goto err_clk; @@ -1470,7 +1483,7 @@ static int fimc_md_probe(struct platform_device *pdev) ret = device_create_file(&pdev->dev, &dev_attr_subdev_conf_mode); if (ret) - goto err_m_ent; + goto err_cleanup; /* * FIMC platform devices need to be registered before the sclk_cam * clocks provider, as one of these devices needs to be activated @@ -1483,8 +1496,6 @@ static int fimc_md_probe(struct platform_device *pdev) } if (fmd->num_sensors > 0) { - fmd->subdev_notifier.subdevs = fmd->async_subdevs; - fmd->subdev_notifier.num_subdevs = fmd->num_sensors; fmd->subdev_notifier.ops = &subdev_notifier_ops; fmd->num_sensors = 0; @@ -1500,10 +1511,12 @@ err_clk_p: fimc_md_unregister_clk_provider(fmd); err_attr: device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode); -err_clk: - fimc_md_put_clocks(fmd); +err_cleanup: + v4l2_async_notifier_cleanup(&fmd->subdev_notifier); err_m_ent: fimc_md_unregister_entities(fmd); +err_clk: + fimc_md_put_clocks(fmd); err_md: media_device_cleanup(&fmd->media_dev); v4l2_device_unregister(&fmd->v4l2_dev); @@ -1519,6 +1532,7 @@ static int fimc_md_remove(struct platform_device *pdev) fimc_md_unregister_clk_provider(fmd); v4l2_async_notifier_unregister(&fmd->subdev_notifier); + v4l2_async_notifier_cleanup(&fmd->subdev_notifier); v4l2_device_unregister(&fmd->v4l2_dev); device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode); diff --git a/drivers/media/platform/exynos4-is/media-dev.h b/drivers/media/platform/exynos4-is/media-dev.h index 957787a2f480..9f527670395a 100644 --- a/drivers/media/platform/exynos4-is/media-dev.h +++ b/drivers/media/platform/exynos4-is/media-dev.h @@ -149,7 +149,6 @@ struct fimc_md { } clk_provider; struct v4l2_async_notifier subdev_notifier; - struct v4l2_async_subdev *async_subdevs[FIMC_MAX_SENSORS]; bool user_subdev_api; spinlock_t slock; diff --git a/drivers/media/platform/exynos4-is/mipi-csis.c b/drivers/media/platform/exynos4-is/mipi-csis.c index b4e28a299e26..35cb0162085b 100644 --- a/drivers/media/platform/exynos4-is/mipi-csis.c +++ b/drivers/media/platform/exynos4-is/mipi-csis.c @@ -718,7 +718,7 @@ static int s5pcsis_parse_dt(struct platform_device *pdev, struct csis_state *state) { struct device_node *node = pdev->dev.of_node; - struct v4l2_fwnode_endpoint endpoint; + struct v4l2_fwnode_endpoint endpoint = { .bus_type = 0 }; int ret; if (of_property_read_u32(node, "clock-frequency", diff --git a/drivers/media/platform/fsl-viu.c b/drivers/media/platform/fsl-viu.c index 0273302aa741..ca6d0317ab42 100644 --- a/drivers/media/platform/fsl-viu.c +++ b/drivers/media/platform/fsl-viu.c @@ -565,9 +565,9 @@ static const struct videobuf_queue_ops viu_video_qops = { static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - strcpy(cap->driver, "viu"); - strcpy(cap->card, "viu"); - strcpy(cap->bus_info, "platform:viu"); + strscpy(cap->driver, "viu", sizeof(cap->driver)); + strscpy(cap->card, "viu", sizeof(cap->card)); + strscpy(cap->bus_info, "platform:viu", sizeof(cap->bus_info)); cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OVERLAY | @@ -941,7 +941,7 @@ static int vidioc_enum_input(struct file *file, void *priv, inp->type = V4L2_INPUT_TYPE_CAMERA; inp->std = fh->dev->vdev->tvnorms; - strcpy(inp->name, "Camera"); + strscpy(inp->name, "Camera", sizeof(inp->name)); return 0; } diff --git a/drivers/media/platform/imx-pxp.c b/drivers/media/platform/imx-pxp.c new file mode 100644 index 000000000000..b76cd0e8313c --- /dev/null +++ b/drivers/media/platform/imx-pxp.c @@ -0,0 +1,1754 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * i.MX Pixel Pipeline (PXP) mem-to-mem scaler/CSC/rotator driver + * + * Copyright (c) 2018 Pengutronix, Philipp Zabel + * + * based on vim2m + * + * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * Pawel Osciak, <pawel@osciak.com> + * Marek Szyprowski, <m.szyprowski@samsung.com> + */ +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/dma-mapping.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/iopoll.h> +#include <linux/interrupt.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/sched.h> +#include <linux/slab.h> + +#include <linux/platform_device.h> +#include <media/v4l2-mem2mem.h> +#include <media/v4l2-device.h> +#include <media/v4l2-ioctl.h> +#include <media/v4l2-ctrls.h> +#include <media/v4l2-event.h> +#include <media/videobuf2-dma-contig.h> + +#include "imx-pxp.h" + +static unsigned int debug; +module_param(debug, uint, 0644); +MODULE_PARM_DESC(debug, "activates debug info"); + +#define MIN_W 8 +#define MIN_H 8 +#define MAX_W 4096 +#define MAX_H 4096 +#define ALIGN_W 3 /* 8x8 pixel blocks */ +#define ALIGN_H 3 + +/* Flags that indicate a format can be used for capture/output */ +#define MEM2MEM_CAPTURE (1 << 0) +#define MEM2MEM_OUTPUT (1 << 1) + +#define MEM2MEM_NAME "pxp" + +/* Flags that indicate processing mode */ +#define MEM2MEM_HFLIP (1 << 0) +#define MEM2MEM_VFLIP (1 << 1) + +#define dprintk(dev, fmt, arg...) \ + v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg) + +struct pxp_fmt { + u32 fourcc; + int depth; + /* Types the format can be used for */ + u32 types; +}; + +static struct pxp_fmt formats[] = { + { + .fourcc = V4L2_PIX_FMT_XBGR32, + .depth = 32, + /* Both capture and output format */ + .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, + }, { + .fourcc = V4L2_PIX_FMT_ABGR32, + .depth = 32, + /* Capture-only format */ + .types = MEM2MEM_CAPTURE, + }, { + .fourcc = V4L2_PIX_FMT_BGR24, + .depth = 24, + .types = MEM2MEM_CAPTURE, + }, { + .fourcc = V4L2_PIX_FMT_RGB565, + .depth = 16, + .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, + }, { + .fourcc = V4L2_PIX_FMT_RGB555, + .depth = 16, + .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, + }, { + .fourcc = V4L2_PIX_FMT_RGB444, + .depth = 16, + .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, + }, { + .fourcc = V4L2_PIX_FMT_YUV32, + .depth = 32, + .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, + }, { + .fourcc = V4L2_PIX_FMT_UYVY, + .depth = 16, + .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, + }, { + .fourcc = V4L2_PIX_FMT_YUYV, + .depth = 16, + /* Output-only format */ + .types = MEM2MEM_OUTPUT, + }, { + .fourcc = V4L2_PIX_FMT_VYUY, + .depth = 16, + .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, + }, { + .fourcc = V4L2_PIX_FMT_YVYU, + .depth = 16, + .types = MEM2MEM_OUTPUT, + }, { + .fourcc = V4L2_PIX_FMT_GREY, + .depth = 8, + .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, + }, { + .fourcc = V4L2_PIX_FMT_Y4, + .depth = 4, + .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, + }, { + .fourcc = V4L2_PIX_FMT_NV16, + .depth = 16, + .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, + }, { + .fourcc = V4L2_PIX_FMT_NV12, + .depth = 12, + .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, + }, { + .fourcc = V4L2_PIX_FMT_NV21, + .depth = 12, + .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, + }, { + .fourcc = V4L2_PIX_FMT_NV61, + .depth = 16, + .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, + }, { + .fourcc = V4L2_PIX_FMT_YUV422P, + .depth = 16, + .types = MEM2MEM_OUTPUT, + }, { + .fourcc = V4L2_PIX_FMT_YUV420, + .depth = 12, + .types = MEM2MEM_OUTPUT, + }, +}; + +#define NUM_FORMATS ARRAY_SIZE(formats) + +/* Per-queue, driver-specific private data */ +struct pxp_q_data { + unsigned int width; + unsigned int height; + unsigned int bytesperline; + unsigned int sizeimage; + unsigned int sequence; + struct pxp_fmt *fmt; + enum v4l2_ycbcr_encoding ycbcr_enc; + enum v4l2_quantization quant; +}; + +enum { + V4L2_M2M_SRC = 0, + V4L2_M2M_DST = 1, +}; + +static struct pxp_fmt *find_format(struct v4l2_format *f) +{ + struct pxp_fmt *fmt; + unsigned int k; + + for (k = 0; k < NUM_FORMATS; k++) { + fmt = &formats[k]; + if (fmt->fourcc == f->fmt.pix.pixelformat) + break; + } + + if (k == NUM_FORMATS) + return NULL; + + return &formats[k]; +} + +struct pxp_dev { + struct v4l2_device v4l2_dev; + struct video_device vfd; + + struct clk *clk; + void __iomem *mmio; + + atomic_t num_inst; + struct mutex dev_mutex; + spinlock_t irqlock; + + struct v4l2_m2m_dev *m2m_dev; +}; + +struct pxp_ctx { + struct v4l2_fh fh; + struct pxp_dev *dev; + + struct v4l2_ctrl_handler hdl; + + /* Abort requested by m2m */ + int aborting; + + /* Processing mode */ + int mode; + u8 alpha_component; + + enum v4l2_colorspace colorspace; + enum v4l2_xfer_func xfer_func; + + /* Source and destination queue data */ + struct pxp_q_data q_data[2]; +}; + +static inline struct pxp_ctx *file2ctx(struct file *file) +{ + return container_of(file->private_data, struct pxp_ctx, fh); +} + +static struct pxp_q_data *get_q_data(struct pxp_ctx *ctx, + enum v4l2_buf_type type) +{ + if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT) + return &ctx->q_data[V4L2_M2M_SRC]; + else + return &ctx->q_data[V4L2_M2M_DST]; +} + +static u32 pxp_v4l2_pix_fmt_to_ps_format(u32 v4l2_pix_fmt) +{ + switch (v4l2_pix_fmt) { + case V4L2_PIX_FMT_XBGR32: return BV_PXP_PS_CTRL_FORMAT__RGB888; + case V4L2_PIX_FMT_RGB555: return BV_PXP_PS_CTRL_FORMAT__RGB555; + case V4L2_PIX_FMT_RGB444: return BV_PXP_PS_CTRL_FORMAT__RGB444; + case V4L2_PIX_FMT_RGB565: return BV_PXP_PS_CTRL_FORMAT__RGB565; + case V4L2_PIX_FMT_YUV32: return BV_PXP_PS_CTRL_FORMAT__YUV1P444; + case V4L2_PIX_FMT_UYVY: return BV_PXP_PS_CTRL_FORMAT__UYVY1P422; + case V4L2_PIX_FMT_YUYV: return BM_PXP_PS_CTRL_WB_SWAP | + BV_PXP_PS_CTRL_FORMAT__UYVY1P422; + case V4L2_PIX_FMT_VYUY: return BV_PXP_PS_CTRL_FORMAT__VYUY1P422; + case V4L2_PIX_FMT_YVYU: return BM_PXP_PS_CTRL_WB_SWAP | + BV_PXP_PS_CTRL_FORMAT__VYUY1P422; + case V4L2_PIX_FMT_GREY: return BV_PXP_PS_CTRL_FORMAT__Y8; + default: + case V4L2_PIX_FMT_Y4: return BV_PXP_PS_CTRL_FORMAT__Y4; + case V4L2_PIX_FMT_NV16: return BV_PXP_PS_CTRL_FORMAT__YUV2P422; + case V4L2_PIX_FMT_NV12: return BV_PXP_PS_CTRL_FORMAT__YUV2P420; + case V4L2_PIX_FMT_NV21: return BV_PXP_PS_CTRL_FORMAT__YVU2P420; + case V4L2_PIX_FMT_NV61: return BV_PXP_PS_CTRL_FORMAT__YVU2P422; + case V4L2_PIX_FMT_YUV422P: return BV_PXP_PS_CTRL_FORMAT__YUV422; + case V4L2_PIX_FMT_YUV420: return BV_PXP_PS_CTRL_FORMAT__YUV420; + } +} + +static u32 pxp_v4l2_pix_fmt_to_out_format(u32 v4l2_pix_fmt) +{ + switch (v4l2_pix_fmt) { + case V4L2_PIX_FMT_XBGR32: return BV_PXP_OUT_CTRL_FORMAT__RGB888; + case V4L2_PIX_FMT_ABGR32: return BV_PXP_OUT_CTRL_FORMAT__ARGB8888; + case V4L2_PIX_FMT_BGR24: return BV_PXP_OUT_CTRL_FORMAT__RGB888P; + /* Missing V4L2 pixel formats for ARGB1555 and ARGB4444 */ + case V4L2_PIX_FMT_RGB555: return BV_PXP_OUT_CTRL_FORMAT__RGB555; + case V4L2_PIX_FMT_RGB444: return BV_PXP_OUT_CTRL_FORMAT__RGB444; + case V4L2_PIX_FMT_RGB565: return BV_PXP_OUT_CTRL_FORMAT__RGB565; + case V4L2_PIX_FMT_YUV32: return BV_PXP_OUT_CTRL_FORMAT__YUV1P444; + case V4L2_PIX_FMT_UYVY: return BV_PXP_OUT_CTRL_FORMAT__UYVY1P422; + case V4L2_PIX_FMT_VYUY: return BV_PXP_OUT_CTRL_FORMAT__VYUY1P422; + case V4L2_PIX_FMT_GREY: return BV_PXP_OUT_CTRL_FORMAT__Y8; + default: + case V4L2_PIX_FMT_Y4: return BV_PXP_OUT_CTRL_FORMAT__Y4; + case V4L2_PIX_FMT_NV16: return BV_PXP_OUT_CTRL_FORMAT__YUV2P422; + case V4L2_PIX_FMT_NV12: return BV_PXP_OUT_CTRL_FORMAT__YUV2P420; + case V4L2_PIX_FMT_NV61: return BV_PXP_OUT_CTRL_FORMAT__YVU2P422; + case V4L2_PIX_FMT_NV21: return BV_PXP_OUT_CTRL_FORMAT__YVU2P420; + } +} + +static bool pxp_v4l2_pix_fmt_is_yuv(u32 v4l2_pix_fmt) +{ + switch (v4l2_pix_fmt) { + case V4L2_PIX_FMT_YUV32: + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_VYUY: + case V4L2_PIX_FMT_YVYU: + case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV61: + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_YUV422P: + case V4L2_PIX_FMT_GREY: + case V4L2_PIX_FMT_Y4: + return true; + default: + return false; + } +} + +static void pxp_setup_csc(struct pxp_ctx *ctx) +{ + struct pxp_dev *dev = ctx->dev; + enum v4l2_ycbcr_encoding ycbcr_enc; + enum v4l2_quantization quantization; + + if (pxp_v4l2_pix_fmt_is_yuv(ctx->q_data[V4L2_M2M_SRC].fmt->fourcc) && + !pxp_v4l2_pix_fmt_is_yuv(ctx->q_data[V4L2_M2M_DST].fmt->fourcc)) { + /* + * CSC1 YUV/YCbCr to RGB conversion is implemented as follows: + * + * |R| |C0 0 C1| |Y + Yoffset | + * |G| = |C0 C3 C2| * |Cb + UVoffset| + * |B| |C0 C4 0 | |Cr + UVoffset| + * + * Results are clamped to 0..255. + * + * BT.601 limited range: + * + * |R| |1.1644 0.0000 1.5960| |Y - 16 | + * |G| = |1.1644 -0.3917 -0.8129| * |Cb - 128| + * |B| |1.1644 2.0172 0.0000| |Cr - 128| + */ + static const u32 csc1_coef_bt601_lim[3] = { + BM_PXP_CSC1_COEF0_YCBCR_MODE | + BF_PXP_CSC1_COEF0_C0(0x12a) | /* 1.1641 (-0.03 %) */ + BF_PXP_CSC1_COEF0_UV_OFFSET(-128) | + BF_PXP_CSC1_COEF0_Y_OFFSET(-16), + BF_PXP_CSC1_COEF1_C1(0x198) | /* 1.5938 (-0.23 %) */ + BF_PXP_CSC1_COEF1_C4(0x204), /* 2.0156 (-0.16 %) */ + BF_PXP_CSC1_COEF2_C2(0x730) | /* -0.8125 (+0.04 %) */ + BF_PXP_CSC1_COEF2_C3(0x79c), /* -0.3906 (+0.11 %) */ + }; + /* + * BT.601 full range: + * + * |R| |1.0000 0.0000 1.4020| |Y + 0 | + * |G| = |1.0000 -0.3441 -0.7141| * |Cb - 128| + * |B| |1.0000 1.7720 0.0000| |Cr - 128| + */ + static const u32 csc1_coef_bt601_full[3] = { + BM_PXP_CSC1_COEF0_YCBCR_MODE | + BF_PXP_CSC1_COEF0_C0(0x100) | /* 1.0000 (+0.00 %) */ + BF_PXP_CSC1_COEF0_UV_OFFSET(-128) | + BF_PXP_CSC1_COEF0_Y_OFFSET(0), + BF_PXP_CSC1_COEF1_C1(0x166) | /* 1.3984 (-0.36 %) */ + BF_PXP_CSC1_COEF1_C4(0x1c5), /* 1.7695 (-0.25 %) */ + BF_PXP_CSC1_COEF2_C2(0x74a) | /* -0.7109 (+0.32 %) */ + BF_PXP_CSC1_COEF2_C3(0x7a8), /* -0.3438 (+0.04 %) */ + }; + /* + * Rec.709 limited range: + * + * |R| |1.1644 0.0000 1.7927| |Y - 16 | + * |G| = |1.1644 -0.2132 -0.5329| * |Cb - 128| + * |B| |1.1644 2.1124 0.0000| |Cr - 128| + */ + static const u32 csc1_coef_rec709_lim[3] = { + BM_PXP_CSC1_COEF0_YCBCR_MODE | + BF_PXP_CSC1_COEF0_C0(0x12a) | /* 1.1641 (-0.03 %) */ + BF_PXP_CSC1_COEF0_UV_OFFSET(-128) | + BF_PXP_CSC1_COEF0_Y_OFFSET(-16), + BF_PXP_CSC1_COEF1_C1(0x1ca) | /* 1.7891 (-0.37 %) */ + BF_PXP_CSC1_COEF1_C4(0x21c), /* 2.1094 (-0.30 %) */ + BF_PXP_CSC1_COEF2_C2(0x778) | /* -0.5312 (+0.16 %) */ + BF_PXP_CSC1_COEF2_C3(0x7ca), /* -0.2109 (+0.23 %) */ + }; + /* + * Rec.709 full range: + * + * |R| |1.0000 0.0000 1.5748| |Y + 0 | + * |G| = |1.0000 -0.1873 -0.4681| * |Cb - 128| + * |B| |1.0000 1.8556 0.0000| |Cr - 128| + */ + static const u32 csc1_coef_rec709_full[3] = { + BM_PXP_CSC1_COEF0_YCBCR_MODE | + BF_PXP_CSC1_COEF0_C0(0x100) | /* 1.0000 (+0.00 %) */ + BF_PXP_CSC1_COEF0_UV_OFFSET(-128) | + BF_PXP_CSC1_COEF0_Y_OFFSET(0), + BF_PXP_CSC1_COEF1_C1(0x193) | /* 1.5742 (-0.06 %) */ + BF_PXP_CSC1_COEF1_C4(0x1db), /* 1.8555 (-0.01 %) */ + BF_PXP_CSC1_COEF2_C2(0x789) | /* -0.4648 (+0.33 %) */ + BF_PXP_CSC1_COEF2_C3(0x7d1), /* -0.1836 (+0.37 %) */ + }; + /* + * BT.2020 limited range: + * + * |R| |1.1644 0.0000 1.6787| |Y - 16 | + * |G| = |1.1644 -0.1874 -0.6505| * |Cb - 128| + * |B| |1.1644 2.1418 0.0000| |Cr - 128| + */ + static const u32 csc1_coef_bt2020_lim[3] = { + BM_PXP_CSC1_COEF0_YCBCR_MODE | + BF_PXP_CSC1_COEF0_C0(0x12a) | /* 1.1641 (-0.03 %) */ + BF_PXP_CSC1_COEF0_UV_OFFSET(-128) | + BF_PXP_CSC1_COEF0_Y_OFFSET(-16), + BF_PXP_CSC1_COEF1_C1(0x1ad) | /* 1.6758 (-0.29 %) */ + BF_PXP_CSC1_COEF1_C4(0x224), /* 2.1406 (-0.11 %) */ + BF_PXP_CSC1_COEF2_C2(0x75a) | /* -0.6484 (+0.20 %) */ + BF_PXP_CSC1_COEF2_C3(0x7d1), /* -0.1836 (+0.38 %) */ + }; + /* + * BT.2020 full range: + * + * |R| |1.0000 0.0000 1.4746| |Y + 0 | + * |G| = |1.0000 -0.1646 -0.5714| * |Cb - 128| + * |B| |1.0000 1.8814 0.0000| |Cr - 128| + */ + static const u32 csc1_coef_bt2020_full[3] = { + BM_PXP_CSC1_COEF0_YCBCR_MODE | + BF_PXP_CSC1_COEF0_C0(0x100) | /* 1.0000 (+0.00 %) */ + BF_PXP_CSC1_COEF0_UV_OFFSET(-128) | + BF_PXP_CSC1_COEF0_Y_OFFSET(0), + BF_PXP_CSC1_COEF1_C1(0x179) | /* 1.4727 (-0.19 %) */ + BF_PXP_CSC1_COEF1_C4(0x1e1), /* 1.8789 (-0.25 %) */ + BF_PXP_CSC1_COEF2_C2(0x76e) | /* -0.5703 (+0.11 %) */ + BF_PXP_CSC1_COEF2_C3(0x7d6), /* -0.1641 (+0.05 %) */ + }; + /* + * SMPTE 240m limited range: + * + * |R| |1.1644 0.0000 1.7937| |Y - 16 | + * |G| = |1.1644 -0.2565 -0.5427| * |Cb - 128| + * |B| |1.1644 2.0798 0.0000| |Cr - 128| + */ + static const u32 csc1_coef_smpte240m_lim[3] = { + BM_PXP_CSC1_COEF0_YCBCR_MODE | + BF_PXP_CSC1_COEF0_C0(0x12a) | /* 1.1641 (-0.03 %) */ + BF_PXP_CSC1_COEF0_UV_OFFSET(-128) | + BF_PXP_CSC1_COEF0_Y_OFFSET(-16), + BF_PXP_CSC1_COEF1_C1(0x1cb) | /* 1.7930 (-0.07 %) */ + BF_PXP_CSC1_COEF1_C4(0x214), /* 2.0781 (-0.17 %) */ + BF_PXP_CSC1_COEF2_C2(0x776) | /* -0.5391 (+0.36 %) */ + BF_PXP_CSC1_COEF2_C3(0x7bf), /* -0.2539 (+0.26 %) */ + }; + /* + * SMPTE 240m full range: + * + * |R| |1.0000 0.0000 1.5756| |Y + 0 | + * |G| = |1.0000 -0.2253 -0.4767| * |Cb - 128| + * |B| |1.0000 1.8270 0.0000| |Cr - 128| + */ + static const u32 csc1_coef_smpte240m_full[3] = { + BM_PXP_CSC1_COEF0_YCBCR_MODE | + BF_PXP_CSC1_COEF0_C0(0x100) | /* 1.0000 (+0.00 %) */ + BF_PXP_CSC1_COEF0_UV_OFFSET(-128) | + BF_PXP_CSC1_COEF0_Y_OFFSET(0), + BF_PXP_CSC1_COEF1_C1(0x193) | /* 1.5742 (-0.14 %) */ + BF_PXP_CSC1_COEF1_C4(0x1d3), /* 1.8242 (-0.28 %) */ + BF_PXP_CSC1_COEF2_C2(0x786) | /* -0.4766 (+0.01 %) */ + BF_PXP_CSC1_COEF2_C3(0x7c7), /* -0.2227 (+0.26 %) */ + }; + const u32 *csc1_coef; + + ycbcr_enc = ctx->q_data[V4L2_M2M_SRC].ycbcr_enc; + quantization = ctx->q_data[V4L2_M2M_SRC].quant; + + if (ycbcr_enc == V4L2_YCBCR_ENC_601) { + if (quantization == V4L2_QUANTIZATION_FULL_RANGE) + csc1_coef = csc1_coef_bt601_full; + else + csc1_coef = csc1_coef_bt601_lim; + } else if (ycbcr_enc == V4L2_YCBCR_ENC_709) { + if (quantization == V4L2_QUANTIZATION_FULL_RANGE) + csc1_coef = csc1_coef_rec709_full; + else + csc1_coef = csc1_coef_rec709_lim; + } else if (ycbcr_enc == V4L2_YCBCR_ENC_BT2020) { + if (quantization == V4L2_QUANTIZATION_FULL_RANGE) + csc1_coef = csc1_coef_bt2020_full; + else + csc1_coef = csc1_coef_bt2020_lim; + } else { + if (quantization == V4L2_QUANTIZATION_FULL_RANGE) + csc1_coef = csc1_coef_smpte240m_full; + else + csc1_coef = csc1_coef_smpte240m_lim; + } + + writel(csc1_coef[0], dev->mmio + HW_PXP_CSC1_COEF0); + writel(csc1_coef[1], dev->mmio + HW_PXP_CSC1_COEF1); + writel(csc1_coef[2], dev->mmio + HW_PXP_CSC1_COEF2); + } else { + writel(BM_PXP_CSC1_COEF0_BYPASS, dev->mmio + HW_PXP_CSC1_COEF0); + } + + if (!pxp_v4l2_pix_fmt_is_yuv(ctx->q_data[V4L2_M2M_SRC].fmt->fourcc) && + pxp_v4l2_pix_fmt_is_yuv(ctx->q_data[V4L2_M2M_DST].fmt->fourcc)) { + /* + * CSC2 RGB to YUV/YCbCr conversion is implemented as follows: + * + * |Y | |A1 A2 A3| |R| |D1| + * |Cb| = |B1 B2 B3| * |G| + |D2| + * |Cr| |C1 C2 C3| |B| |D3| + * + * Results are clamped to 0..255. + * + * BT.601 limited range: + * + * |Y | | 0.2568 0.5041 0.0979| |R| |16 | + * |Cb| = |-0.1482 -0.2910 0.4392| * |G| + |128| + * |Cr| | 0.4392 0.4392 -0.3678| |B| |128| + */ + static const u32 csc2_coef_bt601_lim[6] = { + BF_PXP_CSC2_COEF0_A2(0x081) | /* 0.5039 (-0.02 %) */ + BF_PXP_CSC2_COEF0_A1(0x041), /* 0.2539 (-0.29 %) */ + BF_PXP_CSC2_COEF1_B1(0x7db) | /* -0.1445 (+0.37 %) */ + BF_PXP_CSC2_COEF1_A3(0x019), /* 0.0977 (-0.02 %) */ + BF_PXP_CSC2_COEF2_B3(0x070) | /* 0.4375 (-0.17 %) */ + BF_PXP_CSC2_COEF2_B2(0x7b6), /* -0.2891 (+0.20 %) */ + BF_PXP_CSC2_COEF3_C2(0x7a2) | /* -0.3672 (+0.06 %) */ + BF_PXP_CSC2_COEF3_C1(0x070), /* 0.4375 (-0.17 %) */ + BF_PXP_CSC2_COEF4_D1(16) | + BF_PXP_CSC2_COEF4_C3(0x7ee), /* -0.0703 (+0.11 %) */ + BF_PXP_CSC2_COEF5_D3(128) | + BF_PXP_CSC2_COEF5_D2(128), + }; + /* + * BT.601 full range: + * + * |Y | | 0.2990 0.5870 0.1140| |R| |0 | + * |Cb| = |-0.1687 -0.3313 0.5000| * |G| + |128| + * |Cr| | 0.5000 0.5000 -0.4187| |B| |128| + */ + static const u32 csc2_coef_bt601_full[6] = { + BF_PXP_CSC2_COEF0_A2(0x096) | /* 0.5859 (-0.11 %) */ + BF_PXP_CSC2_COEF0_A1(0x04c), /* 0.2969 (-0.21 %) */ + BF_PXP_CSC2_COEF1_B1(0x7d5) | /* -0.1680 (+0.07 %) */ + BF_PXP_CSC2_COEF1_A3(0x01d), /* 0.1133 (-0.07 %) */ + BF_PXP_CSC2_COEF2_B3(0x080) | /* 0.5000 (+0.00 %) */ + BF_PXP_CSC2_COEF2_B2(0x7ac), /* -0.3281 (+0.32 %) */ + BF_PXP_CSC2_COEF3_C2(0x795) | /* -0.4180 (+0.07 %) */ + BF_PXP_CSC2_COEF3_C1(0x080), /* 0.5000 (+0.00 %) */ + BF_PXP_CSC2_COEF4_D1(0) | + BF_PXP_CSC2_COEF4_C3(0x7ec), /* -0.0781 (+0.32 %) */ + BF_PXP_CSC2_COEF5_D3(128) | + BF_PXP_CSC2_COEF5_D2(128), + }; + /* + * Rec.709 limited range: + * + * |Y | | 0.1826 0.6142 0.0620| |R| |16 | + * |Cb| = |-0.1007 -0.3385 0.4392| * |G| + |128| + * |Cr| | 0.4392 0.4392 -0.3990| |B| |128| + */ + static const u32 csc2_coef_rec709_lim[6] = { + BF_PXP_CSC2_COEF0_A2(0x09d) | /* 0.6133 (-0.09 %) */ + BF_PXP_CSC2_COEF0_A1(0x02e), /* 0.1797 (-0.29 %) */ + BF_PXP_CSC2_COEF1_B1(0x7e7) | /* -0.0977 (+0.30 %) */ + BF_PXP_CSC2_COEF1_A3(0x00f), /* 0.0586 (-0.34 %) */ + BF_PXP_CSC2_COEF2_B3(0x070) | /* 0.4375 (-0.17 %) */ + BF_PXP_CSC2_COEF2_B2(0x7aa), /* -0.3359 (+0.26 %) */ + BF_PXP_CSC2_COEF3_C2(0x79a) | /* -0.3984 (+0.05 %) */ + BF_PXP_CSC2_COEF3_C1(0x070), /* 0.4375 (-0.17 %) */ + BF_PXP_CSC2_COEF4_D1(16) | + BF_PXP_CSC2_COEF4_C3(0x7f6), /* -0.0391 (+0.12 %) */ + BF_PXP_CSC2_COEF5_D3(128) | + BF_PXP_CSC2_COEF5_D2(128), + }; + /* + * Rec.709 full range: + * + * |Y | | 0.2126 0.7152 0.0722| |R| |0 | + * |Cb| = |-0.1146 -0.3854 0.5000| * |G| + |128| + * |Cr| | 0.5000 0.5000 -0.4542| |B| |128| + */ + static const u32 csc2_coef_rec709_full[6] = { + BF_PXP_CSC2_COEF0_A2(0x0b7) | /* 0.7148 (-0.04 %) */ + BF_PXP_CSC2_COEF0_A1(0x036), /* 0.2109 (-0.17 %) */ + BF_PXP_CSC2_COEF1_B1(0x7e3) | /* -0.1133 (+0.13 %) */ + BF_PXP_CSC2_COEF1_A3(0x012), /* 0.0703 (-0.19 %) */ + BF_PXP_CSC2_COEF2_B3(0x080) | /* 0.5000 (+0.00 %) */ + BF_PXP_CSC2_COEF2_B2(0x79e), /* -0.3828 (+0.26 %) */ + BF_PXP_CSC2_COEF3_C2(0x78c) | /* -0.4531 (+0.11 %) */ + BF_PXP_CSC2_COEF3_C1(0x080), /* 0.5000 (+0.00 %) */ + BF_PXP_CSC2_COEF4_D1(0) | + BF_PXP_CSC2_COEF4_C3(0x7f5), /* -0.0430 (+0.28 %) */ + BF_PXP_CSC2_COEF5_D3(128) | + BF_PXP_CSC2_COEF5_D2(128), + }; + /* + * BT.2020 limited range: + * + * |Y | | 0.2256 0.5823 0.0509| |R| |16 | + * |Cb| = |-0.1226 -0.3166 0.4392| * |G| + |128| + * |Cr| | 0.4392 0.4392 -0.4039| |B| |128| + */ + static const u32 csc2_coef_bt2020_lim[6] = { + BF_PXP_CSC2_COEF0_A2(0x095) | /* 0.5820 (-0.03 %) */ + BF_PXP_CSC2_COEF0_A1(0x039), /* 0.2227 (-0.30 %) */ + BF_PXP_CSC2_COEF1_B1(0x7e1) | /* -0.1211 (+0.15 %) */ + BF_PXP_CSC2_COEF1_A3(0x00d), /* 0.0508 (-0.01 %) */ + BF_PXP_CSC2_COEF2_B3(0x070) | /* 0.4375 (-0.17 %) */ + BF_PXP_CSC2_COEF2_B2(0x7af), /* -0.3164 (+0.02 %) */ + BF_PXP_CSC2_COEF3_C2(0x799) | /* -0.4023 (+0.16 %) */ + BF_PXP_CSC2_COEF3_C1(0x070), /* 0.4375 (-0.17 %) */ + BF_PXP_CSC2_COEF4_D1(16) | + BF_PXP_CSC2_COEF4_C3(0x7f7), /* -0.0352 (+0.02 %) */ + BF_PXP_CSC2_COEF5_D3(128) | + BF_PXP_CSC2_COEF5_D2(128), + }; + /* + * BT.2020 full range: + * + * |Y | | 0.2627 0.6780 0.0593| |R| |0 | + * |Cb| = |-0.1396 -0.3604 0.5000| * |G| + |128| + * |Cr| | 0.5000 0.5000 -0.4598| |B| |128| + */ + static const u32 csc2_coef_bt2020_full[6] = { + BF_PXP_CSC2_COEF0_A2(0x0ad) | /* 0.6758 (-0.22 %) */ + BF_PXP_CSC2_COEF0_A1(0x043), /* 0.2617 (-0.10 %) */ + BF_PXP_CSC2_COEF1_B1(0x7dd) | /* -0.1367 (+0.29 %) */ + BF_PXP_CSC2_COEF1_A3(0x00f), /* 0.0586 (-0.07 %) */ + BF_PXP_CSC2_COEF2_B3(0x080) | /* 0.5000 (+0.00 %) */ + BF_PXP_CSC2_COEF2_B2(0x7a4), /* -0.3594 (+0.10 %) */ + BF_PXP_CSC2_COEF3_C2(0x78b) | /* -0.4570 (+0.28 %) */ + BF_PXP_CSC2_COEF3_C1(0x080), /* 0.5000 (+0.00 %) */ + BF_PXP_CSC2_COEF4_D1(0) | + BF_PXP_CSC2_COEF4_C3(0x7f6), /* -0.0391 (+0.11 %) */ + BF_PXP_CSC2_COEF5_D3(128) | + BF_PXP_CSC2_COEF5_D2(128), + }; + /* + * SMPTE 240m limited range: + * + * |Y | | 0.1821 0.6020 0.0747| |R| |16 | + * |Cb| = |-0.1019 -0.3373 0.4392| * |G| + |128| + * |Cr| | 0.4392 0.4392 -0.3909| |B| |128| + */ + static const u32 csc2_coef_smpte240m_lim[6] = { + BF_PXP_CSC2_COEF0_A2(0x09a) | /* 0.6016 (-0.05 %) */ + BF_PXP_CSC2_COEF0_A1(0x02e), /* 0.1797 (-0.24 %) */ + BF_PXP_CSC2_COEF1_B1(0x7e6) | /* -0.1016 (+0.03 %) */ + BF_PXP_CSC2_COEF1_A3(0x013), /* 0.0742 (-0.05 %) */ + BF_PXP_CSC2_COEF2_B3(0x070) | /* 0.4375 (-0.17 %) */ + BF_PXP_CSC2_COEF2_B2(0x7aa), /* -0.3359 (+0.14 %) */ + BF_PXP_CSC2_COEF3_C2(0x79c) | /* -0.3906 (+0.03 %) */ + BF_PXP_CSC2_COEF3_C1(0x070), /* 0.4375 (-0.17 %) */ + BF_PXP_CSC2_COEF4_D1(16) | + BF_PXP_CSC2_COEF4_C3(0x7f4), /* -0.0469 (+0.14 %) */ + BF_PXP_CSC2_COEF5_D3(128) | + BF_PXP_CSC2_COEF5_D2(128), + }; + /* + * SMPTE 240m full range: + * + * |Y | | 0.2120 0.7010 0.0870| |R| |0 | + * |Cb| = |-0.1160 -0.3840 0.5000| * |G| + |128| + * |Cr| | 0.5000 0.5000 -0.4450| |B| |128| + */ + static const u32 csc2_coef_smpte240m_full[6] = { + BF_PXP_CSC2_COEF0_A2(0x0b3) | /* 0.6992 (-0.18 %) */ + BF_PXP_CSC2_COEF0_A1(0x036), /* 0.2109 (-0.11 %) */ + BF_PXP_CSC2_COEF1_B1(0x7e3) | /* -0.1133 (+0.27 %) */ + BF_PXP_CSC2_COEF1_A3(0x016), /* 0.0859 (-0.11 %) */ + BF_PXP_CSC2_COEF2_B3(0x080) | /* 0.5000 (+0.00 %) */ + BF_PXP_CSC2_COEF2_B2(0x79e), /* -0.3828 (+0.12 %) */ + BF_PXP_CSC2_COEF3_C2(0x78f) | /* -0.4414 (+0.36 %) */ + BF_PXP_CSC2_COEF3_C1(0x080), /* 0.5000 (+0.00 %) */ + BF_PXP_CSC2_COEF4_D1(0) | + BF_PXP_CSC2_COEF4_C3(0x7f2), /* -0.0547 (+0.03 %) */ + BF_PXP_CSC2_COEF5_D3(128) | + BF_PXP_CSC2_COEF5_D2(128), + }; + const u32 *csc2_coef; + u32 csc2_ctrl; + + ycbcr_enc = ctx->q_data[V4L2_M2M_DST].ycbcr_enc; + quantization = ctx->q_data[V4L2_M2M_DST].quant; + + if (ycbcr_enc == V4L2_YCBCR_ENC_601) { + if (quantization == V4L2_QUANTIZATION_FULL_RANGE) + csc2_coef = csc2_coef_bt601_full; + else + csc2_coef = csc2_coef_bt601_lim; + } else if (ycbcr_enc == V4L2_YCBCR_ENC_709) { + if (quantization == V4L2_QUANTIZATION_FULL_RANGE) + csc2_coef = csc2_coef_rec709_full; + else + csc2_coef = csc2_coef_rec709_lim; + } else if (ycbcr_enc == V4L2_YCBCR_ENC_709) { + if (quantization == V4L2_QUANTIZATION_FULL_RANGE) + csc2_coef = csc2_coef_bt2020_full; + else + csc2_coef = csc2_coef_bt2020_lim; + } else { + if (quantization == V4L2_QUANTIZATION_FULL_RANGE) + csc2_coef = csc2_coef_smpte240m_full; + else + csc2_coef = csc2_coef_smpte240m_lim; + } + if (quantization == V4L2_QUANTIZATION_FULL_RANGE) { + csc2_ctrl = BV_PXP_CSC2_CTRL_CSC_MODE__RGB2YUV << + BP_PXP_CSC2_CTRL_CSC_MODE; + } else { + csc2_ctrl = BV_PXP_CSC2_CTRL_CSC_MODE__RGB2YCbCr << + BP_PXP_CSC2_CTRL_CSC_MODE; + } + + writel(csc2_ctrl, dev->mmio + HW_PXP_CSC2_CTRL); + writel(csc2_coef[0], dev->mmio + HW_PXP_CSC2_COEF0); + writel(csc2_coef[1], dev->mmio + HW_PXP_CSC2_COEF1); + writel(csc2_coef[2], dev->mmio + HW_PXP_CSC2_COEF2); + writel(csc2_coef[3], dev->mmio + HW_PXP_CSC2_COEF3); + writel(csc2_coef[4], dev->mmio + HW_PXP_CSC2_COEF4); + writel(csc2_coef[5], dev->mmio + HW_PXP_CSC2_COEF5); + } else { + writel(BM_PXP_CSC2_CTRL_BYPASS, dev->mmio + HW_PXP_CSC2_CTRL); + } +} + +static int pxp_start(struct pxp_ctx *ctx, struct vb2_v4l2_buffer *in_vb, + struct vb2_v4l2_buffer *out_vb) +{ + struct pxp_dev *dev = ctx->dev; + struct pxp_q_data *q_data; + u32 src_width, src_height, src_stride, src_fourcc; + u32 dst_width, dst_height, dst_stride, dst_fourcc; + dma_addr_t p_in, p_out; + u32 ctrl, out_ctrl, out_buf, out_buf2, out_pitch, out_lrc, out_ps_ulc; + u32 out_ps_lrc; + u32 ps_ctrl, ps_buf, ps_ubuf, ps_vbuf, ps_pitch, ps_scale, ps_offset; + u32 as_ulc, as_lrc; + u32 y_size; + u32 decx, decy, xscale, yscale; + + q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); + + src_width = ctx->q_data[V4L2_M2M_SRC].width; + dst_width = ctx->q_data[V4L2_M2M_DST].width; + src_height = ctx->q_data[V4L2_M2M_SRC].height; + dst_height = ctx->q_data[V4L2_M2M_DST].height; + src_stride = ctx->q_data[V4L2_M2M_SRC].bytesperline; + dst_stride = ctx->q_data[V4L2_M2M_DST].bytesperline; + src_fourcc = ctx->q_data[V4L2_M2M_SRC].fmt->fourcc; + dst_fourcc = ctx->q_data[V4L2_M2M_DST].fmt->fourcc; + + p_in = vb2_dma_contig_plane_dma_addr(&in_vb->vb2_buf, 0); + p_out = vb2_dma_contig_plane_dma_addr(&out_vb->vb2_buf, 0); + + if (!p_in || !p_out) { + v4l2_err(&dev->v4l2_dev, + "Acquiring DMA addresses of buffers failed\n"); + return -EFAULT; + } + + out_vb->sequence = + get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE)->sequence++; + in_vb->sequence = q_data->sequence++; + out_vb->vb2_buf.timestamp = in_vb->vb2_buf.timestamp; + + if (in_vb->flags & V4L2_BUF_FLAG_TIMECODE) + out_vb->timecode = in_vb->timecode; + out_vb->field = in_vb->field; + out_vb->flags = in_vb->flags & + (V4L2_BUF_FLAG_TIMECODE | + V4L2_BUF_FLAG_KEYFRAME | + V4L2_BUF_FLAG_PFRAME | + V4L2_BUF_FLAG_BFRAME | + V4L2_BUF_FLAG_TSTAMP_SRC_MASK); + + /* Rotation disabled, 8x8 block size */ + ctrl = BF_PXP_CTRL_VFLIP0(!!(ctx->mode & MEM2MEM_VFLIP)) | + BF_PXP_CTRL_HFLIP0(!!(ctx->mode & MEM2MEM_HFLIP)); + /* Always write alpha value as V4L2_CID_ALPHA_COMPONENT */ + out_ctrl = BF_PXP_OUT_CTRL_ALPHA(ctx->alpha_component) | + BF_PXP_OUT_CTRL_ALPHA_OUTPUT(1) | + pxp_v4l2_pix_fmt_to_out_format(dst_fourcc); + out_buf = p_out; + switch (dst_fourcc) { + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_NV61: + out_buf2 = out_buf + dst_stride * dst_height; + break; + default: + out_buf2 = 0; + } + + out_pitch = BF_PXP_OUT_PITCH_PITCH(dst_stride); + out_lrc = BF_PXP_OUT_LRC_X(dst_width - 1) | + BF_PXP_OUT_LRC_Y(dst_height - 1); + /* PS covers whole output */ + out_ps_ulc = BF_PXP_OUT_PS_ULC_X(0) | BF_PXP_OUT_PS_ULC_Y(0); + out_ps_lrc = BF_PXP_OUT_PS_LRC_X(dst_width - 1) | + BF_PXP_OUT_PS_LRC_Y(dst_height - 1); + /* no AS */ + as_ulc = BF_PXP_OUT_AS_ULC_X(1) | BF_PXP_OUT_AS_ULC_Y(1); + as_lrc = BF_PXP_OUT_AS_LRC_X(0) | BF_PXP_OUT_AS_LRC_Y(0); + + decx = (src_width <= dst_width) ? 0 : ilog2(src_width / dst_width); + decy = (src_height <= dst_height) ? 0 : ilog2(src_height / dst_height); + ps_ctrl = BF_PXP_PS_CTRL_DECX(decx) | BF_PXP_PS_CTRL_DECY(decy) | + pxp_v4l2_pix_fmt_to_ps_format(src_fourcc); + ps_buf = p_in; + y_size = src_stride * src_height; + switch (src_fourcc) { + case V4L2_PIX_FMT_YUV420: + ps_ubuf = ps_buf + y_size; + ps_vbuf = ps_ubuf + y_size / 4; + break; + case V4L2_PIX_FMT_YUV422P: + ps_ubuf = ps_buf + y_size; + ps_vbuf = ps_ubuf + y_size / 2; + break; + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_NV61: + ps_ubuf = ps_buf + y_size; + ps_vbuf = 0; + break; + case V4L2_PIX_FMT_GREY: + case V4L2_PIX_FMT_Y4: + ps_ubuf = 0; + /* In grayscale mode, ps_vbuf contents are reused as CbCr */ + ps_vbuf = 0x8080; + break; + default: + ps_ubuf = 0; + ps_vbuf = 0; + break; + } + ps_pitch = BF_PXP_PS_PITCH_PITCH(src_stride); + if (decx) { + xscale = (src_width >> decx) * 0x1000 / dst_width; + } else { + switch (src_fourcc) { + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_VYUY: + case V4L2_PIX_FMT_YVYU: + case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV61: + case V4L2_PIX_FMT_YUV422P: + case V4L2_PIX_FMT_YUV420: + /* + * This avoids sampling past the right edge for + * horizontally chroma subsampled formats. + */ + xscale = (src_width - 2) * 0x1000 / (dst_width - 1); + break; + default: + xscale = (src_width - 1) * 0x1000 / (dst_width - 1); + break; + } + } + if (decy) + yscale = (src_height >> decy) * 0x1000 / dst_height; + else + yscale = (src_height - 1) * 0x1000 / (dst_height - 1); + ps_scale = BF_PXP_PS_SCALE_YSCALE(yscale) | + BF_PXP_PS_SCALE_XSCALE(xscale); + ps_offset = BF_PXP_PS_OFFSET_YOFFSET(0) | BF_PXP_PS_OFFSET_XOFFSET(0); + + writel(ctrl, dev->mmio + HW_PXP_CTRL); + /* skip STAT */ + writel(out_ctrl, dev->mmio + HW_PXP_OUT_CTRL); + writel(out_buf, dev->mmio + HW_PXP_OUT_BUF); + writel(out_buf2, dev->mmio + HW_PXP_OUT_BUF2); + writel(out_pitch, dev->mmio + HW_PXP_OUT_PITCH); + writel(out_lrc, dev->mmio + HW_PXP_OUT_LRC); + writel(out_ps_ulc, dev->mmio + HW_PXP_OUT_PS_ULC); + writel(out_ps_lrc, dev->mmio + HW_PXP_OUT_PS_LRC); + writel(as_ulc, dev->mmio + HW_PXP_OUT_AS_ULC); + writel(as_lrc, dev->mmio + HW_PXP_OUT_AS_LRC); + writel(ps_ctrl, dev->mmio + HW_PXP_PS_CTRL); + writel(ps_buf, dev->mmio + HW_PXP_PS_BUF); + writel(ps_ubuf, dev->mmio + HW_PXP_PS_UBUF); + writel(ps_vbuf, dev->mmio + HW_PXP_PS_VBUF); + writel(ps_pitch, dev->mmio + HW_PXP_PS_PITCH); + writel(0x00ffffff, dev->mmio + HW_PXP_PS_BACKGROUND_0); + writel(ps_scale, dev->mmio + HW_PXP_PS_SCALE); + writel(ps_offset, dev->mmio + HW_PXP_PS_OFFSET); + /* disable processed surface color keying */ + writel(0x00ffffff, dev->mmio + HW_PXP_PS_CLRKEYLOW_0); + writel(0x00000000, dev->mmio + HW_PXP_PS_CLRKEYHIGH_0); + + /* disable alpha surface color keying */ + writel(0x00ffffff, dev->mmio + HW_PXP_AS_CLRKEYLOW_0); + writel(0x00000000, dev->mmio + HW_PXP_AS_CLRKEYHIGH_0); + + /* setup CSC */ + pxp_setup_csc(ctx); + + /* bypass LUT */ + writel(BM_PXP_LUT_CTRL_BYPASS, dev->mmio + HW_PXP_LUT_CTRL); + + writel(BF_PXP_DATA_PATH_CTRL0_MUX15_SEL(0)| + BF_PXP_DATA_PATH_CTRL0_MUX14_SEL(1)| + BF_PXP_DATA_PATH_CTRL0_MUX13_SEL(0)| + BF_PXP_DATA_PATH_CTRL0_MUX12_SEL(0)| + BF_PXP_DATA_PATH_CTRL0_MUX11_SEL(0)| + BF_PXP_DATA_PATH_CTRL0_MUX10_SEL(0)| + BF_PXP_DATA_PATH_CTRL0_MUX9_SEL(1)| + BF_PXP_DATA_PATH_CTRL0_MUX8_SEL(0)| + BF_PXP_DATA_PATH_CTRL0_MUX7_SEL(0)| + BF_PXP_DATA_PATH_CTRL0_MUX6_SEL(0)| + BF_PXP_DATA_PATH_CTRL0_MUX5_SEL(0)| + BF_PXP_DATA_PATH_CTRL0_MUX4_SEL(0)| + BF_PXP_DATA_PATH_CTRL0_MUX3_SEL(0)| + BF_PXP_DATA_PATH_CTRL0_MUX2_SEL(0)| + BF_PXP_DATA_PATH_CTRL0_MUX1_SEL(0)| + BF_PXP_DATA_PATH_CTRL0_MUX0_SEL(0), + dev->mmio + HW_PXP_DATA_PATH_CTRL0); + writel(BF_PXP_DATA_PATH_CTRL1_MUX17_SEL(1) | + BF_PXP_DATA_PATH_CTRL1_MUX16_SEL(1), + dev->mmio + HW_PXP_DATA_PATH_CTRL1); + + writel(0xffff, dev->mmio + HW_PXP_IRQ_MASK); + + /* ungate, enable PS/AS/OUT and PXP operation */ + writel(BM_PXP_CTRL_IRQ_ENABLE, dev->mmio + HW_PXP_CTRL_SET); + writel(BM_PXP_CTRL_ENABLE | BM_PXP_CTRL_ENABLE_CSC2 | + BM_PXP_CTRL_ENABLE_LUT | BM_PXP_CTRL_ENABLE_ROTATE0 | + BM_PXP_CTRL_ENABLE_PS_AS_OUT, dev->mmio + HW_PXP_CTRL_SET); + + return 0; +} + +static void pxp_job_finish(struct pxp_dev *dev) +{ + struct pxp_ctx *curr_ctx; + struct vb2_v4l2_buffer *src_vb, *dst_vb; + unsigned long flags; + + curr_ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev); + + if (curr_ctx == NULL) { + pr_err("Instance released before the end of transaction\n"); + return; + } + + src_vb = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx); + dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx); + + spin_lock_irqsave(&dev->irqlock, flags); + v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE); + v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE); + spin_unlock_irqrestore(&dev->irqlock, flags); + + dprintk(curr_ctx->dev, "Finishing transaction\n"); + v4l2_m2m_job_finish(dev->m2m_dev, curr_ctx->fh.m2m_ctx); +} + +/* + * mem2mem callbacks + */ +static void pxp_device_run(void *priv) +{ + struct pxp_ctx *ctx = priv; + struct vb2_v4l2_buffer *src_buf, *dst_buf; + + src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); + dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); + + pxp_start(ctx, src_buf, dst_buf); +} + +static int pxp_job_ready(void *priv) +{ + struct pxp_ctx *ctx = priv; + + if (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) < 1 || + v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx) < 1) { + dprintk(ctx->dev, "Not enough buffers available\n"); + return 0; + } + + return 1; +} + +static void pxp_job_abort(void *priv) +{ + struct pxp_ctx *ctx = priv; + + /* Will cancel the transaction in the next interrupt handler */ + ctx->aborting = 1; +} + +/* + * interrupt handler + */ +static irqreturn_t pxp_irq_handler(int irq, void *dev_id) +{ + struct pxp_dev *dev = dev_id; + u32 stat; + + stat = readl(dev->mmio + HW_PXP_STAT); + + if (stat & BM_PXP_STAT_IRQ0) { + /* we expect x = 0, y = height, irq0 = 1 */ + if (stat & ~(BM_PXP_STAT_BLOCKX | BM_PXP_STAT_BLOCKY | + BM_PXP_STAT_IRQ0)) + dprintk(dev, "%s: stat = 0x%08x\n", __func__, stat); + writel(BM_PXP_STAT_IRQ0, dev->mmio + HW_PXP_STAT_CLR); + + pxp_job_finish(dev); + } else { + u32 irq = readl(dev->mmio + HW_PXP_IRQ); + + dprintk(dev, "%s: stat = 0x%08x\n", __func__, stat); + dprintk(dev, "%s: irq = 0x%08x\n", __func__, irq); + + writel(irq, dev->mmio + HW_PXP_IRQ_CLR); + } + + return IRQ_HANDLED; +} + +/* + * video ioctls + */ +static int pxp_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + strlcpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver)); + strlcpy(cap->card, MEM2MEM_NAME, sizeof(cap->card)); + snprintf(cap->bus_info, sizeof(cap->bus_info), + "platform:%s", MEM2MEM_NAME); + return 0; +} + +static int pxp_enum_fmt(struct v4l2_fmtdesc *f, u32 type) +{ + int i, num; + struct pxp_fmt *fmt; + + num = 0; + + for (i = 0; i < NUM_FORMATS; ++i) { + if (formats[i].types & type) { + /* index-th format of type type found ? */ + if (num == f->index) + break; + /* + * Correct type but haven't reached our index yet, + * just increment per-type index + */ + ++num; + } + } + + if (i < NUM_FORMATS) { + /* Format found */ + fmt = &formats[i]; + f->pixelformat = fmt->fourcc; + return 0; + } + + /* Format not found */ + return -EINVAL; +} + +static int pxp_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + return pxp_enum_fmt(f, MEM2MEM_CAPTURE); +} + +static int pxp_enum_fmt_vid_out(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + return pxp_enum_fmt(f, MEM2MEM_OUTPUT); +} + +static int pxp_g_fmt(struct pxp_ctx *ctx, struct v4l2_format *f) +{ + struct vb2_queue *vq; + struct pxp_q_data *q_data; + + vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); + if (!vq) + return -EINVAL; + + q_data = get_q_data(ctx, f->type); + + f->fmt.pix.width = q_data->width; + f->fmt.pix.height = q_data->height; + f->fmt.pix.field = V4L2_FIELD_NONE; + f->fmt.pix.pixelformat = q_data->fmt->fourcc; + f->fmt.pix.bytesperline = q_data->bytesperline; + f->fmt.pix.sizeimage = q_data->sizeimage; + f->fmt.pix.colorspace = ctx->colorspace; + f->fmt.pix.xfer_func = ctx->xfer_func; + f->fmt.pix.ycbcr_enc = q_data->ycbcr_enc; + f->fmt.pix.quantization = q_data->quant; + + return 0; +} + +static int pxp_g_fmt_vid_out(struct file *file, void *priv, + struct v4l2_format *f) +{ + return pxp_g_fmt(file2ctx(file), f); +} + +static int pxp_g_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + return pxp_g_fmt(file2ctx(file), f); +} + +static inline u32 pxp_bytesperline(struct pxp_fmt *fmt, u32 width) +{ + switch (fmt->fourcc) { + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_YUV422P: + case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_NV61: + return width; + default: + return (width * fmt->depth) >> 3; + } +} + +static inline u32 pxp_sizeimage(struct pxp_fmt *fmt, u32 width, u32 height) +{ + return (fmt->depth * width * height) >> 3; +} + +static int pxp_try_fmt(struct v4l2_format *f, struct pxp_fmt *fmt) +{ + v4l_bound_align_image(&f->fmt.pix.width, MIN_W, MAX_W, ALIGN_W, + &f->fmt.pix.height, MIN_H, MAX_H, ALIGN_H, 0); + + f->fmt.pix.bytesperline = pxp_bytesperline(fmt, f->fmt.pix.width); + f->fmt.pix.sizeimage = pxp_sizeimage(fmt, f->fmt.pix.width, + f->fmt.pix.height); + f->fmt.pix.field = V4L2_FIELD_NONE; + + return 0; +} + +static void +pxp_fixup_colorimetry_cap(struct pxp_ctx *ctx, u32 dst_fourcc, + enum v4l2_ycbcr_encoding *ycbcr_enc, + enum v4l2_quantization *quantization) +{ + bool dst_is_yuv = pxp_v4l2_pix_fmt_is_yuv(dst_fourcc); + + if (pxp_v4l2_pix_fmt_is_yuv(ctx->q_data[V4L2_M2M_SRC].fmt->fourcc) == + dst_is_yuv) { + /* + * There is no support for conversion between different YCbCr + * encodings or between RGB limited and full range. + */ + *ycbcr_enc = ctx->q_data[V4L2_M2M_SRC].ycbcr_enc; + *quantization = ctx->q_data[V4L2_M2M_SRC].quant; + } else { + *ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(ctx->colorspace); + *quantization = V4L2_MAP_QUANTIZATION_DEFAULT(!dst_is_yuv, + ctx->colorspace, + *ycbcr_enc); + } +} + +static int pxp_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct pxp_fmt *fmt; + struct pxp_ctx *ctx = file2ctx(file); + + fmt = find_format(f); + if (!fmt) { + f->fmt.pix.pixelformat = formats[0].fourcc; + fmt = find_format(f); + } + if (!(fmt->types & MEM2MEM_CAPTURE)) { + v4l2_err(&ctx->dev->v4l2_dev, + "Fourcc format (0x%08x) invalid.\n", + f->fmt.pix.pixelformat); + return -EINVAL; + } + + f->fmt.pix.colorspace = ctx->colorspace; + f->fmt.pix.xfer_func = ctx->xfer_func; + + pxp_fixup_colorimetry_cap(ctx, fmt->fourcc, + &f->fmt.pix.ycbcr_enc, + &f->fmt.pix.quantization); + + return pxp_try_fmt(f, fmt); +} + +static int pxp_try_fmt_vid_out(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct pxp_fmt *fmt; + struct pxp_ctx *ctx = file2ctx(file); + + fmt = find_format(f); + if (!fmt) { + f->fmt.pix.pixelformat = formats[0].fourcc; + fmt = find_format(f); + } + if (!(fmt->types & MEM2MEM_OUTPUT)) { + v4l2_err(&ctx->dev->v4l2_dev, + "Fourcc format (0x%08x) invalid.\n", + f->fmt.pix.pixelformat); + return -EINVAL; + } + + if (!f->fmt.pix.colorspace) + f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709; + + return pxp_try_fmt(f, fmt); +} + +static int pxp_s_fmt(struct pxp_ctx *ctx, struct v4l2_format *f) +{ + struct pxp_q_data *q_data; + struct vb2_queue *vq; + + vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); + if (!vq) + return -EINVAL; + + q_data = get_q_data(ctx, f->type); + if (!q_data) + return -EINVAL; + + if (vb2_is_busy(vq)) { + v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__); + return -EBUSY; + } + + q_data->fmt = find_format(f); + q_data->width = f->fmt.pix.width; + q_data->height = f->fmt.pix.height; + q_data->bytesperline = f->fmt.pix.bytesperline; + q_data->sizeimage = f->fmt.pix.sizeimage; + + dprintk(ctx->dev, + "Setting format for type %d, wxh: %dx%d, fmt: %d\n", + f->type, q_data->width, q_data->height, q_data->fmt->fourcc); + + return 0; +} + +static int pxp_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct pxp_ctx *ctx = file2ctx(file); + int ret; + + ret = pxp_try_fmt_vid_cap(file, priv, f); + if (ret) + return ret; + + ret = pxp_s_fmt(file2ctx(file), f); + if (ret) + return ret; + + ctx->q_data[V4L2_M2M_DST].ycbcr_enc = f->fmt.pix.ycbcr_enc; + ctx->q_data[V4L2_M2M_DST].quant = f->fmt.pix.quantization; + + return 0; +} + +static int pxp_s_fmt_vid_out(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct pxp_ctx *ctx = file2ctx(file); + int ret; + + ret = pxp_try_fmt_vid_out(file, priv, f); + if (ret) + return ret; + + ret = pxp_s_fmt(file2ctx(file), f); + if (ret) + return ret; + + ctx->colorspace = f->fmt.pix.colorspace; + ctx->xfer_func = f->fmt.pix.xfer_func; + ctx->q_data[V4L2_M2M_SRC].ycbcr_enc = f->fmt.pix.ycbcr_enc; + ctx->q_data[V4L2_M2M_SRC].quant = f->fmt.pix.quantization; + + pxp_fixup_colorimetry_cap(ctx, ctx->q_data[V4L2_M2M_DST].fmt->fourcc, + &ctx->q_data[V4L2_M2M_DST].ycbcr_enc, + &ctx->q_data[V4L2_M2M_DST].quant); + + return 0; +} + +static int pxp_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct pxp_ctx *ctx = + container_of(ctrl->handler, struct pxp_ctx, hdl); + + switch (ctrl->id) { + case V4L2_CID_HFLIP: + if (ctrl->val) + ctx->mode |= MEM2MEM_HFLIP; + else + ctx->mode &= ~MEM2MEM_HFLIP; + break; + + case V4L2_CID_VFLIP: + if (ctrl->val) + ctx->mode |= MEM2MEM_VFLIP; + else + ctx->mode &= ~MEM2MEM_VFLIP; + break; + + case V4L2_CID_ALPHA_COMPONENT: + ctx->alpha_component = ctrl->val; + break; + + default: + v4l2_err(&ctx->dev->v4l2_dev, "Invalid control\n"); + return -EINVAL; + } + + return 0; +} + +static const struct v4l2_ctrl_ops pxp_ctrl_ops = { + .s_ctrl = pxp_s_ctrl, +}; + +static const struct v4l2_ioctl_ops pxp_ioctl_ops = { + .vidioc_querycap = pxp_querycap, + + .vidioc_enum_fmt_vid_cap = pxp_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = pxp_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = pxp_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = pxp_s_fmt_vid_cap, + + .vidioc_enum_fmt_vid_out = pxp_enum_fmt_vid_out, + .vidioc_g_fmt_vid_out = pxp_g_fmt_vid_out, + .vidioc_try_fmt_vid_out = pxp_try_fmt_vid_out, + .vidioc_s_fmt_vid_out = pxp_s_fmt_vid_out, + + .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, + .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, + .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, + .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, + .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, + .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, + .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, + + .vidioc_streamon = v4l2_m2m_ioctl_streamon, + .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, + + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, +}; + +/* + * Queue operations + */ +static int pxp_queue_setup(struct vb2_queue *vq, + unsigned int *nbuffers, unsigned int *nplanes, + unsigned int sizes[], struct device *alloc_devs[]) +{ + struct pxp_ctx *ctx = vb2_get_drv_priv(vq); + struct pxp_q_data *q_data; + unsigned int size, count = *nbuffers; + + q_data = get_q_data(ctx, vq->type); + + size = q_data->sizeimage; + + *nbuffers = count; + + if (*nplanes) + return sizes[0] < size ? -EINVAL : 0; + + *nplanes = 1; + sizes[0] = size; + + dprintk(ctx->dev, "get %d buffer(s) of size %d each.\n", count, size); + + return 0; +} + +static int pxp_buf_prepare(struct vb2_buffer *vb) +{ + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct pxp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + struct pxp_dev *dev = ctx->dev; + struct pxp_q_data *q_data; + + dprintk(ctx->dev, "type: %d\n", vb->vb2_queue->type); + + q_data = get_q_data(ctx, vb->vb2_queue->type); + if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { + if (vbuf->field == V4L2_FIELD_ANY) + vbuf->field = V4L2_FIELD_NONE; + if (vbuf->field != V4L2_FIELD_NONE) { + dprintk(dev, "%s field isn't supported\n", __func__); + return -EINVAL; + } + } + + if (vb2_plane_size(vb, 0) < q_data->sizeimage) { + dprintk(dev, "%s data will not fit into plane (%lu < %lu)\n", + __func__, vb2_plane_size(vb, 0), + (long)q_data->sizeimage); + return -EINVAL; + } + + vb2_set_plane_payload(vb, 0, q_data->sizeimage); + + return 0; +} + +static void pxp_buf_queue(struct vb2_buffer *vb) +{ + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct pxp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + + v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); +} + +static int pxp_start_streaming(struct vb2_queue *q, unsigned int count) +{ + struct pxp_ctx *ctx = vb2_get_drv_priv(q); + struct pxp_q_data *q_data = get_q_data(ctx, q->type); + + q_data->sequence = 0; + return 0; +} + +static void pxp_stop_streaming(struct vb2_queue *q) +{ + struct pxp_ctx *ctx = vb2_get_drv_priv(q); + struct vb2_v4l2_buffer *vbuf; + unsigned long flags; + + for (;;) { + if (V4L2_TYPE_IS_OUTPUT(q->type)) + vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); + else + vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); + if (vbuf == NULL) + return; + spin_lock_irqsave(&ctx->dev->irqlock, flags); + v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR); + spin_unlock_irqrestore(&ctx->dev->irqlock, flags); + } +} + +static const struct vb2_ops pxp_qops = { + .queue_setup = pxp_queue_setup, + .buf_prepare = pxp_buf_prepare, + .buf_queue = pxp_buf_queue, + .start_streaming = pxp_start_streaming, + .stop_streaming = pxp_stop_streaming, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, +}; + +static int queue_init(void *priv, struct vb2_queue *src_vq, + struct vb2_queue *dst_vq) +{ + struct pxp_ctx *ctx = priv; + int ret; + + src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; + src_vq->io_modes = VB2_MMAP | VB2_DMABUF; + src_vq->drv_priv = ctx; + src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); + src_vq->ops = &pxp_qops; + src_vq->mem_ops = &vb2_dma_contig_memops; + src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; + src_vq->lock = &ctx->dev->dev_mutex; + src_vq->dev = ctx->dev->v4l2_dev.dev; + + ret = vb2_queue_init(src_vq); + if (ret) + return ret; + + dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; + dst_vq->drv_priv = ctx; + dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); + dst_vq->ops = &pxp_qops; + dst_vq->mem_ops = &vb2_dma_contig_memops; + dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; + dst_vq->lock = &ctx->dev->dev_mutex; + dst_vq->dev = ctx->dev->v4l2_dev.dev; + + return vb2_queue_init(dst_vq); +} + +/* + * File operations + */ +static int pxp_open(struct file *file) +{ + struct pxp_dev *dev = video_drvdata(file); + struct pxp_ctx *ctx = NULL; + struct v4l2_ctrl_handler *hdl; + int rc = 0; + + if (mutex_lock_interruptible(&dev->dev_mutex)) + return -ERESTARTSYS; + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) { + rc = -ENOMEM; + goto open_unlock; + } + + v4l2_fh_init(&ctx->fh, video_devdata(file)); + file->private_data = &ctx->fh; + ctx->dev = dev; + hdl = &ctx->hdl; + v4l2_ctrl_handler_init(hdl, 4); + v4l2_ctrl_new_std(hdl, &pxp_ctrl_ops, V4L2_CID_HFLIP, 0, 1, 1, 0); + v4l2_ctrl_new_std(hdl, &pxp_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0); + v4l2_ctrl_new_std(hdl, &pxp_ctrl_ops, V4L2_CID_ALPHA_COMPONENT, + 0, 255, 1, 255); + if (hdl->error) { + rc = hdl->error; + v4l2_ctrl_handler_free(hdl); + kfree(ctx); + goto open_unlock; + } + ctx->fh.ctrl_handler = hdl; + v4l2_ctrl_handler_setup(hdl); + + ctx->q_data[V4L2_M2M_SRC].fmt = &formats[0]; + ctx->q_data[V4L2_M2M_SRC].width = 640; + ctx->q_data[V4L2_M2M_SRC].height = 480; + ctx->q_data[V4L2_M2M_SRC].bytesperline = + pxp_bytesperline(&formats[0], 640); + ctx->q_data[V4L2_M2M_SRC].sizeimage = + pxp_sizeimage(&formats[0], 640, 480); + ctx->q_data[V4L2_M2M_DST] = ctx->q_data[V4L2_M2M_SRC]; + ctx->colorspace = V4L2_COLORSPACE_REC709; + + ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init); + + if (IS_ERR(ctx->fh.m2m_ctx)) { + rc = PTR_ERR(ctx->fh.m2m_ctx); + + v4l2_ctrl_handler_free(hdl); + v4l2_fh_exit(&ctx->fh); + kfree(ctx); + goto open_unlock; + } + + v4l2_fh_add(&ctx->fh); + atomic_inc(&dev->num_inst); + + dprintk(dev, "Created instance: %p, m2m_ctx: %p\n", + ctx, ctx->fh.m2m_ctx); + +open_unlock: + mutex_unlock(&dev->dev_mutex); + return rc; +} + +static int pxp_release(struct file *file) +{ + struct pxp_dev *dev = video_drvdata(file); + struct pxp_ctx *ctx = file2ctx(file); + + dprintk(dev, "Releasing instance %p\n", ctx); + + v4l2_fh_del(&ctx->fh); + v4l2_fh_exit(&ctx->fh); + v4l2_ctrl_handler_free(&ctx->hdl); + mutex_lock(&dev->dev_mutex); + v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); + mutex_unlock(&dev->dev_mutex); + kfree(ctx); + + atomic_dec(&dev->num_inst); + + return 0; +} + +static const struct v4l2_file_operations pxp_fops = { + .owner = THIS_MODULE, + .open = pxp_open, + .release = pxp_release, + .poll = v4l2_m2m_fop_poll, + .unlocked_ioctl = video_ioctl2, + .mmap = v4l2_m2m_fop_mmap, +}; + +static const struct video_device pxp_videodev = { + .name = MEM2MEM_NAME, + .vfl_dir = VFL_DIR_M2M, + .fops = &pxp_fops, + .device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING, + .ioctl_ops = &pxp_ioctl_ops, + .minor = -1, + .release = video_device_release_empty, +}; + +static const struct v4l2_m2m_ops m2m_ops = { + .device_run = pxp_device_run, + .job_ready = pxp_job_ready, + .job_abort = pxp_job_abort, +}; + +static void pxp_soft_reset(struct pxp_dev *dev) +{ + int ret; + u32 val; + + writel(BM_PXP_CTRL_SFTRST, dev->mmio + HW_PXP_CTRL_CLR); + writel(BM_PXP_CTRL_CLKGATE, dev->mmio + HW_PXP_CTRL_CLR); + + writel(BM_PXP_CTRL_SFTRST, dev->mmio + HW_PXP_CTRL_SET); + + ret = readl_poll_timeout(dev->mmio + HW_PXP_CTRL, val, + val & BM_PXP_CTRL_CLKGATE, 0, 100); + if (ret < 0) + pr_err("PXP reset timeout\n"); + + writel(BM_PXP_CTRL_SFTRST, dev->mmio + HW_PXP_CTRL_CLR); + writel(BM_PXP_CTRL_CLKGATE, dev->mmio + HW_PXP_CTRL_CLR); +} + +static int pxp_probe(struct platform_device *pdev) +{ + struct pxp_dev *dev; + struct resource *res; + struct video_device *vfd; + int irq; + int ret; + + dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + + dev->clk = devm_clk_get(&pdev->dev, "axi"); + if (IS_ERR(dev->clk)) { + ret = PTR_ERR(dev->clk); + dev_err(&pdev->dev, "Failed to get clk: %d\n", ret); + return ret; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + dev->mmio = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(dev->mmio)) { + ret = PTR_ERR(dev->mmio); + dev_err(&pdev->dev, "Failed to map register space: %d\n", ret); + return ret; + } + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "Failed to get irq resource: %d\n", irq); + return irq; + } + + ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, pxp_irq_handler, + IRQF_ONESHOT, dev_name(&pdev->dev), dev); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to request irq: %d\n", ret); + return ret; + } + + clk_prepare_enable(dev->clk); + pxp_soft_reset(dev); + + spin_lock_init(&dev->irqlock); + + ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); + if (ret) + goto err_clk; + + atomic_set(&dev->num_inst, 0); + mutex_init(&dev->dev_mutex); + + dev->vfd = pxp_videodev; + vfd = &dev->vfd; + vfd->lock = &dev->dev_mutex; + vfd->v4l2_dev = &dev->v4l2_dev; + + video_set_drvdata(vfd, dev); + snprintf(vfd->name, sizeof(vfd->name), "%s", pxp_videodev.name); + v4l2_info(&dev->v4l2_dev, + "Device registered as /dev/video%d\n", vfd->num); + + platform_set_drvdata(pdev, dev); + + dev->m2m_dev = v4l2_m2m_init(&m2m_ops); + if (IS_ERR(dev->m2m_dev)) { + v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n"); + ret = PTR_ERR(dev->m2m_dev); + goto err_v4l2; + } + + ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); + if (ret) { + v4l2_err(&dev->v4l2_dev, "Failed to register video device\n"); + goto err_m2m; + } + + return 0; + +err_m2m: + v4l2_m2m_release(dev->m2m_dev); +err_v4l2: + v4l2_device_unregister(&dev->v4l2_dev); +err_clk: + clk_disable_unprepare(dev->clk); + + return ret; +} + +static int pxp_remove(struct platform_device *pdev) +{ + struct pxp_dev *dev = platform_get_drvdata(pdev); + + writel(BM_PXP_CTRL_CLKGATE, dev->mmio + HW_PXP_CTRL_SET); + writel(BM_PXP_CTRL_SFTRST, dev->mmio + HW_PXP_CTRL_SET); + + clk_disable_unprepare(dev->clk); + + v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_NAME); + video_unregister_device(&dev->vfd); + v4l2_m2m_release(dev->m2m_dev); + v4l2_device_unregister(&dev->v4l2_dev); + + return 0; +} + +static const struct of_device_id pxp_dt_ids[] = { + { .compatible = "fsl,imx6ull-pxp", .data = NULL }, + { }, +}; +MODULE_DEVICE_TABLE(of, pxp_dt_ids); + +static struct platform_driver pxp_driver = { + .probe = pxp_probe, + .remove = pxp_remove, + .driver = { + .name = MEM2MEM_NAME, + .of_match_table = of_match_ptr(pxp_dt_ids), + }, +}; + +module_platform_driver(pxp_driver); + +MODULE_DESCRIPTION("i.MX PXP mem2mem scaler/CSC/rotator"); +MODULE_AUTHOR("Philipp Zabel <kernel@pengutronix.de>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/platform/imx-pxp.h b/drivers/media/platform/imx-pxp.h new file mode 100644 index 000000000000..44f95c749d2e --- /dev/null +++ b/drivers/media/platform/imx-pxp.h @@ -0,0 +1,1685 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Freescale PXP Register Definitions + * + * based on pxp_dma_v3.h, Xml Revision: 1.77, Template Revision: 1.3 + * + * Copyright 2014-2015 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +#ifndef __IMX_PXP_H__ +#define __IMX_PXP_H__ + +#define HW_PXP_CTRL (0x00000000) +#define HW_PXP_CTRL_SET (0x00000004) +#define HW_PXP_CTRL_CLR (0x00000008) +#define HW_PXP_CTRL_TOG (0x0000000c) + +#define BM_PXP_CTRL_SFTRST 0x80000000 +#define BF_PXP_CTRL_SFTRST(v) \ + (((v) << 31) & BM_PXP_CTRL_SFTRST) +#define BM_PXP_CTRL_CLKGATE 0x40000000 +#define BF_PXP_CTRL_CLKGATE(v) \ + (((v) << 30) & BM_PXP_CTRL_CLKGATE) +#define BM_PXP_CTRL_RSVD4 0x20000000 +#define BF_PXP_CTRL_RSVD4(v) \ + (((v) << 29) & BM_PXP_CTRL_RSVD4) +#define BM_PXP_CTRL_EN_REPEAT 0x10000000 +#define BF_PXP_CTRL_EN_REPEAT(v) \ + (((v) << 28) & BM_PXP_CTRL_EN_REPEAT) +#define BM_PXP_CTRL_ENABLE_ROTATE1 0x08000000 +#define BF_PXP_CTRL_ENABLE_ROTATE1(v) \ + (((v) << 27) & BM_PXP_CTRL_ENABLE_ROTATE1) +#define BM_PXP_CTRL_ENABLE_ROTATE0 0x04000000 +#define BF_PXP_CTRL_ENABLE_ROTATE0(v) \ + (((v) << 26) & BM_PXP_CTRL_ENABLE_ROTATE0) +#define BM_PXP_CTRL_ENABLE_LUT 0x02000000 +#define BF_PXP_CTRL_ENABLE_LUT(v) \ + (((v) << 25) & BM_PXP_CTRL_ENABLE_LUT) +#define BM_PXP_CTRL_ENABLE_CSC2 0x01000000 +#define BF_PXP_CTRL_ENABLE_CSC2(v) \ + (((v) << 24) & BM_PXP_CTRL_ENABLE_CSC2) +#define BM_PXP_CTRL_BLOCK_SIZE 0x00800000 +#define BF_PXP_CTRL_BLOCK_SIZE(v) \ + (((v) << 23) & BM_PXP_CTRL_BLOCK_SIZE) +#define BV_PXP_CTRL_BLOCK_SIZE__8X8 0x0 +#define BV_PXP_CTRL_BLOCK_SIZE__16X16 0x1 +#define BM_PXP_CTRL_RSVD1 0x00400000 +#define BF_PXP_CTRL_RSVD1(v) \ + (((v) << 22) & BM_PXP_CTRL_RSVD1) +#define BM_PXP_CTRL_ENABLE_ALPHA_B 0x00200000 +#define BF_PXP_CTRL_ENABLE_ALPHA_B(v) \ + (((v) << 21) & BM_PXP_CTRL_ENABLE_ALPHA_B) +#define BM_PXP_CTRL_ENABLE_INPUT_FETCH_STORE 0x00100000 +#define BF_PXP_CTRL_ENABLE_INPUT_FETCH_STORE(v) \ + (((v) << 20) & BM_PXP_CTRL_ENABLE_INPUT_FETCH_STORE) +#define BM_PXP_CTRL_ENABLE_WFE_B 0x00080000 +#define BF_PXP_CTRL_ENABLE_WFE_B(v) \ + (((v) << 19) & BM_PXP_CTRL_ENABLE_WFE_B) +#define BM_PXP_CTRL_ENABLE_WFE_A 0x00040000 +#define BF_PXP_CTRL_ENABLE_WFE_A(v) \ + (((v) << 18) & BM_PXP_CTRL_ENABLE_WFE_A) +#define BM_PXP_CTRL_ENABLE_DITHER 0x00020000 +#define BF_PXP_CTRL_ENABLE_DITHER(v) \ + (((v) << 17) & BM_PXP_CTRL_ENABLE_DITHER) +#define BM_PXP_CTRL_ENABLE_PS_AS_OUT 0x00010000 +#define BF_PXP_CTRL_ENABLE_PS_AS_OUT(v) \ + (((v) << 16) & BM_PXP_CTRL_ENABLE_PS_AS_OUT) +#define BM_PXP_CTRL_VFLIP1 0x00008000 +#define BF_PXP_CTRL_VFLIP1(v) \ + (((v) << 15) & BM_PXP_CTRL_VFLIP1) +#define BM_PXP_CTRL_HFLIP1 0x00004000 +#define BF_PXP_CTRL_HFLIP1(v) \ + (((v) << 14) & BM_PXP_CTRL_HFLIP1) +#define BP_PXP_CTRL_ROTATE1 12 +#define BM_PXP_CTRL_ROTATE1 0x00003000 +#define BF_PXP_CTRL_ROTATE1(v) \ + (((v) << 12) & BM_PXP_CTRL_ROTATE1) +#define BV_PXP_CTRL_ROTATE1__ROT_0 0x0 +#define BV_PXP_CTRL_ROTATE1__ROT_90 0x1 +#define BV_PXP_CTRL_ROTATE1__ROT_180 0x2 +#define BV_PXP_CTRL_ROTATE1__ROT_270 0x3 +#define BM_PXP_CTRL_VFLIP0 0x00000800 +#define BF_PXP_CTRL_VFLIP0(v) \ + (((v) << 11) & BM_PXP_CTRL_VFLIP0) +#define BM_PXP_CTRL_HFLIP0 0x00000400 +#define BF_PXP_CTRL_HFLIP0(v) \ + (((v) << 10) & BM_PXP_CTRL_HFLIP0) +#define BP_PXP_CTRL_ROTATE0 8 +#define BM_PXP_CTRL_ROTATE0 0x00000300 +#define BF_PXP_CTRL_ROTATE0(v) \ + (((v) << 8) & BM_PXP_CTRL_ROTATE0) +#define BV_PXP_CTRL_ROTATE0__ROT_0 0x0 +#define BV_PXP_CTRL_ROTATE0__ROT_90 0x1 +#define BV_PXP_CTRL_ROTATE0__ROT_180 0x2 +#define BV_PXP_CTRL_ROTATE0__ROT_270 0x3 +#define BP_PXP_CTRL_RSVD0 6 +#define BM_PXP_CTRL_RSVD0 0x000000C0 +#define BF_PXP_CTRL_RSVD0(v) \ + (((v) << 6) & BM_PXP_CTRL_RSVD0) +#define BM_PXP_CTRL_HANDSHAKE_ABORT_SKIP 0x00000020 +#define BF_PXP_CTRL_HANDSHAKE_ABORT_SKIP(v) \ + (((v) << 5) & BM_PXP_CTRL_HANDSHAKE_ABORT_SKIP) +#define BM_PXP_CTRL_ENABLE_LCD0_HANDSHAKE 0x00000010 +#define BF_PXP_CTRL_ENABLE_LCD0_HANDSHAKE(v) \ + (((v) << 4) & BM_PXP_CTRL_ENABLE_LCD0_HANDSHAKE) +#define BM_PXP_CTRL_LUT_DMA_IRQ_ENABLE 0x00000008 +#define BF_PXP_CTRL_LUT_DMA_IRQ_ENABLE(v) \ + (((v) << 3) & BM_PXP_CTRL_LUT_DMA_IRQ_ENABLE) +#define BM_PXP_CTRL_NEXT_IRQ_ENABLE 0x00000004 +#define BF_PXP_CTRL_NEXT_IRQ_ENABLE(v) \ + (((v) << 2) & BM_PXP_CTRL_NEXT_IRQ_ENABLE) +#define BM_PXP_CTRL_IRQ_ENABLE 0x00000002 +#define BF_PXP_CTRL_IRQ_ENABLE(v) \ + (((v) << 1) & BM_PXP_CTRL_IRQ_ENABLE) +#define BM_PXP_CTRL_ENABLE 0x00000001 +#define BF_PXP_CTRL_ENABLE(v) \ + (((v) << 0) & BM_PXP_CTRL_ENABLE) + +#define HW_PXP_STAT (0x00000010) +#define HW_PXP_STAT_SET (0x00000014) +#define HW_PXP_STAT_CLR (0x00000018) +#define HW_PXP_STAT_TOG (0x0000001c) + +#define BP_PXP_STAT_BLOCKX 24 +#define BM_PXP_STAT_BLOCKX 0xFF000000 +#define BF_PXP_STAT_BLOCKX(v) \ + (((v) << 24) & BM_PXP_STAT_BLOCKX) +#define BP_PXP_STAT_BLOCKY 16 +#define BM_PXP_STAT_BLOCKY 0x00FF0000 +#define BF_PXP_STAT_BLOCKY(v) \ + (((v) << 16) & BM_PXP_STAT_BLOCKY) +#define BP_PXP_STAT_AXI_ERROR_ID_1 12 +#define BM_PXP_STAT_AXI_ERROR_ID_1 0x0000F000 +#define BF_PXP_STAT_AXI_ERROR_ID_1(v) \ + (((v) << 12) & BM_PXP_STAT_AXI_ERROR_ID_1) +#define BM_PXP_STAT_RSVD2 0x00000800 +#define BF_PXP_STAT_RSVD2(v) \ + (((v) << 11) & BM_PXP_STAT_RSVD2) +#define BM_PXP_STAT_AXI_READ_ERROR_1 0x00000400 +#define BF_PXP_STAT_AXI_READ_ERROR_1(v) \ + (((v) << 10) & BM_PXP_STAT_AXI_READ_ERROR_1) +#define BM_PXP_STAT_AXI_WRITE_ERROR_1 0x00000200 +#define BF_PXP_STAT_AXI_WRITE_ERROR_1(v) \ + (((v) << 9) & BM_PXP_STAT_AXI_WRITE_ERROR_1) +#define BM_PXP_STAT_LUT_DMA_LOAD_DONE_IRQ 0x00000100 +#define BF_PXP_STAT_LUT_DMA_LOAD_DONE_IRQ(v) \ + (((v) << 8) & BM_PXP_STAT_LUT_DMA_LOAD_DONE_IRQ) +#define BP_PXP_STAT_AXI_ERROR_ID_0 4 +#define BM_PXP_STAT_AXI_ERROR_ID_0 0x000000F0 +#define BF_PXP_STAT_AXI_ERROR_ID_0(v) \ + (((v) << 4) & BM_PXP_STAT_AXI_ERROR_ID_0) +#define BM_PXP_STAT_NEXT_IRQ 0x00000008 +#define BF_PXP_STAT_NEXT_IRQ(v) \ + (((v) << 3) & BM_PXP_STAT_NEXT_IRQ) +#define BM_PXP_STAT_AXI_READ_ERROR_0 0x00000004 +#define BF_PXP_STAT_AXI_READ_ERROR_0(v) \ + (((v) << 2) & BM_PXP_STAT_AXI_READ_ERROR_0) +#define BM_PXP_STAT_AXI_WRITE_ERROR_0 0x00000002 +#define BF_PXP_STAT_AXI_WRITE_ERROR_0(v) \ + (((v) << 1) & BM_PXP_STAT_AXI_WRITE_ERROR_0) +#define BM_PXP_STAT_IRQ0 0x00000001 +#define BF_PXP_STAT_IRQ0(v) \ + (((v) << 0) & BM_PXP_STAT_IRQ0) + +#define HW_PXP_OUT_CTRL (0x00000020) +#define HW_PXP_OUT_CTRL_SET (0x00000024) +#define HW_PXP_OUT_CTRL_CLR (0x00000028) +#define HW_PXP_OUT_CTRL_TOG (0x0000002c) + +#define BP_PXP_OUT_CTRL_ALPHA 24 +#define BM_PXP_OUT_CTRL_ALPHA 0xFF000000 +#define BF_PXP_OUT_CTRL_ALPHA(v) \ + (((v) << 24) & BM_PXP_OUT_CTRL_ALPHA) +#define BM_PXP_OUT_CTRL_ALPHA_OUTPUT 0x00800000 +#define BF_PXP_OUT_CTRL_ALPHA_OUTPUT(v) \ + (((v) << 23) & BM_PXP_OUT_CTRL_ALPHA_OUTPUT) +#define BP_PXP_OUT_CTRL_RSVD1 10 +#define BM_PXP_OUT_CTRL_RSVD1 0x007FFC00 +#define BF_PXP_OUT_CTRL_RSVD1(v) \ + (((v) << 10) & BM_PXP_OUT_CTRL_RSVD1) +#define BP_PXP_OUT_CTRL_INTERLACED_OUTPUT 8 +#define BM_PXP_OUT_CTRL_INTERLACED_OUTPUT 0x00000300 +#define BF_PXP_OUT_CTRL_INTERLACED_OUTPUT(v) \ + (((v) << 8) & BM_PXP_OUT_CTRL_INTERLACED_OUTPUT) +#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__PROGRESSIVE 0x0 +#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__FIELD0 0x1 +#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__FIELD1 0x2 +#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__INTERLACED 0x3 +#define BP_PXP_OUT_CTRL_RSVD0 5 +#define BM_PXP_OUT_CTRL_RSVD0 0x000000E0 +#define BF_PXP_OUT_CTRL_RSVD0(v) \ + (((v) << 5) & BM_PXP_OUT_CTRL_RSVD0) +#define BP_PXP_OUT_CTRL_FORMAT 0 +#define BM_PXP_OUT_CTRL_FORMAT 0x0000001F +#define BF_PXP_OUT_CTRL_FORMAT(v) \ + (((v) << 0) & BM_PXP_OUT_CTRL_FORMAT) +#define BV_PXP_OUT_CTRL_FORMAT__ARGB8888 0x0 +#define BV_PXP_OUT_CTRL_FORMAT__RGB888 0x4 +#define BV_PXP_OUT_CTRL_FORMAT__RGB888P 0x5 +#define BV_PXP_OUT_CTRL_FORMAT__ARGB1555 0x8 +#define BV_PXP_OUT_CTRL_FORMAT__ARGB4444 0x9 +#define BV_PXP_OUT_CTRL_FORMAT__RGB555 0xC +#define BV_PXP_OUT_CTRL_FORMAT__RGB444 0xD +#define BV_PXP_OUT_CTRL_FORMAT__RGB565 0xE +#define BV_PXP_OUT_CTRL_FORMAT__YUV1P444 0x10 +#define BV_PXP_OUT_CTRL_FORMAT__UYVY1P422 0x12 +#define BV_PXP_OUT_CTRL_FORMAT__VYUY1P422 0x13 +#define BV_PXP_OUT_CTRL_FORMAT__Y8 0x14 +#define BV_PXP_OUT_CTRL_FORMAT__Y4 0x15 +#define BV_PXP_OUT_CTRL_FORMAT__YUV2P422 0x18 +#define BV_PXP_OUT_CTRL_FORMAT__YUV2P420 0x19 +#define BV_PXP_OUT_CTRL_FORMAT__YVU2P422 0x1A +#define BV_PXP_OUT_CTRL_FORMAT__YVU2P420 0x1B + +#define HW_PXP_OUT_BUF (0x00000030) + +#define BP_PXP_OUT_BUF_ADDR 0 +#define BM_PXP_OUT_BUF_ADDR 0xFFFFFFFF +#define BF_PXP_OUT_BUF_ADDR(v) (v) + +#define HW_PXP_OUT_BUF2 (0x00000040) + +#define BP_PXP_OUT_BUF2_ADDR 0 +#define BM_PXP_OUT_BUF2_ADDR 0xFFFFFFFF +#define BF_PXP_OUT_BUF2_ADDR(v) (v) + +#define HW_PXP_OUT_PITCH (0x00000050) + +#define BP_PXP_OUT_PITCH_RSVD 16 +#define BM_PXP_OUT_PITCH_RSVD 0xFFFF0000 +#define BF_PXP_OUT_PITCH_RSVD(v) \ + (((v) << 16) & BM_PXP_OUT_PITCH_RSVD) +#define BP_PXP_OUT_PITCH_PITCH 0 +#define BM_PXP_OUT_PITCH_PITCH 0x0000FFFF +#define BF_PXP_OUT_PITCH_PITCH(v) \ + (((v) << 0) & BM_PXP_OUT_PITCH_PITCH) + +#define HW_PXP_OUT_LRC (0x00000060) + +#define BP_PXP_OUT_LRC_RSVD1 30 +#define BM_PXP_OUT_LRC_RSVD1 0xC0000000 +#define BF_PXP_OUT_LRC_RSVD1(v) \ + (((v) << 30) & BM_PXP_OUT_LRC_RSVD1) +#define BP_PXP_OUT_LRC_X 16 +#define BM_PXP_OUT_LRC_X 0x3FFF0000 +#define BF_PXP_OUT_LRC_X(v) \ + (((v) << 16) & BM_PXP_OUT_LRC_X) +#define BP_PXP_OUT_LRC_RSVD0 14 +#define BM_PXP_OUT_LRC_RSVD0 0x0000C000 +#define BF_PXP_OUT_LRC_RSVD0(v) \ + (((v) << 14) & BM_PXP_OUT_LRC_RSVD0) +#define BP_PXP_OUT_LRC_Y 0 +#define BM_PXP_OUT_LRC_Y 0x00003FFF +#define BF_PXP_OUT_LRC_Y(v) \ + (((v) << 0) & BM_PXP_OUT_LRC_Y) + +#define HW_PXP_OUT_PS_ULC (0x00000070) + +#define BP_PXP_OUT_PS_ULC_RSVD1 30 +#define BM_PXP_OUT_PS_ULC_RSVD1 0xC0000000 +#define BF_PXP_OUT_PS_ULC_RSVD1(v) \ + (((v) << 30) & BM_PXP_OUT_PS_ULC_RSVD1) +#define BP_PXP_OUT_PS_ULC_X 16 +#define BM_PXP_OUT_PS_ULC_X 0x3FFF0000 +#define BF_PXP_OUT_PS_ULC_X(v) \ + (((v) << 16) & BM_PXP_OUT_PS_ULC_X) +#define BP_PXP_OUT_PS_ULC_RSVD0 14 +#define BM_PXP_OUT_PS_ULC_RSVD0 0x0000C000 +#define BF_PXP_OUT_PS_ULC_RSVD0(v) \ + (((v) << 14) & BM_PXP_OUT_PS_ULC_RSVD0) +#define BP_PXP_OUT_PS_ULC_Y 0 +#define BM_PXP_OUT_PS_ULC_Y 0x00003FFF +#define BF_PXP_OUT_PS_ULC_Y(v) \ + (((v) << 0) & BM_PXP_OUT_PS_ULC_Y) + +#define HW_PXP_OUT_PS_LRC (0x00000080) + +#define BP_PXP_OUT_PS_LRC_RSVD1 30 +#define BM_PXP_OUT_PS_LRC_RSVD1 0xC0000000 +#define BF_PXP_OUT_PS_LRC_RSVD1(v) \ + (((v) << 30) & BM_PXP_OUT_PS_LRC_RSVD1) +#define BP_PXP_OUT_PS_LRC_X 16 +#define BM_PXP_OUT_PS_LRC_X 0x3FFF0000 +#define BF_PXP_OUT_PS_LRC_X(v) \ + (((v) << 16) & BM_PXP_OUT_PS_LRC_X) +#define BP_PXP_OUT_PS_LRC_RSVD0 14 +#define BM_PXP_OUT_PS_LRC_RSVD0 0x0000C000 +#define BF_PXP_OUT_PS_LRC_RSVD0(v) \ + (((v) << 14) & BM_PXP_OUT_PS_LRC_RSVD0) +#define BP_PXP_OUT_PS_LRC_Y 0 +#define BM_PXP_OUT_PS_LRC_Y 0x00003FFF +#define BF_PXP_OUT_PS_LRC_Y(v) \ + (((v) << 0) & BM_PXP_OUT_PS_LRC_Y) + +#define HW_PXP_OUT_AS_ULC (0x00000090) + +#define BP_PXP_OUT_AS_ULC_RSVD1 30 +#define BM_PXP_OUT_AS_ULC_RSVD1 0xC0000000 +#define BF_PXP_OUT_AS_ULC_RSVD1(v) \ + (((v) << 30) & BM_PXP_OUT_AS_ULC_RSVD1) +#define BP_PXP_OUT_AS_ULC_X 16 +#define BM_PXP_OUT_AS_ULC_X 0x3FFF0000 +#define BF_PXP_OUT_AS_ULC_X(v) \ + (((v) << 16) & BM_PXP_OUT_AS_ULC_X) +#define BP_PXP_OUT_AS_ULC_RSVD0 14 +#define BM_PXP_OUT_AS_ULC_RSVD0 0x0000C000 +#define BF_PXP_OUT_AS_ULC_RSVD0(v) \ + (((v) << 14) & BM_PXP_OUT_AS_ULC_RSVD0) +#define BP_PXP_OUT_AS_ULC_Y 0 +#define BM_PXP_OUT_AS_ULC_Y 0x00003FFF +#define BF_PXP_OUT_AS_ULC_Y(v) \ + (((v) << 0) & BM_PXP_OUT_AS_ULC_Y) + +#define HW_PXP_OUT_AS_LRC (0x000000a0) + +#define BP_PXP_OUT_AS_LRC_RSVD1 30 +#define BM_PXP_OUT_AS_LRC_RSVD1 0xC0000000 +#define BF_PXP_OUT_AS_LRC_RSVD1(v) \ + (((v) << 30) & BM_PXP_OUT_AS_LRC_RSVD1) +#define BP_PXP_OUT_AS_LRC_X 16 +#define BM_PXP_OUT_AS_LRC_X 0x3FFF0000 +#define BF_PXP_OUT_AS_LRC_X(v) \ + (((v) << 16) & BM_PXP_OUT_AS_LRC_X) +#define BP_PXP_OUT_AS_LRC_RSVD0 14 +#define BM_PXP_OUT_AS_LRC_RSVD0 0x0000C000 +#define BF_PXP_OUT_AS_LRC_RSVD0(v) \ + (((v) << 14) & BM_PXP_OUT_AS_LRC_RSVD0) +#define BP_PXP_OUT_AS_LRC_Y 0 +#define BM_PXP_OUT_AS_LRC_Y 0x00003FFF +#define BF_PXP_OUT_AS_LRC_Y(v) \ + (((v) << 0) & BM_PXP_OUT_AS_LRC_Y) + +#define HW_PXP_PS_CTRL (0x000000b0) +#define HW_PXP_PS_CTRL_SET (0x000000b4) +#define HW_PXP_PS_CTRL_CLR (0x000000b8) +#define HW_PXP_PS_CTRL_TOG (0x000000bc) + +#define BP_PXP_PS_CTRL_RSVD1 12 +#define BM_PXP_PS_CTRL_RSVD1 0xFFFFF000 +#define BF_PXP_PS_CTRL_RSVD1(v) \ + (((v) << 12) & BM_PXP_PS_CTRL_RSVD1) +#define BP_PXP_PS_CTRL_DECX 10 +#define BM_PXP_PS_CTRL_DECX 0x00000C00 +#define BF_PXP_PS_CTRL_DECX(v) \ + (((v) << 10) & BM_PXP_PS_CTRL_DECX) +#define BV_PXP_PS_CTRL_DECX__DISABLE 0x0 +#define BV_PXP_PS_CTRL_DECX__DECX2 0x1 +#define BV_PXP_PS_CTRL_DECX__DECX4 0x2 +#define BV_PXP_PS_CTRL_DECX__DECX8 0x3 +#define BP_PXP_PS_CTRL_DECY 8 +#define BM_PXP_PS_CTRL_DECY 0x00000300 +#define BF_PXP_PS_CTRL_DECY(v) \ + (((v) << 8) & BM_PXP_PS_CTRL_DECY) +#define BV_PXP_PS_CTRL_DECY__DISABLE 0x0 +#define BV_PXP_PS_CTRL_DECY__DECY2 0x1 +#define BV_PXP_PS_CTRL_DECY__DECY4 0x2 +#define BV_PXP_PS_CTRL_DECY__DECY8 0x3 +#define BM_PXP_PS_CTRL_RSVD0 0x00000080 +#define BF_PXP_PS_CTRL_RSVD0(v) \ + (((v) << 7) & BM_PXP_PS_CTRL_RSVD0) +#define BM_PXP_PS_CTRL_WB_SWAP 0x00000040 +#define BF_PXP_PS_CTRL_WB_SWAP(v) \ + (((v) << 6) & BM_PXP_PS_CTRL_WB_SWAP) +#define BP_PXP_PS_CTRL_FORMAT 0 +#define BM_PXP_PS_CTRL_FORMAT 0x0000003F +#define BF_PXP_PS_CTRL_FORMAT(v) \ + (((v) << 0) & BM_PXP_PS_CTRL_FORMAT) +#define BV_PXP_PS_CTRL_FORMAT__RGB888 0x4 +#define BV_PXP_PS_CTRL_FORMAT__RGB555 0xC +#define BV_PXP_PS_CTRL_FORMAT__RGB444 0xD +#define BV_PXP_PS_CTRL_FORMAT__RGB565 0xE +#define BV_PXP_PS_CTRL_FORMAT__YUV1P444 0x10 +#define BV_PXP_PS_CTRL_FORMAT__UYVY1P422 0x12 +#define BV_PXP_PS_CTRL_FORMAT__VYUY1P422 0x13 +#define BV_PXP_PS_CTRL_FORMAT__Y8 0x14 +#define BV_PXP_PS_CTRL_FORMAT__Y4 0x15 +#define BV_PXP_PS_CTRL_FORMAT__YUV2P422 0x18 +#define BV_PXP_PS_CTRL_FORMAT__YUV2P420 0x19 +#define BV_PXP_PS_CTRL_FORMAT__YVU2P422 0x1A +#define BV_PXP_PS_CTRL_FORMAT__YVU2P420 0x1B +#define BV_PXP_PS_CTRL_FORMAT__YUV422 0x1E +#define BV_PXP_PS_CTRL_FORMAT__YUV420 0x1F + +#define HW_PXP_PS_BUF (0x000000c0) + +#define BP_PXP_PS_BUF_ADDR 0 +#define BM_PXP_PS_BUF_ADDR 0xFFFFFFFF +#define BF_PXP_PS_BUF_ADDR(v) (v) + +#define HW_PXP_PS_UBUF (0x000000d0) + +#define BP_PXP_PS_UBUF_ADDR 0 +#define BM_PXP_PS_UBUF_ADDR 0xFFFFFFFF +#define BF_PXP_PS_UBUF_ADDR(v) (v) + +#define HW_PXP_PS_VBUF (0x000000e0) + +#define BP_PXP_PS_VBUF_ADDR 0 +#define BM_PXP_PS_VBUF_ADDR 0xFFFFFFFF +#define BF_PXP_PS_VBUF_ADDR(v) (v) + +#define HW_PXP_PS_PITCH (0x000000f0) + +#define BP_PXP_PS_PITCH_RSVD 16 +#define BM_PXP_PS_PITCH_RSVD 0xFFFF0000 +#define BF_PXP_PS_PITCH_RSVD(v) \ + (((v) << 16) & BM_PXP_PS_PITCH_RSVD) +#define BP_PXP_PS_PITCH_PITCH 0 +#define BM_PXP_PS_PITCH_PITCH 0x0000FFFF +#define BF_PXP_PS_PITCH_PITCH(v) \ + (((v) << 0) & BM_PXP_PS_PITCH_PITCH) + +#define HW_PXP_PS_BACKGROUND_0 (0x00000100) + +#define BP_PXP_PS_BACKGROUND_0_RSVD 24 +#define BM_PXP_PS_BACKGROUND_0_RSVD 0xFF000000 +#define BF_PXP_PS_BACKGROUND_0_RSVD(v) \ + (((v) << 24) & BM_PXP_PS_BACKGROUND_0_RSVD) +#define BP_PXP_PS_BACKGROUND_0_COLOR 0 +#define BM_PXP_PS_BACKGROUND_0_COLOR 0x00FFFFFF +#define BF_PXP_PS_BACKGROUND_0_COLOR(v) \ + (((v) << 0) & BM_PXP_PS_BACKGROUND_0_COLOR) + +#define HW_PXP_PS_SCALE (0x00000110) + +#define BM_PXP_PS_SCALE_RSVD2 0x80000000 +#define BF_PXP_PS_SCALE_RSVD2(v) \ + (((v) << 31) & BM_PXP_PS_SCALE_RSVD2) +#define BP_PXP_PS_SCALE_YSCALE 16 +#define BM_PXP_PS_SCALE_YSCALE 0x7FFF0000 +#define BF_PXP_PS_SCALE_YSCALE(v) \ + (((v) << 16) & BM_PXP_PS_SCALE_YSCALE) +#define BM_PXP_PS_SCALE_RSVD1 0x00008000 +#define BF_PXP_PS_SCALE_RSVD1(v) \ + (((v) << 15) & BM_PXP_PS_SCALE_RSVD1) +#define BP_PXP_PS_SCALE_XSCALE 0 +#define BM_PXP_PS_SCALE_XSCALE 0x00007FFF +#define BF_PXP_PS_SCALE_XSCALE(v) \ + (((v) << 0) & BM_PXP_PS_SCALE_XSCALE) + +#define HW_PXP_PS_OFFSET (0x00000120) + +#define BP_PXP_PS_OFFSET_RSVD2 28 +#define BM_PXP_PS_OFFSET_RSVD2 0xF0000000 +#define BF_PXP_PS_OFFSET_RSVD2(v) \ + (((v) << 28) & BM_PXP_PS_OFFSET_RSVD2) +#define BP_PXP_PS_OFFSET_YOFFSET 16 +#define BM_PXP_PS_OFFSET_YOFFSET 0x0FFF0000 +#define BF_PXP_PS_OFFSET_YOFFSET(v) \ + (((v) << 16) & BM_PXP_PS_OFFSET_YOFFSET) +#define BP_PXP_PS_OFFSET_RSVD1 12 +#define BM_PXP_PS_OFFSET_RSVD1 0x0000F000 +#define BF_PXP_PS_OFFSET_RSVD1(v) \ + (((v) << 12) & BM_PXP_PS_OFFSET_RSVD1) +#define BP_PXP_PS_OFFSET_XOFFSET 0 +#define BM_PXP_PS_OFFSET_XOFFSET 0x00000FFF +#define BF_PXP_PS_OFFSET_XOFFSET(v) \ + (((v) << 0) & BM_PXP_PS_OFFSET_XOFFSET) + +#define HW_PXP_PS_CLRKEYLOW_0 (0x00000130) + +#define BP_PXP_PS_CLRKEYLOW_0_RSVD1 24 +#define BM_PXP_PS_CLRKEYLOW_0_RSVD1 0xFF000000 +#define BF_PXP_PS_CLRKEYLOW_0_RSVD1(v) \ + (((v) << 24) & BM_PXP_PS_CLRKEYLOW_0_RSVD1) +#define BP_PXP_PS_CLRKEYLOW_0_PIXEL 0 +#define BM_PXP_PS_CLRKEYLOW_0_PIXEL 0x00FFFFFF +#define BF_PXP_PS_CLRKEYLOW_0_PIXEL(v) \ + (((v) << 0) & BM_PXP_PS_CLRKEYLOW_0_PIXEL) + +#define HW_PXP_PS_CLRKEYHIGH_0 (0x00000140) + +#define BP_PXP_PS_CLRKEYHIGH_0_RSVD1 24 +#define BM_PXP_PS_CLRKEYHIGH_0_RSVD1 0xFF000000 +#define BF_PXP_PS_CLRKEYHIGH_0_RSVD1(v) \ + (((v) << 24) & BM_PXP_PS_CLRKEYHIGH_0_RSVD1) +#define BP_PXP_PS_CLRKEYHIGH_0_PIXEL 0 +#define BM_PXP_PS_CLRKEYHIGH_0_PIXEL 0x00FFFFFF +#define BF_PXP_PS_CLRKEYHIGH_0_PIXEL(v) \ + (((v) << 0) & BM_PXP_PS_CLRKEYHIGH_0_PIXEL) + +#define HW_PXP_AS_CTRL (0x00000150) + +#define BP_PXP_AS_CTRL_RSVD1 22 +#define BM_PXP_AS_CTRL_RSVD1 0xFFC00000 +#define BF_PXP_AS_CTRL_RSVD1(v) \ + (((v) << 22) & BM_PXP_AS_CTRL_RSVD1) +#define BM_PXP_AS_CTRL_ALPHA1_INVERT 0x00200000 +#define BF_PXP_AS_CTRL_ALPHA1_INVERT(v) \ + (((v) << 21) & BM_PXP_AS_CTRL_ALPHA1_INVERT) +#define BM_PXP_AS_CTRL_ALPHA0_INVERT 0x00100000 +#define BF_PXP_AS_CTRL_ALPHA0_INVERT(v) \ + (((v) << 20) & BM_PXP_AS_CTRL_ALPHA0_INVERT) +#define BP_PXP_AS_CTRL_ROP 16 +#define BM_PXP_AS_CTRL_ROP 0x000F0000 +#define BF_PXP_AS_CTRL_ROP(v) \ + (((v) << 16) & BM_PXP_AS_CTRL_ROP) +#define BV_PXP_AS_CTRL_ROP__MASKAS 0x0 +#define BV_PXP_AS_CTRL_ROP__MASKNOTAS 0x1 +#define BV_PXP_AS_CTRL_ROP__MASKASNOT 0x2 +#define BV_PXP_AS_CTRL_ROP__MERGEAS 0x3 +#define BV_PXP_AS_CTRL_ROP__MERGENOTAS 0x4 +#define BV_PXP_AS_CTRL_ROP__MERGEASNOT 0x5 +#define BV_PXP_AS_CTRL_ROP__NOTCOPYAS 0x6 +#define BV_PXP_AS_CTRL_ROP__NOT 0x7 +#define BV_PXP_AS_CTRL_ROP__NOTMASKAS 0x8 +#define BV_PXP_AS_CTRL_ROP__NOTMERGEAS 0x9 +#define BV_PXP_AS_CTRL_ROP__XORAS 0xA +#define BV_PXP_AS_CTRL_ROP__NOTXORAS 0xB +#define BP_PXP_AS_CTRL_ALPHA 8 +#define BM_PXP_AS_CTRL_ALPHA 0x0000FF00 +#define BF_PXP_AS_CTRL_ALPHA(v) \ + (((v) << 8) & BM_PXP_AS_CTRL_ALPHA) +#define BP_PXP_AS_CTRL_FORMAT 4 +#define BM_PXP_AS_CTRL_FORMAT 0x000000F0 +#define BF_PXP_AS_CTRL_FORMAT(v) \ + (((v) << 4) & BM_PXP_AS_CTRL_FORMAT) +#define BV_PXP_AS_CTRL_FORMAT__ARGB8888 0x0 +#define BV_PXP_AS_CTRL_FORMAT__RGBA8888 0x1 +#define BV_PXP_AS_CTRL_FORMAT__RGB888 0x4 +#define BV_PXP_AS_CTRL_FORMAT__ARGB1555 0x8 +#define BV_PXP_AS_CTRL_FORMAT__ARGB4444 0x9 +#define BV_PXP_AS_CTRL_FORMAT__RGB555 0xC +#define BV_PXP_AS_CTRL_FORMAT__RGB444 0xD +#define BV_PXP_AS_CTRL_FORMAT__RGB565 0xE +#define BM_PXP_AS_CTRL_ENABLE_COLORKEY 0x00000008 +#define BF_PXP_AS_CTRL_ENABLE_COLORKEY(v) \ + (((v) << 3) & BM_PXP_AS_CTRL_ENABLE_COLORKEY) +#define BP_PXP_AS_CTRL_ALPHA_CTRL 1 +#define BM_PXP_AS_CTRL_ALPHA_CTRL 0x00000006 +#define BF_PXP_AS_CTRL_ALPHA_CTRL(v) \ + (((v) << 1) & BM_PXP_AS_CTRL_ALPHA_CTRL) +#define BV_PXP_AS_CTRL_ALPHA_CTRL__Embedded 0x0 +#define BV_PXP_AS_CTRL_ALPHA_CTRL__Override 0x1 +#define BV_PXP_AS_CTRL_ALPHA_CTRL__Multiply 0x2 +#define BV_PXP_AS_CTRL_ALPHA_CTRL__ROPs 0x3 +#define BM_PXP_AS_CTRL_RSVD0 0x00000001 +#define BF_PXP_AS_CTRL_RSVD0(v) \ + (((v) << 0) & BM_PXP_AS_CTRL_RSVD0) + +#define HW_PXP_AS_BUF (0x00000160) + +#define BP_PXP_AS_BUF_ADDR 0 +#define BM_PXP_AS_BUF_ADDR 0xFFFFFFFF +#define BF_PXP_AS_BUF_ADDR(v) (v) + +#define HW_PXP_AS_PITCH (0x00000170) + +#define BP_PXP_AS_PITCH_RSVD 16 +#define BM_PXP_AS_PITCH_RSVD 0xFFFF0000 +#define BF_PXP_AS_PITCH_RSVD(v) \ + (((v) << 16) & BM_PXP_AS_PITCH_RSVD) +#define BP_PXP_AS_PITCH_PITCH 0 +#define BM_PXP_AS_PITCH_PITCH 0x0000FFFF +#define BF_PXP_AS_PITCH_PITCH(v) \ + (((v) << 0) & BM_PXP_AS_PITCH_PITCH) + +#define HW_PXP_AS_CLRKEYLOW_0 (0x00000180) + +#define BP_PXP_AS_CLRKEYLOW_0_RSVD1 24 +#define BM_PXP_AS_CLRKEYLOW_0_RSVD1 0xFF000000 +#define BF_PXP_AS_CLRKEYLOW_0_RSVD1(v) \ + (((v) << 24) & BM_PXP_AS_CLRKEYLOW_0_RSVD1) +#define BP_PXP_AS_CLRKEYLOW_0_PIXEL 0 +#define BM_PXP_AS_CLRKEYLOW_0_PIXEL 0x00FFFFFF +#define BF_PXP_AS_CLRKEYLOW_0_PIXEL(v) \ + (((v) << 0) & BM_PXP_AS_CLRKEYLOW_0_PIXEL) + +#define HW_PXP_AS_CLRKEYHIGH_0 (0x00000190) + +#define BP_PXP_AS_CLRKEYHIGH_0_RSVD1 24 +#define BM_PXP_AS_CLRKEYHIGH_0_RSVD1 0xFF000000 +#define BF_PXP_AS_CLRKEYHIGH_0_RSVD1(v) \ + (((v) << 24) & BM_PXP_AS_CLRKEYHIGH_0_RSVD1) +#define BP_PXP_AS_CLRKEYHIGH_0_PIXEL 0 +#define BM_PXP_AS_CLRKEYHIGH_0_PIXEL 0x00FFFFFF +#define BF_PXP_AS_CLRKEYHIGH_0_PIXEL(v) \ + (((v) << 0) & BM_PXP_AS_CLRKEYHIGH_0_PIXEL) + +#define HW_PXP_CSC1_COEF0 (0x000001a0) + +#define BM_PXP_CSC1_COEF0_YCBCR_MODE 0x80000000 +#define BF_PXP_CSC1_COEF0_YCBCR_MODE(v) \ + (((v) << 31) & BM_PXP_CSC1_COEF0_YCBCR_MODE) +#define BM_PXP_CSC1_COEF0_BYPASS 0x40000000 +#define BF_PXP_CSC1_COEF0_BYPASS(v) \ + (((v) << 30) & BM_PXP_CSC1_COEF0_BYPASS) +#define BM_PXP_CSC1_COEF0_RSVD1 0x20000000 +#define BF_PXP_CSC1_COEF0_RSVD1(v) \ + (((v) << 29) & BM_PXP_CSC1_COEF0_RSVD1) +#define BP_PXP_CSC1_COEF0_C0 18 +#define BM_PXP_CSC1_COEF0_C0 0x1FFC0000 +#define BF_PXP_CSC1_COEF0_C0(v) \ + (((v) << 18) & BM_PXP_CSC1_COEF0_C0) +#define BP_PXP_CSC1_COEF0_UV_OFFSET 9 +#define BM_PXP_CSC1_COEF0_UV_OFFSET 0x0003FE00 +#define BF_PXP_CSC1_COEF0_UV_OFFSET(v) \ + (((v) << 9) & BM_PXP_CSC1_COEF0_UV_OFFSET) +#define BP_PXP_CSC1_COEF0_Y_OFFSET 0 +#define BM_PXP_CSC1_COEF0_Y_OFFSET 0x000001FF +#define BF_PXP_CSC1_COEF0_Y_OFFSET(v) \ + (((v) << 0) & BM_PXP_CSC1_COEF0_Y_OFFSET) + +#define HW_PXP_CSC1_COEF1 (0x000001b0) + +#define BP_PXP_CSC1_COEF1_RSVD1 27 +#define BM_PXP_CSC1_COEF1_RSVD1 0xF8000000 +#define BF_PXP_CSC1_COEF1_RSVD1(v) \ + (((v) << 27) & BM_PXP_CSC1_COEF1_RSVD1) +#define BP_PXP_CSC1_COEF1_C1 16 +#define BM_PXP_CSC1_COEF1_C1 0x07FF0000 +#define BF_PXP_CSC1_COEF1_C1(v) \ + (((v) << 16) & BM_PXP_CSC1_COEF1_C1) +#define BP_PXP_CSC1_COEF1_RSVD0 11 +#define BM_PXP_CSC1_COEF1_RSVD0 0x0000F800 +#define BF_PXP_CSC1_COEF1_RSVD0(v) \ + (((v) << 11) & BM_PXP_CSC1_COEF1_RSVD0) +#define BP_PXP_CSC1_COEF1_C4 0 +#define BM_PXP_CSC1_COEF1_C4 0x000007FF +#define BF_PXP_CSC1_COEF1_C4(v) \ + (((v) << 0) & BM_PXP_CSC1_COEF1_C4) + +#define HW_PXP_CSC1_COEF2 (0x000001c0) + +#define BP_PXP_CSC1_COEF2_RSVD1 27 +#define BM_PXP_CSC1_COEF2_RSVD1 0xF8000000 +#define BF_PXP_CSC1_COEF2_RSVD1(v) \ + (((v) << 27) & BM_PXP_CSC1_COEF2_RSVD1) +#define BP_PXP_CSC1_COEF2_C2 16 +#define BM_PXP_CSC1_COEF2_C2 0x07FF0000 +#define BF_PXP_CSC1_COEF2_C2(v) \ + (((v) << 16) & BM_PXP_CSC1_COEF2_C2) +#define BP_PXP_CSC1_COEF2_RSVD0 11 +#define BM_PXP_CSC1_COEF2_RSVD0 0x0000F800 +#define BF_PXP_CSC1_COEF2_RSVD0(v) \ + (((v) << 11) & BM_PXP_CSC1_COEF2_RSVD0) +#define BP_PXP_CSC1_COEF2_C3 0 +#define BM_PXP_CSC1_COEF2_C3 0x000007FF +#define BF_PXP_CSC1_COEF2_C3(v) \ + (((v) << 0) & BM_PXP_CSC1_COEF2_C3) + +#define HW_PXP_CSC2_CTRL (0x000001d0) + +#define BP_PXP_CSC2_CTRL_RSVD 3 +#define BM_PXP_CSC2_CTRL_RSVD 0xFFFFFFF8 +#define BF_PXP_CSC2_CTRL_RSVD(v) \ + (((v) << 3) & BM_PXP_CSC2_CTRL_RSVD) +#define BP_PXP_CSC2_CTRL_CSC_MODE 1 +#define BM_PXP_CSC2_CTRL_CSC_MODE 0x00000006 +#define BF_PXP_CSC2_CTRL_CSC_MODE(v) \ + (((v) << 1) & BM_PXP_CSC2_CTRL_CSC_MODE) +#define BV_PXP_CSC2_CTRL_CSC_MODE__YUV2RGB 0x0 +#define BV_PXP_CSC2_CTRL_CSC_MODE__YCbCr2RGB 0x1 +#define BV_PXP_CSC2_CTRL_CSC_MODE__RGB2YUV 0x2 +#define BV_PXP_CSC2_CTRL_CSC_MODE__RGB2YCbCr 0x3 +#define BM_PXP_CSC2_CTRL_BYPASS 0x00000001 +#define BF_PXP_CSC2_CTRL_BYPASS(v) \ + (((v) << 0) & BM_PXP_CSC2_CTRL_BYPASS) + +#define HW_PXP_CSC2_COEF0 (0x000001e0) + +#define BP_PXP_CSC2_COEF0_RSVD1 27 +#define BM_PXP_CSC2_COEF0_RSVD1 0xF8000000 +#define BF_PXP_CSC2_COEF0_RSVD1(v) \ + (((v) << 27) & BM_PXP_CSC2_COEF0_RSVD1) +#define BP_PXP_CSC2_COEF0_A2 16 +#define BM_PXP_CSC2_COEF0_A2 0x07FF0000 +#define BF_PXP_CSC2_COEF0_A2(v) \ + (((v) << 16) & BM_PXP_CSC2_COEF0_A2) +#define BP_PXP_CSC2_COEF0_RSVD0 11 +#define BM_PXP_CSC2_COEF0_RSVD0 0x0000F800 +#define BF_PXP_CSC2_COEF0_RSVD0(v) \ + (((v) << 11) & BM_PXP_CSC2_COEF0_RSVD0) +#define BP_PXP_CSC2_COEF0_A1 0 +#define BM_PXP_CSC2_COEF0_A1 0x000007FF +#define BF_PXP_CSC2_COEF0_A1(v) \ + (((v) << 0) & BM_PXP_CSC2_COEF0_A1) + +#define HW_PXP_CSC2_COEF1 (0x000001f0) + +#define BP_PXP_CSC2_COEF1_RSVD1 27 +#define BM_PXP_CSC2_COEF1_RSVD1 0xF8000000 +#define BF_PXP_CSC2_COEF1_RSVD1(v) \ + (((v) << 27) & BM_PXP_CSC2_COEF1_RSVD1) +#define BP_PXP_CSC2_COEF1_B1 16 +#define BM_PXP_CSC2_COEF1_B1 0x07FF0000 +#define BF_PXP_CSC2_COEF1_B1(v) \ + (((v) << 16) & BM_PXP_CSC2_COEF1_B1) +#define BP_PXP_CSC2_COEF1_RSVD0 11 +#define BM_PXP_CSC2_COEF1_RSVD0 0x0000F800 +#define BF_PXP_CSC2_COEF1_RSVD0(v) \ + (((v) << 11) & BM_PXP_CSC2_COEF1_RSVD0) +#define BP_PXP_CSC2_COEF1_A3 0 +#define BM_PXP_CSC2_COEF1_A3 0x000007FF +#define BF_PXP_CSC2_COEF1_A3(v) \ + (((v) << 0) & BM_PXP_CSC2_COEF1_A3) + +#define HW_PXP_CSC2_COEF2 (0x00000200) + +#define BP_PXP_CSC2_COEF2_RSVD1 27 +#define BM_PXP_CSC2_COEF2_RSVD1 0xF8000000 +#define BF_PXP_CSC2_COEF2_RSVD1(v) \ + (((v) << 27) & BM_PXP_CSC2_COEF2_RSVD1) +#define BP_PXP_CSC2_COEF2_B3 16 +#define BM_PXP_CSC2_COEF2_B3 0x07FF0000 +#define BF_PXP_CSC2_COEF2_B3(v) \ + (((v) << 16) & BM_PXP_CSC2_COEF2_B3) +#define BP_PXP_CSC2_COEF2_RSVD0 11 +#define BM_PXP_CSC2_COEF2_RSVD0 0x0000F800 +#define BF_PXP_CSC2_COEF2_RSVD0(v) \ + (((v) << 11) & BM_PXP_CSC2_COEF2_RSVD0) +#define BP_PXP_CSC2_COEF2_B2 0 +#define BM_PXP_CSC2_COEF2_B2 0x000007FF +#define BF_PXP_CSC2_COEF2_B2(v) \ + (((v) << 0) & BM_PXP_CSC2_COEF2_B2) + +#define HW_PXP_CSC2_COEF3 (0x00000210) + +#define BP_PXP_CSC2_COEF3_RSVD1 27 +#define BM_PXP_CSC2_COEF3_RSVD1 0xF8000000 +#define BF_PXP_CSC2_COEF3_RSVD1(v) \ + (((v) << 27) & BM_PXP_CSC2_COEF3_RSVD1) +#define BP_PXP_CSC2_COEF3_C2 16 +#define BM_PXP_CSC2_COEF3_C2 0x07FF0000 +#define BF_PXP_CSC2_COEF3_C2(v) \ + (((v) << 16) & BM_PXP_CSC2_COEF3_C2) +#define BP_PXP_CSC2_COEF3_RSVD0 11 +#define BM_PXP_CSC2_COEF3_RSVD0 0x0000F800 +#define BF_PXP_CSC2_COEF3_RSVD0(v) \ + (((v) << 11) & BM_PXP_CSC2_COEF3_RSVD0) +#define BP_PXP_CSC2_COEF3_C1 0 +#define BM_PXP_CSC2_COEF3_C1 0x000007FF +#define BF_PXP_CSC2_COEF3_C1(v) \ + (((v) << 0) & BM_PXP_CSC2_COEF3_C1) + +#define HW_PXP_CSC2_COEF4 (0x00000220) + +#define BP_PXP_CSC2_COEF4_RSVD1 25 +#define BM_PXP_CSC2_COEF4_RSVD1 0xFE000000 +#define BF_PXP_CSC2_COEF4_RSVD1(v) \ + (((v) << 25) & BM_PXP_CSC2_COEF4_RSVD1) +#define BP_PXP_CSC2_COEF4_D1 16 +#define BM_PXP_CSC2_COEF4_D1 0x01FF0000 +#define BF_PXP_CSC2_COEF4_D1(v) \ + (((v) << 16) & BM_PXP_CSC2_COEF4_D1) +#define BP_PXP_CSC2_COEF4_RSVD0 11 +#define BM_PXP_CSC2_COEF4_RSVD0 0x0000F800 +#define BF_PXP_CSC2_COEF4_RSVD0(v) \ + (((v) << 11) & BM_PXP_CSC2_COEF4_RSVD0) +#define BP_PXP_CSC2_COEF4_C3 0 +#define BM_PXP_CSC2_COEF4_C3 0x000007FF +#define BF_PXP_CSC2_COEF4_C3(v) \ + (((v) << 0) & BM_PXP_CSC2_COEF4_C3) + +#define HW_PXP_CSC2_COEF5 (0x00000230) + +#define BP_PXP_CSC2_COEF5_RSVD1 25 +#define BM_PXP_CSC2_COEF5_RSVD1 0xFE000000 +#define BF_PXP_CSC2_COEF5_RSVD1(v) \ + (((v) << 25) & BM_PXP_CSC2_COEF5_RSVD1) +#define BP_PXP_CSC2_COEF5_D3 16 +#define BM_PXP_CSC2_COEF5_D3 0x01FF0000 +#define BF_PXP_CSC2_COEF5_D3(v) \ + (((v) << 16) & BM_PXP_CSC2_COEF5_D3) +#define BP_PXP_CSC2_COEF5_RSVD0 9 +#define BM_PXP_CSC2_COEF5_RSVD0 0x0000FE00 +#define BF_PXP_CSC2_COEF5_RSVD0(v) \ + (((v) << 9) & BM_PXP_CSC2_COEF5_RSVD0) +#define BP_PXP_CSC2_COEF5_D2 0 +#define BM_PXP_CSC2_COEF5_D2 0x000001FF +#define BF_PXP_CSC2_COEF5_D2(v) \ + (((v) << 0) & BM_PXP_CSC2_COEF5_D2) + +#define HW_PXP_LUT_CTRL (0x00000240) + +#define BM_PXP_LUT_CTRL_BYPASS 0x80000000 +#define BF_PXP_LUT_CTRL_BYPASS(v) \ + (((v) << 31) & BM_PXP_LUT_CTRL_BYPASS) +#define BP_PXP_LUT_CTRL_RSVD3 26 +#define BM_PXP_LUT_CTRL_RSVD3 0x7C000000 +#define BF_PXP_LUT_CTRL_RSVD3(v) \ + (((v) << 26) & BM_PXP_LUT_CTRL_RSVD3) +#define BP_PXP_LUT_CTRL_LOOKUP_MODE 24 +#define BM_PXP_LUT_CTRL_LOOKUP_MODE 0x03000000 +#define BF_PXP_LUT_CTRL_LOOKUP_MODE(v) \ + (((v) << 24) & BM_PXP_LUT_CTRL_LOOKUP_MODE) +#define BV_PXP_LUT_CTRL_LOOKUP_MODE__CACHE_RGB565 0x0 +#define BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8 0x1 +#define BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_RGB444 0x2 +#define BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_RGB454 0x3 +#define BP_PXP_LUT_CTRL_RSVD2 18 +#define BM_PXP_LUT_CTRL_RSVD2 0x00FC0000 +#define BF_PXP_LUT_CTRL_RSVD2(v) \ + (((v) << 18) & BM_PXP_LUT_CTRL_RSVD2) +#define BP_PXP_LUT_CTRL_OUT_MODE 16 +#define BM_PXP_LUT_CTRL_OUT_MODE 0x00030000 +#define BF_PXP_LUT_CTRL_OUT_MODE(v) \ + (((v) << 16) & BM_PXP_LUT_CTRL_OUT_MODE) +#define BV_PXP_LUT_CTRL_OUT_MODE__RESERVED 0x0 +#define BV_PXP_LUT_CTRL_OUT_MODE__Y8 0x1 +#define BV_PXP_LUT_CTRL_OUT_MODE__RGBW4444CFA 0x2 +#define BV_PXP_LUT_CTRL_OUT_MODE__RGB888 0x3 +#define BP_PXP_LUT_CTRL_RSVD1 11 +#define BM_PXP_LUT_CTRL_RSVD1 0x0000F800 +#define BF_PXP_LUT_CTRL_RSVD1(v) \ + (((v) << 11) & BM_PXP_LUT_CTRL_RSVD1) +#define BM_PXP_LUT_CTRL_SEL_8KB 0x00000400 +#define BF_PXP_LUT_CTRL_SEL_8KB(v) \ + (((v) << 10) & BM_PXP_LUT_CTRL_SEL_8KB) +#define BM_PXP_LUT_CTRL_LRU_UPD 0x00000200 +#define BF_PXP_LUT_CTRL_LRU_UPD(v) \ + (((v) << 9) & BM_PXP_LUT_CTRL_LRU_UPD) +#define BM_PXP_LUT_CTRL_INVALID 0x00000100 +#define BF_PXP_LUT_CTRL_INVALID(v) \ + (((v) << 8) & BM_PXP_LUT_CTRL_INVALID) +#define BP_PXP_LUT_CTRL_RSVD0 1 +#define BM_PXP_LUT_CTRL_RSVD0 0x000000FE +#define BF_PXP_LUT_CTRL_RSVD0(v) \ + (((v) << 1) & BM_PXP_LUT_CTRL_RSVD0) +#define BM_PXP_LUT_CTRL_DMA_START 0x00000001 +#define BF_PXP_LUT_CTRL_DMA_START(v) \ + (((v) << 0) & BM_PXP_LUT_CTRL_DMA_START) + +#define HW_PXP_LUT_ADDR (0x00000250) + +#define BM_PXP_LUT_ADDR_RSVD2 0x80000000 +#define BF_PXP_LUT_ADDR_RSVD2(v) \ + (((v) << 31) & BM_PXP_LUT_ADDR_RSVD2) +#define BP_PXP_LUT_ADDR_NUM_BYTES 16 +#define BM_PXP_LUT_ADDR_NUM_BYTES 0x7FFF0000 +#define BF_PXP_LUT_ADDR_NUM_BYTES(v) \ + (((v) << 16) & BM_PXP_LUT_ADDR_NUM_BYTES) +#define BP_PXP_LUT_ADDR_RSVD1 14 +#define BM_PXP_LUT_ADDR_RSVD1 0x0000C000 +#define BF_PXP_LUT_ADDR_RSVD1(v) \ + (((v) << 14) & BM_PXP_LUT_ADDR_RSVD1) +#define BP_PXP_LUT_ADDR_ADDR 0 +#define BM_PXP_LUT_ADDR_ADDR 0x00003FFF +#define BF_PXP_LUT_ADDR_ADDR(v) \ + (((v) << 0) & BM_PXP_LUT_ADDR_ADDR) + +#define HW_PXP_LUT_DATA (0x00000260) + +#define BP_PXP_LUT_DATA_DATA 0 +#define BM_PXP_LUT_DATA_DATA 0xFFFFFFFF +#define BF_PXP_LUT_DATA_DATA(v) (v) + +#define HW_PXP_LUT_EXTMEM (0x00000270) + +#define BP_PXP_LUT_EXTMEM_ADDR 0 +#define BM_PXP_LUT_EXTMEM_ADDR 0xFFFFFFFF +#define BF_PXP_LUT_EXTMEM_ADDR(v) (v) + +#define HW_PXP_CFA (0x00000280) + +#define BP_PXP_CFA_DATA 0 +#define BM_PXP_CFA_DATA 0xFFFFFFFF +#define BF_PXP_CFA_DATA(v) (v) + +#define HW_PXP_ALPHA_A_CTRL (0x00000290) + +#define BP_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA 24 +#define BM_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA 0xFF000000 +#define BF_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA(v) \ + (((v) << 24) & BM_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA) +#define BP_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA 16 +#define BM_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA 0x00FF0000 +#define BF_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA(v) \ + (((v) << 16) & BM_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA) +#define BP_PXP_ALPHA_A_CTRL_RSVD0 14 +#define BM_PXP_ALPHA_A_CTRL_RSVD0 0x0000C000 +#define BF_PXP_ALPHA_A_CTRL_RSVD0(v) \ + (((v) << 14) & BM_PXP_ALPHA_A_CTRL_RSVD0) +#define BM_PXP_ALPHA_A_CTRL_S1_COLOR_MODE 0x00002000 +#define BF_PXP_ALPHA_A_CTRL_S1_COLOR_MODE(v) \ + (((v) << 13) & BM_PXP_ALPHA_A_CTRL_S1_COLOR_MODE) +#define BV_PXP_ALPHA_A_CTRL_S1_COLOR_MODE__0 0x0 +#define BV_PXP_ALPHA_A_CTRL_S1_COLOR_MODE__1 0x1 +#define BM_PXP_ALPHA_A_CTRL_S1_ALPHA_MODE 0x00001000 +#define BF_PXP_ALPHA_A_CTRL_S1_ALPHA_MODE(v) \ + (((v) << 12) & BM_PXP_ALPHA_A_CTRL_S1_ALPHA_MODE) +#define BV_PXP_ALPHA_A_CTRL_S1_ALPHA_MODE__0 0x0 +#define BV_PXP_ALPHA_A_CTRL_S1_ALPHA_MODE__1 0x1 +#define BP_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE 10 +#define BM_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE 0x00000C00 +#define BF_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE(v) \ + (((v) << 10) & BM_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE) +#define BV_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE__0 0x0 +#define BV_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE__1 0x0 +#define BV_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE__2 0x0 +#define BV_PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE__3 0x0 +#define BP_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE 8 +#define BM_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE 0x00000300 +#define BF_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE(v) \ + (((v) << 8) & BM_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE) +#define BV_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE__0 0x0 +#define BV_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE__1 0x1 +#define BV_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE__2 0x2 +#define BV_PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE__3 0x3 +#define BM_PXP_ALPHA_A_CTRL_RSVD1 0x00000080 +#define BF_PXP_ALPHA_A_CTRL_RSVD1(v) \ + (((v) << 7) & BM_PXP_ALPHA_A_CTRL_RSVD1) +#define BM_PXP_ALPHA_A_CTRL_S0_COLOR_MODE 0x00000040 +#define BF_PXP_ALPHA_A_CTRL_S0_COLOR_MODE(v) \ + (((v) << 6) & BM_PXP_ALPHA_A_CTRL_S0_COLOR_MODE) +#define BV_PXP_ALPHA_A_CTRL_S0_COLOR_MODE__0 0x0 +#define BV_PXP_ALPHA_A_CTRL_S0_COLOR_MODE__1 0x1 +#define BM_PXP_ALPHA_A_CTRL_S0_ALPHA_MODE 0x00000020 +#define BF_PXP_ALPHA_A_CTRL_S0_ALPHA_MODE(v) \ + (((v) << 5) & BM_PXP_ALPHA_A_CTRL_S0_ALPHA_MODE) +#define BV_PXP_ALPHA_A_CTRL_S0_ALPHA_MODE__0 0x0 +#define BV_PXP_ALPHA_A_CTRL_S0_ALPHA_MODE__1 0x1 +#define BP_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE 3 +#define BM_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE 0x00000018 +#define BF_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE(v) \ + (((v) << 3) & BM_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE) +#define BV_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE__0 0x0 +#define BV_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE__1 0x1 +#define BV_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE__2 0x2 +#define BV_PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE__3 0x3 +#define BP_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE 1 +#define BM_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE 0x00000006 +#define BF_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE(v) \ + (((v) << 1) & BM_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE) +#define BV_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE__0 0x0 +#define BV_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE__1 0x1 +#define BV_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE__2 0x2 +#define BV_PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE__3 0x3 +#define BM_PXP_ALPHA_A_CTRL_POTER_DUFF_ENABLE 0x00000001 +#define BF_PXP_ALPHA_A_CTRL_POTER_DUFF_ENABLE(v) \ + (((v) << 0) & BM_PXP_ALPHA_A_CTRL_POTER_DUFF_ENABLE) +#define BV_PXP_ALPHA_A_CTRL_POTER_DUFF_ENABLE__0 0x0 +#define BV_PXP_ALPHA_A_CTRL_POTER_DUFF_ENABLE__1 0x1 + +#define HW_PXP_ALPHA_B_CTRL (0x000002a0) + +#define BP_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA 24 +#define BM_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA 0xFF000000 +#define BF_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA(v) \ + (((v) << 24) & BM_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA) +#define BP_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA 16 +#define BM_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA 0x00FF0000 +#define BF_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA(v) \ + (((v) << 16) & BM_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA) +#define BP_PXP_ALPHA_B_CTRL_RSVD0 14 +#define BM_PXP_ALPHA_B_CTRL_RSVD0 0x0000C000 +#define BF_PXP_ALPHA_B_CTRL_RSVD0(v) \ + (((v) << 14) & BM_PXP_ALPHA_B_CTRL_RSVD0) +#define BM_PXP_ALPHA_B_CTRL_S1_COLOR_MODE 0x00002000 +#define BF_PXP_ALPHA_B_CTRL_S1_COLOR_MODE(v) \ + (((v) << 13) & BM_PXP_ALPHA_B_CTRL_S1_COLOR_MODE) +#define BV_PXP_ALPHA_B_CTRL_S1_COLOR_MODE__0 0x0 +#define BV_PXP_ALPHA_B_CTRL_S1_COLOR_MODE__1 0x1 +#define BM_PXP_ALPHA_B_CTRL_S1_ALPHA_MODE 0x00001000 +#define BF_PXP_ALPHA_B_CTRL_S1_ALPHA_MODE(v) \ + (((v) << 12) & BM_PXP_ALPHA_B_CTRL_S1_ALPHA_MODE) +#define BV_PXP_ALPHA_B_CTRL_S1_ALPHA_MODE__0 0x0 +#define BV_PXP_ALPHA_B_CTRL_S1_ALPHA_MODE__1 0x1 +#define BP_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE 10 +#define BM_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE 0x00000C00 +#define BF_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE(v) \ + (((v) << 10) & BM_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE) +#define BV_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE__0 0x0 +#define BV_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE__1 0x1 +#define BV_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE__2 0x2 +#define BV_PXP_ALPHA_B_CTRL_S1_GLOBAL_ALPHA_MODE__3 0x3 +#define BP_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE 8 +#define BM_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE 0x00000300 +#define BF_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE(v) \ + (((v) << 8) & BM_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE) +#define BV_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE__0 0x0 +#define BV_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE__1 0x1 +#define BV_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE__2 0x2 +#define BV_PXP_ALPHA_B_CTRL_S1_S0_FACTOR_MODE__3 0x3 +#define BM_PXP_ALPHA_B_CTRL_RSVD1 0x00000080 +#define BF_PXP_ALPHA_B_CTRL_RSVD1(v) \ + (((v) << 7) & BM_PXP_ALPHA_B_CTRL_RSVD1) +#define BM_PXP_ALPHA_B_CTRL_S0_COLOR_MODE 0x00000040 +#define BF_PXP_ALPHA_B_CTRL_S0_COLOR_MODE(v) \ + (((v) << 6) & BM_PXP_ALPHA_B_CTRL_S0_COLOR_MODE) +#define BV_PXP_ALPHA_B_CTRL_S0_COLOR_MODE__0 0x0 +#define BV_PXP_ALPHA_B_CTRL_S0_COLOR_MODE__1 0x1 +#define BM_PXP_ALPHA_B_CTRL_S0_ALPHA_MODE 0x00000020 +#define BF_PXP_ALPHA_B_CTRL_S0_ALPHA_MODE(v) \ + (((v) << 5) & BM_PXP_ALPHA_B_CTRL_S0_ALPHA_MODE) +#define BV_PXP_ALPHA_B_CTRL_S0_ALPHA_MODE__0 0x0 +#define BV_PXP_ALPHA_B_CTRL_S0_ALPHA_MODE__1 0x1 +#define BP_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE 3 +#define BM_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE 0x00000018 +#define BF_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE(v) \ + (((v) << 3) & BM_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE) +#define BV_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE__0 0x0 +#define BV_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE__1 0x1 +#define BV_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE__2 0x2 +#define BV_PXP_ALPHA_B_CTRL_S0_GLOBAL_ALPHA_MODE__3 0x3 +#define BP_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE 1 +#define BM_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE 0x00000006 +#define BF_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE(v) \ + (((v) << 1) & BM_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE) +#define BV_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE__0 0x0 +#define BV_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE__1 0x1 +#define BV_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE__2 0x2 +#define BV_PXP_ALPHA_B_CTRL_S0_S1_FACTOR_MODE__3 0x3 +#define BM_PXP_ALPHA_B_CTRL_POTER_DUFF_ENABLE 0x00000001 +#define BF_PXP_ALPHA_B_CTRL_POTER_DUFF_ENABLE(v) \ + (((v) << 0) & BM_PXP_ALPHA_B_CTRL_POTER_DUFF_ENABLE) +#define BV_PXP_ALPHA_B_CTRL_POTER_DUFF_ENABLE__0 0x0 +#define BV_PXP_ALPHA_B_CTRL_POTER_DUFF_ENABLE__1 0x1 + +#define HW_PXP_ALPHA_B_CTRL_1 (0x000002b0) + +#define BP_PXP_ALPHA_B_CTRL_1_RSVD0 8 +#define BM_PXP_ALPHA_B_CTRL_1_RSVD0 0xFFFFFF00 +#define BF_PXP_ALPHA_B_CTRL_1_RSVD0(v) \ + (((v) << 8) & BM_PXP_ALPHA_B_CTRL_1_RSVD0) +#define BP_PXP_ALPHA_B_CTRL_1_ROP 4 +#define BM_PXP_ALPHA_B_CTRL_1_ROP 0x000000F0 +#define BF_PXP_ALPHA_B_CTRL_1_ROP(v) \ + (((v) << 4) & BM_PXP_ALPHA_B_CTRL_1_ROP) +#define BV_PXP_ALPHA_B_CTRL_1_ROP__MASKAS 0x0 +#define BV_PXP_ALPHA_B_CTRL_1_ROP__MASKNOTAS 0x1 +#define BV_PXP_ALPHA_B_CTRL_1_ROP__MASKASNOT 0x2 +#define BV_PXP_ALPHA_B_CTRL_1_ROP__MERGEAS 0x3 +#define BV_PXP_ALPHA_B_CTRL_1_ROP__MERGENOTAS 0x4 +#define BV_PXP_ALPHA_B_CTRL_1_ROP__MERGEASNOT 0x5 +#define BV_PXP_ALPHA_B_CTRL_1_ROP__NOTCOPYAS 0x6 +#define BV_PXP_ALPHA_B_CTRL_1_ROP__NOT 0x7 +#define BV_PXP_ALPHA_B_CTRL_1_ROP__NOTMASKAS 0x8 +#define BV_PXP_ALPHA_B_CTRL_1_ROP__NOTMERGEAS 0x9 +#define BV_PXP_ALPHA_B_CTRL_1_ROP__XORAS 0xA +#define BV_PXP_ALPHA_B_CTRL_1_ROP__NOTXORAS 0xB +#define BP_PXP_ALPHA_B_CTRL_1_RSVD1 2 +#define BM_PXP_ALPHA_B_CTRL_1_RSVD1 0x0000000C +#define BF_PXP_ALPHA_B_CTRL_1_RSVD1(v) \ + (((v) << 2) & BM_PXP_ALPHA_B_CTRL_1_RSVD1) +#define BM_PXP_ALPHA_B_CTRL_1_OL_CLRKEY_ENABLE 0x00000002 +#define BF_PXP_ALPHA_B_CTRL_1_OL_CLRKEY_ENABLE(v) \ + (((v) << 1) & BM_PXP_ALPHA_B_CTRL_1_OL_CLRKEY_ENABLE) +#define BM_PXP_ALPHA_B_CTRL_1_ROP_ENABLE 0x00000001 +#define BF_PXP_ALPHA_B_CTRL_1_ROP_ENABLE(v) \ + (((v) << 0) & BM_PXP_ALPHA_B_CTRL_1_ROP_ENABLE) + +#define HW_PXP_PS_BACKGROUND_1 (0x000002c0) + +#define BP_PXP_PS_BACKGROUND_1_RSVD 24 +#define BM_PXP_PS_BACKGROUND_1_RSVD 0xFF000000 +#define BF_PXP_PS_BACKGROUND_1_RSVD(v) \ + (((v) << 24) & BM_PXP_PS_BACKGROUND_1_RSVD) +#define BP_PXP_PS_BACKGROUND_1_COLOR 0 +#define BM_PXP_PS_BACKGROUND_1_COLOR 0x00FFFFFF +#define BF_PXP_PS_BACKGROUND_1_COLOR(v) \ + (((v) << 0) & BM_PXP_PS_BACKGROUND_1_COLOR) + +#define HW_PXP_PS_CLRKEYLOW_1 (0x000002d0) + +#define BP_PXP_PS_CLRKEYLOW_1_RSVD1 24 +#define BM_PXP_PS_CLRKEYLOW_1_RSVD1 0xFF000000 +#define BF_PXP_PS_CLRKEYLOW_1_RSVD1(v) \ + (((v) << 24) & BM_PXP_PS_CLRKEYLOW_1_RSVD1) +#define BP_PXP_PS_CLRKEYLOW_1_PIXEL 0 +#define BM_PXP_PS_CLRKEYLOW_1_PIXEL 0x00FFFFFF +#define BF_PXP_PS_CLRKEYLOW_1_PIXEL(v) \ + (((v) << 0) & BM_PXP_PS_CLRKEYLOW_1_PIXEL) + +#define HW_PXP_PS_CLRKEYHIGH_1 (0x000002e0) + +#define BP_PXP_PS_CLRKEYHIGH_1_RSVD1 24 +#define BM_PXP_PS_CLRKEYHIGH_1_RSVD1 0xFF000000 +#define BF_PXP_PS_CLRKEYHIGH_1_RSVD1(v) \ + (((v) << 24) & BM_PXP_PS_CLRKEYHIGH_1_RSVD1) +#define BP_PXP_PS_CLRKEYHIGH_1_PIXEL 0 +#define BM_PXP_PS_CLRKEYHIGH_1_PIXEL 0x00FFFFFF +#define BF_PXP_PS_CLRKEYHIGH_1_PIXEL(v) \ + (((v) << 0) & BM_PXP_PS_CLRKEYHIGH_1_PIXEL) + +#define HW_PXP_AS_CLRKEYLOW_1 (0x000002f0) + +#define BP_PXP_AS_CLRKEYLOW_1_RSVD1 24 +#define BM_PXP_AS_CLRKEYLOW_1_RSVD1 0xFF000000 +#define BF_PXP_AS_CLRKEYLOW_1_RSVD1(v) \ + (((v) << 24) & BM_PXP_AS_CLRKEYLOW_1_RSVD1) +#define BP_PXP_AS_CLRKEYLOW_1_PIXEL 0 +#define BM_PXP_AS_CLRKEYLOW_1_PIXEL 0x00FFFFFF +#define BF_PXP_AS_CLRKEYLOW_1_PIXEL(v) \ + (((v) << 0) & BM_PXP_AS_CLRKEYLOW_1_PIXEL) + +#define HW_PXP_AS_CLRKEYHIGH_1 (0x00000300) + +#define BP_PXP_AS_CLRKEYHIGH_1_RSVD1 24 +#define BM_PXP_AS_CLRKEYHIGH_1_RSVD1 0xFF000000 +#define BF_PXP_AS_CLRKEYHIGH_1_RSVD1(v) \ + (((v) << 24) & BM_PXP_AS_CLRKEYHIGH_1_RSVD1) +#define BP_PXP_AS_CLRKEYHIGH_1_PIXEL 0 +#define BM_PXP_AS_CLRKEYHIGH_1_PIXEL 0x00FFFFFF +#define BF_PXP_AS_CLRKEYHIGH_1_PIXEL(v) \ + (((v) << 0) & BM_PXP_AS_CLRKEYHIGH_1_PIXEL) + +#define HW_PXP_CTRL2 (0x00000310) +#define HW_PXP_CTRL2_SET (0x00000314) +#define HW_PXP_CTRL2_CLR (0x00000318) +#define HW_PXP_CTRL2_TOG (0x0000031c) + +#define BP_PXP_CTRL2_RSVD3 28 +#define BM_PXP_CTRL2_RSVD3 0xF0000000 +#define BF_PXP_CTRL2_RSVD3(v) \ + (((v) << 28) & BM_PXP_CTRL2_RSVD3) +#define BM_PXP_CTRL2_ENABLE_ROTATE1 0x08000000 +#define BF_PXP_CTRL2_ENABLE_ROTATE1(v) \ + (((v) << 27) & BM_PXP_CTRL2_ENABLE_ROTATE1) +#define BM_PXP_CTRL2_ENABLE_ROTATE0 0x04000000 +#define BF_PXP_CTRL2_ENABLE_ROTATE0(v) \ + (((v) << 26) & BM_PXP_CTRL2_ENABLE_ROTATE0) +#define BM_PXP_CTRL2_ENABLE_LUT 0x02000000 +#define BF_PXP_CTRL2_ENABLE_LUT(v) \ + (((v) << 25) & BM_PXP_CTRL2_ENABLE_LUT) +#define BM_PXP_CTRL2_ENABLE_CSC2 0x01000000 +#define BF_PXP_CTRL2_ENABLE_CSC2(v) \ + (((v) << 24) & BM_PXP_CTRL2_ENABLE_CSC2) +#define BM_PXP_CTRL2_BLOCK_SIZE 0x00800000 +#define BF_PXP_CTRL2_BLOCK_SIZE(v) \ + (((v) << 23) & BM_PXP_CTRL2_BLOCK_SIZE) +#define BV_PXP_CTRL2_BLOCK_SIZE__8X8 0x0 +#define BV_PXP_CTRL2_BLOCK_SIZE__16X16 0x1 +#define BM_PXP_CTRL2_RSVD2 0x00400000 +#define BF_PXP_CTRL2_RSVD2(v) \ + (((v) << 22) & BM_PXP_CTRL2_RSVD2) +#define BM_PXP_CTRL2_ENABLE_ALPHA_B 0x00200000 +#define BF_PXP_CTRL2_ENABLE_ALPHA_B(v) \ + (((v) << 21) & BM_PXP_CTRL2_ENABLE_ALPHA_B) +#define BM_PXP_CTRL2_ENABLE_INPUT_FETCH_STORE 0x00100000 +#define BF_PXP_CTRL2_ENABLE_INPUT_FETCH_STORE(v) \ + (((v) << 20) & BM_PXP_CTRL2_ENABLE_INPUT_FETCH_STORE) +#define BM_PXP_CTRL2_ENABLE_WFE_B 0x00080000 +#define BF_PXP_CTRL2_ENABLE_WFE_B(v) \ + (((v) << 19) & BM_PXP_CTRL2_ENABLE_WFE_B) +#define BM_PXP_CTRL2_ENABLE_WFE_A 0x00040000 +#define BF_PXP_CTRL2_ENABLE_WFE_A(v) \ + (((v) << 18) & BM_PXP_CTRL2_ENABLE_WFE_A) +#define BM_PXP_CTRL2_ENABLE_DITHER 0x00020000 +#define BF_PXP_CTRL2_ENABLE_DITHER(v) \ + (((v) << 17) & BM_PXP_CTRL2_ENABLE_DITHER) +#define BM_PXP_CTRL2_RSVD1 0x00010000 +#define BF_PXP_CTRL2_RSVD1(v) \ + (((v) << 16) & BM_PXP_CTRL2_RSVD1) +#define BM_PXP_CTRL2_VFLIP1 0x00008000 +#define BF_PXP_CTRL2_VFLIP1(v) \ + (((v) << 15) & BM_PXP_CTRL2_VFLIP1) +#define BM_PXP_CTRL2_HFLIP1 0x00004000 +#define BF_PXP_CTRL2_HFLIP1(v) \ + (((v) << 14) & BM_PXP_CTRL2_HFLIP1) +#define BP_PXP_CTRL2_ROTATE1 12 +#define BM_PXP_CTRL2_ROTATE1 0x00003000 +#define BF_PXP_CTRL2_ROTATE1(v) \ + (((v) << 12) & BM_PXP_CTRL2_ROTATE1) +#define BV_PXP_CTRL2_ROTATE1__ROT_0 0x0 +#define BV_PXP_CTRL2_ROTATE1__ROT_90 0x1 +#define BV_PXP_CTRL2_ROTATE1__ROT_180 0x2 +#define BV_PXP_CTRL2_ROTATE1__ROT_270 0x3 +#define BM_PXP_CTRL2_VFLIP0 0x00000800 +#define BF_PXP_CTRL2_VFLIP0(v) \ + (((v) << 11) & BM_PXP_CTRL2_VFLIP0) +#define BM_PXP_CTRL2_HFLIP0 0x00000400 +#define BF_PXP_CTRL2_HFLIP0(v) \ + (((v) << 10) & BM_PXP_CTRL2_HFLIP0) +#define BP_PXP_CTRL2_ROTATE0 8 +#define BM_PXP_CTRL2_ROTATE0 0x00000300 +#define BF_PXP_CTRL2_ROTATE0(v) \ + (((v) << 8) & BM_PXP_CTRL2_ROTATE0) +#define BV_PXP_CTRL2_ROTATE0__ROT_0 0x0 +#define BV_PXP_CTRL2_ROTATE0__ROT_90 0x1 +#define BV_PXP_CTRL2_ROTATE0__ROT_180 0x2 +#define BV_PXP_CTRL2_ROTATE0__ROT_270 0x3 +#define BP_PXP_CTRL2_RSVD0 1 +#define BM_PXP_CTRL2_RSVD0 0x000000FE +#define BF_PXP_CTRL2_RSVD0(v) \ + (((v) << 1) & BM_PXP_CTRL2_RSVD0) +#define BM_PXP_CTRL2_ENABLE 0x00000001 +#define BF_PXP_CTRL2_ENABLE(v) \ + (((v) << 0) & BM_PXP_CTRL2_ENABLE) + +#define HW_PXP_POWER_REG0 (0x00000320) + +#define BP_PXP_POWER_REG0_CTRL 12 +#define BM_PXP_POWER_REG0_CTRL 0xFFFFF000 +#define BF_PXP_POWER_REG0_CTRL(v) \ + (((v) << 12) & BM_PXP_POWER_REG0_CTRL) +#define BP_PXP_POWER_REG0_ROT0_MEM_LP_STATE 9 +#define BM_PXP_POWER_REG0_ROT0_MEM_LP_STATE 0x00000E00 +#define BF_PXP_POWER_REG0_ROT0_MEM_LP_STATE(v) \ + (((v) << 9) & BM_PXP_POWER_REG0_ROT0_MEM_LP_STATE) +#define BV_PXP_POWER_REG0_ROT0_MEM_LP_STATE__NONE 0x0 +#define BV_PXP_POWER_REG0_ROT0_MEM_LP_STATE__LS 0x1 +#define BV_PXP_POWER_REG0_ROT0_MEM_LP_STATE__DS 0x2 +#define BV_PXP_POWER_REG0_ROT0_MEM_LP_STATE__SD 0x4 +#define BP_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN 6 +#define BM_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN 0x000001C0 +#define BF_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN(v) \ + (((v) << 6) & BM_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN) +#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN__NONE 0x0 +#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN__LS 0x1 +#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN__DS 0x2 +#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY1_BANKN__SD 0x4 +#define BP_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN 3 +#define BM_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN 0x00000038 +#define BF_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN(v) \ + (((v) << 3) & BM_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN) +#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN__NONE 0x0 +#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN__LS 0x1 +#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN__DS 0x2 +#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANKN__SD 0x4 +#define BP_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0 0 +#define BM_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0 0x00000007 +#define BF_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0(v) \ + (((v) << 0) & BM_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0) +#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0__NONE 0x0 +#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0__LS 0x1 +#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0__DS 0x2 +#define BV_PXP_POWER_REG0_LUT_LP_STATE_WAY0_BANK0__SD 0x4 + +#define HW_PXP_POWER_REG1 (0x00000330) + +#define BP_PXP_POWER_REG1_RSVD0 24 +#define BM_PXP_POWER_REG1_RSVD0 0xFF000000 +#define BF_PXP_POWER_REG1_RSVD0(v) \ + (((v) << 24) & BM_PXP_POWER_REG1_RSVD0) +#define BP_PXP_POWER_REG1_ALU_B_MEM_LP_STATE 21 +#define BM_PXP_POWER_REG1_ALU_B_MEM_LP_STATE 0x00E00000 +#define BF_PXP_POWER_REG1_ALU_B_MEM_LP_STATE(v) \ + (((v) << 21) & BM_PXP_POWER_REG1_ALU_B_MEM_LP_STATE) +#define BV_PXP_POWER_REG1_ALU_B_MEM_LP_STATE__NONE 0x0 +#define BV_PXP_POWER_REG1_ALU_B_MEM_LP_STATE__LS 0x1 +#define BV_PXP_POWER_REG1_ALU_B_MEM_LP_STATE__DS 0x2 +#define BV_PXP_POWER_REG1_ALU_B_MEM_LP_STATE__SD 0x4 +#define BP_PXP_POWER_REG1_ALU_A_MEM_LP_STATE 18 +#define BM_PXP_POWER_REG1_ALU_A_MEM_LP_STATE 0x001C0000 +#define BF_PXP_POWER_REG1_ALU_A_MEM_LP_STATE(v) \ + (((v) << 18) & BM_PXP_POWER_REG1_ALU_A_MEM_LP_STATE) +#define BV_PXP_POWER_REG1_ALU_A_MEM_LP_STATE__NONE 0x0 +#define BV_PXP_POWER_REG1_ALU_A_MEM_LP_STATE__LS 0x1 +#define BV_PXP_POWER_REG1_ALU_A_MEM_LP_STATE__DS 0x2 +#define BV_PXP_POWER_REG1_ALU_A_MEM_LP_STATE__SD 0x4 +#define BP_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE 15 +#define BM_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE 0x00038000 +#define BF_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE(v) \ + (((v) << 15) & BM_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE) +#define BV_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE__NONE 0x0 +#define BV_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE__LS 0x1 +#define BV_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE__DS 0x2 +#define BV_PXP_POWER_REG1_DITH2_LUT_MEM_LP_STATE__SD 0x4 +#define BP_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE 12 +#define BM_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE 0x00007000 +#define BF_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE(v) \ + (((v) << 12) & BM_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE) +#define BV_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE__NONE 0x0 +#define BV_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE__LS 0x1 +#define BV_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE__DS 0x2 +#define BV_PXP_POWER_REG1_DITH1_LUT_MEM_LP_STATE__SD 0x4 +#define BP_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE 9 +#define BM_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE 0x00000E00 +#define BF_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE(v) \ + (((v) << 9) & BM_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE) +#define BV_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE__NONE 0x0 +#define BV_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE__LS 0x1 +#define BV_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE__DS 0x2 +#define BV_PXP_POWER_REG1_DITH0_ERR1_MEM_LP_STATE__SD 0x4 +#define BP_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE 6 +#define BM_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE 0x000001C0 +#define BF_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE(v) \ + (((v) << 6) & BM_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE) +#define BV_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE__NONE 0x0 +#define BV_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE__LS 0x1 +#define BV_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE__DS 0x2 +#define BV_PXP_POWER_REG1_DITH0_ERR0_MEM_LP_STATE__SD 0x4 +#define BP_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE 3 +#define BM_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE 0x00000038 +#define BF_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE(v) \ + (((v) << 3) & BM_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE) +#define BV_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE__NONE 0x0 +#define BV_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE__LS 0x1 +#define BV_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE__DS 0x2 +#define BV_PXP_POWER_REG1_DITH0_LUT_MEM_LP_STATE__SD 0x4 +#define BP_PXP_POWER_REG1_ROT1_MEM_LP_STATE 0 +#define BM_PXP_POWER_REG1_ROT1_MEM_LP_STATE 0x00000007 +#define BF_PXP_POWER_REG1_ROT1_MEM_LP_STATE(v) \ + (((v) << 0) & BM_PXP_POWER_REG1_ROT1_MEM_LP_STATE) +#define BV_PXP_POWER_REG1_ROT1_MEM_LP_STATE__NONE 0x0 +#define BV_PXP_POWER_REG1_ROT1_MEM_LP_STATE__LS 0x1 +#define BV_PXP_POWER_REG1_ROT1_MEM_LP_STATE__DS 0x2 +#define BV_PXP_POWER_REG1_ROT1_MEM_LP_STATE__SD 0x4 + +#define HW_PXP_DATA_PATH_CTRL0 (0x00000340) +#define HW_PXP_DATA_PATH_CTRL0_SET (0x00000344) +#define HW_PXP_DATA_PATH_CTRL0_CLR (0x00000348) +#define HW_PXP_DATA_PATH_CTRL0_TOG (0x0000034c) + +#define BP_PXP_DATA_PATH_CTRL0_MUX15_SEL 30 +#define BM_PXP_DATA_PATH_CTRL0_MUX15_SEL 0xC0000000 +#define BF_PXP_DATA_PATH_CTRL0_MUX15_SEL(v) \ + (((v) << 30) & BM_PXP_DATA_PATH_CTRL0_MUX15_SEL) +#define BV_PXP_DATA_PATH_CTRL0_MUX15_SEL__0 0x0 +#define BV_PXP_DATA_PATH_CTRL0_MUX15_SEL__1 0x1 +#define BV_PXP_DATA_PATH_CTRL0_MUX15_SEL__2 0x2 +#define BV_PXP_DATA_PATH_CTRL0_MUX15_SEL__3 0x3 +#define BP_PXP_DATA_PATH_CTRL0_MUX14_SEL 28 +#define BM_PXP_DATA_PATH_CTRL0_MUX14_SEL 0x30000000 +#define BF_PXP_DATA_PATH_CTRL0_MUX14_SEL(v) \ + (((v) << 28) & BM_PXP_DATA_PATH_CTRL0_MUX14_SEL) +#define BV_PXP_DATA_PATH_CTRL0_MUX14_SEL__0 0x0 +#define BV_PXP_DATA_PATH_CTRL0_MUX14_SEL__1 0x1 +#define BV_PXP_DATA_PATH_CTRL0_MUX14_SEL__2 0x2 +#define BV_PXP_DATA_PATH_CTRL0_MUX14_SEL__3 0x3 +#define BP_PXP_DATA_PATH_CTRL0_MUX13_SEL 26 +#define BM_PXP_DATA_PATH_CTRL0_MUX13_SEL 0x0C000000 +#define BF_PXP_DATA_PATH_CTRL0_MUX13_SEL(v) \ + (((v) << 26) & BM_PXP_DATA_PATH_CTRL0_MUX13_SEL) +#define BV_PXP_DATA_PATH_CTRL0_MUX13_SEL__0 0x0 +#define BV_PXP_DATA_PATH_CTRL0_MUX13_SEL__1 0x1 +#define BV_PXP_DATA_PATH_CTRL0_MUX13_SEL__2 0x2 +#define BV_PXP_DATA_PATH_CTRL0_MUX13_SEL__3 0x3 +#define BP_PXP_DATA_PATH_CTRL0_MUX12_SEL 24 +#define BM_PXP_DATA_PATH_CTRL0_MUX12_SEL 0x03000000 +#define BF_PXP_DATA_PATH_CTRL0_MUX12_SEL(v) \ + (((v) << 24) & BM_PXP_DATA_PATH_CTRL0_MUX12_SEL) +#define BV_PXP_DATA_PATH_CTRL0_MUX12_SEL__0 0x0 +#define BV_PXP_DATA_PATH_CTRL0_MUX12_SEL__1 0x1 +#define BV_PXP_DATA_PATH_CTRL0_MUX12_SEL__2 0x2 +#define BV_PXP_DATA_PATH_CTRL0_MUX12_SEL__3 0x3 +#define BP_PXP_DATA_PATH_CTRL0_MUX11_SEL 22 +#define BM_PXP_DATA_PATH_CTRL0_MUX11_SEL 0x00C00000 +#define BF_PXP_DATA_PATH_CTRL0_MUX11_SEL(v) \ + (((v) << 22) & BM_PXP_DATA_PATH_CTRL0_MUX11_SEL) +#define BV_PXP_DATA_PATH_CTRL0_MUX11_SEL__0 0x0 +#define BV_PXP_DATA_PATH_CTRL0_MUX11_SEL__1 0x1 +#define BV_PXP_DATA_PATH_CTRL0_MUX11_SEL__2 0x2 +#define BV_PXP_DATA_PATH_CTRL0_MUX11_SEL__3 0x3 +#define BP_PXP_DATA_PATH_CTRL0_MUX10_SEL 20 +#define BM_PXP_DATA_PATH_CTRL0_MUX10_SEL 0x00300000 +#define BF_PXP_DATA_PATH_CTRL0_MUX10_SEL(v) \ + (((v) << 20) & BM_PXP_DATA_PATH_CTRL0_MUX10_SEL) +#define BV_PXP_DATA_PATH_CTRL0_MUX10_SEL__0 0x0 +#define BV_PXP_DATA_PATH_CTRL0_MUX10_SEL__1 0x1 +#define BV_PXP_DATA_PATH_CTRL0_MUX10_SEL__2 0x2 +#define BV_PXP_DATA_PATH_CTRL0_MUX10_SEL__3 0x3 +#define BP_PXP_DATA_PATH_CTRL0_MUX9_SEL 18 +#define BM_PXP_DATA_PATH_CTRL0_MUX9_SEL 0x000C0000 +#define BF_PXP_DATA_PATH_CTRL0_MUX9_SEL(v) \ + (((v) << 18) & BM_PXP_DATA_PATH_CTRL0_MUX9_SEL) +#define BV_PXP_DATA_PATH_CTRL0_MUX9_SEL__0 0x0 +#define BV_PXP_DATA_PATH_CTRL0_MUX9_SEL__1 0x1 +#define BV_PXP_DATA_PATH_CTRL0_MUX9_SEL__2 0x2 +#define BV_PXP_DATA_PATH_CTRL0_MUX9_SEL__3 0x3 +#define BP_PXP_DATA_PATH_CTRL0_MUX8_SEL 16 +#define BM_PXP_DATA_PATH_CTRL0_MUX8_SEL 0x00030000 +#define BF_PXP_DATA_PATH_CTRL0_MUX8_SEL(v) \ + (((v) << 16) & BM_PXP_DATA_PATH_CTRL0_MUX8_SEL) +#define BV_PXP_DATA_PATH_CTRL0_MUX8_SEL__0 0x0 +#define BV_PXP_DATA_PATH_CTRL0_MUX8_SEL__1 0x1 +#define BV_PXP_DATA_PATH_CTRL0_MUX8_SEL__2 0x2 +#define BV_PXP_DATA_PATH_CTRL0_MUX8_SEL__3 0x3 +#define BP_PXP_DATA_PATH_CTRL0_MUX7_SEL 14 +#define BM_PXP_DATA_PATH_CTRL0_MUX7_SEL 0x0000C000 +#define BF_PXP_DATA_PATH_CTRL0_MUX7_SEL(v) \ + (((v) << 14) & BM_PXP_DATA_PATH_CTRL0_MUX7_SEL) +#define BV_PXP_DATA_PATH_CTRL0_MUX7_SEL__0 0x0 +#define BV_PXP_DATA_PATH_CTRL0_MUX7_SEL__1 0x1 +#define BV_PXP_DATA_PATH_CTRL0_MUX7_SEL__2 0x2 +#define BV_PXP_DATA_PATH_CTRL0_MUX7_SEL__3 0x3 +#define BP_PXP_DATA_PATH_CTRL0_MUX6_SEL 12 +#define BM_PXP_DATA_PATH_CTRL0_MUX6_SEL 0x00003000 +#define BF_PXP_DATA_PATH_CTRL0_MUX6_SEL(v) \ + (((v) << 12) & BM_PXP_DATA_PATH_CTRL0_MUX6_SEL) +#define BV_PXP_DATA_PATH_CTRL0_MUX6_SEL__0 0x0 +#define BV_PXP_DATA_PATH_CTRL0_MUX6_SEL__1 0x1 +#define BV_PXP_DATA_PATH_CTRL0_MUX6_SEL__2 0x2 +#define BV_PXP_DATA_PATH_CTRL0_MUX6_SEL__3 0x3 +#define BP_PXP_DATA_PATH_CTRL0_MUX5_SEL 10 +#define BM_PXP_DATA_PATH_CTRL0_MUX5_SEL 0x00000C00 +#define BF_PXP_DATA_PATH_CTRL0_MUX5_SEL(v) \ + (((v) << 10) & BM_PXP_DATA_PATH_CTRL0_MUX5_SEL) +#define BV_PXP_DATA_PATH_CTRL0_MUX5_SEL__0 0x0 +#define BV_PXP_DATA_PATH_CTRL0_MUX5_SEL__1 0x1 +#define BV_PXP_DATA_PATH_CTRL0_MUX5_SEL__2 0x2 +#define BV_PXP_DATA_PATH_CTRL0_MUX5_SEL__3 0x3 +#define BP_PXP_DATA_PATH_CTRL0_MUX4_SEL 8 +#define BM_PXP_DATA_PATH_CTRL0_MUX4_SEL 0x00000300 +#define BF_PXP_DATA_PATH_CTRL0_MUX4_SEL(v) \ + (((v) << 8) & BM_PXP_DATA_PATH_CTRL0_MUX4_SEL) +#define BV_PXP_DATA_PATH_CTRL0_MUX4_SEL__0 0x0 +#define BV_PXP_DATA_PATH_CTRL0_MUX4_SEL__1 0x1 +#define BV_PXP_DATA_PATH_CTRL0_MUX4_SEL__2 0x2 +#define BV_PXP_DATA_PATH_CTRL0_MUX4_SEL__3 0x3 +#define BP_PXP_DATA_PATH_CTRL0_MUX3_SEL 6 +#define BM_PXP_DATA_PATH_CTRL0_MUX3_SEL 0x000000C0 +#define BF_PXP_DATA_PATH_CTRL0_MUX3_SEL(v) \ + (((v) << 6) & BM_PXP_DATA_PATH_CTRL0_MUX3_SEL) +#define BV_PXP_DATA_PATH_CTRL0_MUX3_SEL__0 0x0 +#define BV_PXP_DATA_PATH_CTRL0_MUX3_SEL__1 0x1 +#define BV_PXP_DATA_PATH_CTRL0_MUX3_SEL__2 0x2 +#define BV_PXP_DATA_PATH_CTRL0_MUX3_SEL__3 0x3 +#define BP_PXP_DATA_PATH_CTRL0_MUX2_SEL 4 +#define BM_PXP_DATA_PATH_CTRL0_MUX2_SEL 0x00000030 +#define BF_PXP_DATA_PATH_CTRL0_MUX2_SEL(v) \ + (((v) << 4) & BM_PXP_DATA_PATH_CTRL0_MUX2_SEL) +#define BV_PXP_DATA_PATH_CTRL0_MUX2_SEL__0 0x0 +#define BV_PXP_DATA_PATH_CTRL0_MUX2_SEL__1 0x1 +#define BV_PXP_DATA_PATH_CTRL0_MUX2_SEL__2 0x2 +#define BV_PXP_DATA_PATH_CTRL0_MUX2_SEL__3 0x3 +#define BP_PXP_DATA_PATH_CTRL0_MUX1_SEL 2 +#define BM_PXP_DATA_PATH_CTRL0_MUX1_SEL 0x0000000C +#define BF_PXP_DATA_PATH_CTRL0_MUX1_SEL(v) \ + (((v) << 2) & BM_PXP_DATA_PATH_CTRL0_MUX1_SEL) +#define BV_PXP_DATA_PATH_CTRL0_MUX1_SEL__0 0x0 +#define BV_PXP_DATA_PATH_CTRL0_MUX1_SEL__1 0x1 +#define BV_PXP_DATA_PATH_CTRL0_MUX1_SEL__2 0x2 +#define BV_PXP_DATA_PATH_CTRL0_MUX1_SEL__3 0x3 +#define BP_PXP_DATA_PATH_CTRL0_MUX0_SEL 0 +#define BM_PXP_DATA_PATH_CTRL0_MUX0_SEL 0x00000003 +#define BF_PXP_DATA_PATH_CTRL0_MUX0_SEL(v) \ + (((v) << 0) & BM_PXP_DATA_PATH_CTRL0_MUX0_SEL) +#define BV_PXP_DATA_PATH_CTRL0_MUX0_SEL__0 0x0 +#define BV_PXP_DATA_PATH_CTRL0_MUX0_SEL__1 0x1 +#define BV_PXP_DATA_PATH_CTRL0_MUX0_SEL__2 0x2 +#define BV_PXP_DATA_PATH_CTRL0_MUX0_SEL__3 0x3 + +#define HW_PXP_DATA_PATH_CTRL1 (0x00000350) +#define HW_PXP_DATA_PATH_CTRL1_SET (0x00000354) +#define HW_PXP_DATA_PATH_CTRL1_CLR (0x00000358) +#define HW_PXP_DATA_PATH_CTRL1_TOG (0x0000035c) + +#define BP_PXP_DATA_PATH_CTRL1_RSVD0 4 +#define BM_PXP_DATA_PATH_CTRL1_RSVD0 0xFFFFFFF0 +#define BF_PXP_DATA_PATH_CTRL1_RSVD0(v) \ + (((v) << 4) & BM_PXP_DATA_PATH_CTRL1_RSVD0) +#define BP_PXP_DATA_PATH_CTRL1_MUX17_SEL 2 +#define BM_PXP_DATA_PATH_CTRL1_MUX17_SEL 0x0000000C +#define BF_PXP_DATA_PATH_CTRL1_MUX17_SEL(v) \ + (((v) << 2) & BM_PXP_DATA_PATH_CTRL1_MUX17_SEL) +#define BV_PXP_DATA_PATH_CTRL1_MUX17_SEL__0 0x0 +#define BV_PXP_DATA_PATH_CTRL1_MUX17_SEL__1 0x1 +#define BV_PXP_DATA_PATH_CTRL1_MUX17_SEL__2 0x2 +#define BV_PXP_DATA_PATH_CTRL1_MUX17_SEL__3 0x3 +#define BP_PXP_DATA_PATH_CTRL1_MUX16_SEL 0 +#define BM_PXP_DATA_PATH_CTRL1_MUX16_SEL 0x00000003 +#define BF_PXP_DATA_PATH_CTRL1_MUX16_SEL(v) \ + (((v) << 0) & BM_PXP_DATA_PATH_CTRL1_MUX16_SEL) +#define BV_PXP_DATA_PATH_CTRL1_MUX16_SEL__0 0x0 +#define BV_PXP_DATA_PATH_CTRL1_MUX16_SEL__1 0x1 +#define BV_PXP_DATA_PATH_CTRL1_MUX16_SEL__2 0x2 +#define BV_PXP_DATA_PATH_CTRL1_MUX16_SEL__3 0x3 + +#define HW_PXP_INIT_MEM_CTRL (0x00000360) +#define HW_PXP_INIT_MEM_CTRL_SET (0x00000364) +#define HW_PXP_INIT_MEM_CTRL_CLR (0x00000368) +#define HW_PXP_INIT_MEM_CTRL_TOG (0x0000036c) + +#define BM_PXP_INIT_MEM_CTRL_START 0x80000000 +#define BF_PXP_INIT_MEM_CTRL_START(v) \ + (((v) << 31) & BM_PXP_INIT_MEM_CTRL_START) +#define BP_PXP_INIT_MEM_CTRL_SELECT 27 +#define BM_PXP_INIT_MEM_CTRL_SELECT 0x78000000 +#define BF_PXP_INIT_MEM_CTRL_SELECT(v) \ + (((v) << 27) & BM_PXP_INIT_MEM_CTRL_SELECT) +#define BV_PXP_INIT_MEM_CTRL_SELECT__DITHER0_LUT 0x0 +#define BV_PXP_INIT_MEM_CTRL_SELECT__DITHER0_ERR0 0x1 +#define BV_PXP_INIT_MEM_CTRL_SELECT__DITHER0_ERR1 0x2 +#define BV_PXP_INIT_MEM_CTRL_SELECT__DITHER1_LUT 0x3 +#define BV_PXP_INIT_MEM_CTRL_SELECT__DITHER2_LUT 0x4 +#define BV_PXP_INIT_MEM_CTRL_SELECT__ALU_A 0x5 +#define BV_PXP_INIT_MEM_CTRL_SELECT__ALU_B 0x6 +#define BV_PXP_INIT_MEM_CTRL_SELECT__WFE_A_FETCH 0x7 +#define BV_PXP_INIT_MEM_CTRL_SELECT__WFE_B_FETCH 0x8 +#define BV_PXP_INIT_MEM_CTRL_SELECT__RESERVED 0x15 +#define BP_PXP_INIT_MEM_CTRL_RSVD0 16 +#define BM_PXP_INIT_MEM_CTRL_RSVD0 0x07FF0000 +#define BF_PXP_INIT_MEM_CTRL_RSVD0(v) \ + (((v) << 16) & BM_PXP_INIT_MEM_CTRL_RSVD0) +#define BP_PXP_INIT_MEM_CTRL_ADDR 0 +#define BM_PXP_INIT_MEM_CTRL_ADDR 0x0000FFFF +#define BF_PXP_INIT_MEM_CTRL_ADDR(v) \ + (((v) << 0) & BM_PXP_INIT_MEM_CTRL_ADDR) + +#define HW_PXP_INIT_MEM_DATA (0x00000370) + +#define BP_PXP_INIT_MEM_DATA_DATA 0 +#define BM_PXP_INIT_MEM_DATA_DATA 0xFFFFFFFF +#define BF_PXP_INIT_MEM_DATA_DATA(v) (v) + +#define HW_PXP_INIT_MEM_DATA_HIGH (0x00000380) + +#define BP_PXP_INIT_MEM_DATA_HIGH_DATA 0 +#define BM_PXP_INIT_MEM_DATA_HIGH_DATA 0xFFFFFFFF +#define BF_PXP_INIT_MEM_DATA_HIGH_DATA(v) (v) + +#define HW_PXP_IRQ_MASK (0x00000390) +#define HW_PXP_IRQ_MASK_SET (0x00000394) +#define HW_PXP_IRQ_MASK_CLR (0x00000398) +#define HW_PXP_IRQ_MASK_TOG (0x0000039c) + +#define BM_PXP_IRQ_MASK_COMPRESS_DONE_IRQ_EN 0x80000000 +#define BF_PXP_IRQ_MASK_COMPRESS_DONE_IRQ_EN(v) \ + (((v) << 31) & BM_PXP_IRQ_MASK_COMPRESS_DONE_IRQ_EN) +#define BP_PXP_IRQ_MASK_RSVD1 16 +#define BM_PXP_IRQ_MASK_RSVD1 0x7FFF0000 +#define BF_PXP_IRQ_MASK_RSVD1(v) \ + (((v) << 16) & BM_PXP_IRQ_MASK_RSVD1) +#define BM_PXP_IRQ_MASK_WFE_B_STORE_IRQ_EN 0x00008000 +#define BF_PXP_IRQ_MASK_WFE_B_STORE_IRQ_EN(v) \ + (((v) << 15) & BM_PXP_IRQ_MASK_WFE_B_STORE_IRQ_EN) +#define BM_PXP_IRQ_MASK_WFE_A_STORE_IRQ_EN 0x00004000 +#define BF_PXP_IRQ_MASK_WFE_A_STORE_IRQ_EN(v) \ + (((v) << 14) & BM_PXP_IRQ_MASK_WFE_A_STORE_IRQ_EN) +#define BM_PXP_IRQ_MASK_DITHER_STORE_IRQ_EN 0x00002000 +#define BF_PXP_IRQ_MASK_DITHER_STORE_IRQ_EN(v) \ + (((v) << 13) & BM_PXP_IRQ_MASK_DITHER_STORE_IRQ_EN) +#define BM_PXP_IRQ_MASK_FIRST_STORE_IRQ_EN 0x00001000 +#define BF_PXP_IRQ_MASK_FIRST_STORE_IRQ_EN(v) \ + (((v) << 12) & BM_PXP_IRQ_MASK_FIRST_STORE_IRQ_EN) +#define BM_PXP_IRQ_MASK_WFE_B_CH1_STORE_IRQ_EN 0x00000800 +#define BF_PXP_IRQ_MASK_WFE_B_CH1_STORE_IRQ_EN(v) \ + (((v) << 11) & BM_PXP_IRQ_MASK_WFE_B_CH1_STORE_IRQ_EN) +#define BM_PXP_IRQ_MASK_WFE_B_CH0_STORE_IRQ_EN 0x00000400 +#define BF_PXP_IRQ_MASK_WFE_B_CH0_STORE_IRQ_EN(v) \ + (((v) << 10) & BM_PXP_IRQ_MASK_WFE_B_CH0_STORE_IRQ_EN) +#define BM_PXP_IRQ_MASK_WFE_A_CH1_STORE_IRQ_EN 0x00000200 +#define BF_PXP_IRQ_MASK_WFE_A_CH1_STORE_IRQ_EN(v) \ + (((v) << 9) & BM_PXP_IRQ_MASK_WFE_A_CH1_STORE_IRQ_EN) +#define BM_PXP_IRQ_MASK_WFE_A_CH0_STORE_IRQ_EN 0x00000100 +#define BF_PXP_IRQ_MASK_WFE_A_CH0_STORE_IRQ_EN(v) \ + (((v) << 8) & BM_PXP_IRQ_MASK_WFE_A_CH0_STORE_IRQ_EN) +#define BM_PXP_IRQ_MASK_DITHER_CH1_STORE_IRQ_EN 0x00000080 +#define BF_PXP_IRQ_MASK_DITHER_CH1_STORE_IRQ_EN(v) \ + (((v) << 7) & BM_PXP_IRQ_MASK_DITHER_CH1_STORE_IRQ_EN) +#define BM_PXP_IRQ_MASK_DITHER_CH0_STORE_IRQ_EN 0x00000040 +#define BF_PXP_IRQ_MASK_DITHER_CH0_STORE_IRQ_EN(v) \ + (((v) << 6) & BM_PXP_IRQ_MASK_DITHER_CH0_STORE_IRQ_EN) +#define BM_PXP_IRQ_MASK_DITHER_CH1_PREFETCH_IRQ_EN 0x00000020 +#define BF_PXP_IRQ_MASK_DITHER_CH1_PREFETCH_IRQ_EN(v) \ + (((v) << 5) & BM_PXP_IRQ_MASK_DITHER_CH1_PREFETCH_IRQ_EN) +#define BM_PXP_IRQ_MASK_DITHER_CH0_PREFETCH_IRQ_EN 0x00000010 +#define BF_PXP_IRQ_MASK_DITHER_CH0_PREFETCH_IRQ_EN(v) \ + (((v) << 4) & BM_PXP_IRQ_MASK_DITHER_CH0_PREFETCH_IRQ_EN) +#define BM_PXP_IRQ_MASK_FIRST_CH1_STORE_IRQ_EN 0x00000008 +#define BF_PXP_IRQ_MASK_FIRST_CH1_STORE_IRQ_EN(v) \ + (((v) << 3) & BM_PXP_IRQ_MASK_FIRST_CH1_STORE_IRQ_EN) +#define BM_PXP_IRQ_MASK_FIRST_CH0_STORE_IRQ_EN 0x00000004 +#define BF_PXP_IRQ_MASK_FIRST_CH0_STORE_IRQ_EN(v) \ + (((v) << 2) & BM_PXP_IRQ_MASK_FIRST_CH0_STORE_IRQ_EN) +#define BM_PXP_IRQ_MASK_FIRST_CH1_PREFETCH_IRQ_EN 0x00000002 +#define BF_PXP_IRQ_MASK_FIRST_CH1_PREFETCH_IRQ_EN(v) \ + (((v) << 1) & BM_PXP_IRQ_MASK_FIRST_CH1_PREFETCH_IRQ_EN) +#define BM_PXP_IRQ_MASK_FIRST_CH0_PREFETCH_IRQ_EN 0x00000001 +#define BF_PXP_IRQ_MASK_FIRST_CH0_PREFETCH_IRQ_EN(v) \ + (((v) << 0) & BM_PXP_IRQ_MASK_FIRST_CH0_PREFETCH_IRQ_EN) + +#define HW_PXP_IRQ (0x000003a0) +#define HW_PXP_IRQ_SET (0x000003a4) +#define HW_PXP_IRQ_CLR (0x000003a8) +#define HW_PXP_IRQ_TOG (0x000003ac) + +#define BM_PXP_IRQ_COMPRESS_DONE_IRQ 0x80000000 +#define BF_PXP_IRQ_COMPRESS_DONE_IRQ(v) \ + (((v) << 31) & BM_PXP_IRQ_COMPRESS_DONE_IRQ) +#define BP_PXP_IRQ_RSVD1 16 +#define BM_PXP_IRQ_RSVD1 0x7FFF0000 +#define BF_PXP_IRQ_RSVD1(v) \ + (((v) << 16) & BM_PXP_IRQ_RSVD1) +#define BM_PXP_IRQ_WFE_B_STORE_IRQ 0x00008000 +#define BF_PXP_IRQ_WFE_B_STORE_IRQ(v) \ + (((v) << 15) & BM_PXP_IRQ_WFE_B_STORE_IRQ) +#define BM_PXP_IRQ_WFE_A_STORE_IRQ 0x00004000 +#define BF_PXP_IRQ_WFE_A_STORE_IRQ(v) \ + (((v) << 14) & BM_PXP_IRQ_WFE_A_STORE_IRQ) +#define BM_PXP_IRQ_DITHER_STORE_IRQ 0x00002000 +#define BF_PXP_IRQ_DITHER_STORE_IRQ(v) \ + (((v) << 13) & BM_PXP_IRQ_DITHER_STORE_IRQ) +#define BM_PXP_IRQ_FIRST_STORE_IRQ 0x00001000 +#define BF_PXP_IRQ_FIRST_STORE_IRQ(v) \ + (((v) << 12) & BM_PXP_IRQ_FIRST_STORE_IRQ) +#define BM_PXP_IRQ_WFE_B_CH1_STORE_IRQ 0x00000800 +#define BF_PXP_IRQ_WFE_B_CH1_STORE_IRQ(v) \ + (((v) << 11) & BM_PXP_IRQ_WFE_B_CH1_STORE_IRQ) +#define BM_PXP_IRQ_WFE_B_CH0_STORE_IRQ 0x00000400 +#define BF_PXP_IRQ_WFE_B_CH0_STORE_IRQ(v) \ + (((v) << 10) & BM_PXP_IRQ_WFE_B_CH0_STORE_IRQ) +#define BM_PXP_IRQ_WFE_A_CH1_STORE_IRQ 0x00000200 +#define BF_PXP_IRQ_WFE_A_CH1_STORE_IRQ(v) \ + (((v) << 9) & BM_PXP_IRQ_WFE_A_CH1_STORE_IRQ) +#define BM_PXP_IRQ_WFE_A_CH0_STORE_IRQ 0x00000100 +#define BF_PXP_IRQ_WFE_A_CH0_STORE_IRQ(v) \ + (((v) << 8) & BM_PXP_IRQ_WFE_A_CH0_STORE_IRQ) +#define BM_PXP_IRQ_DITHER_CH1_STORE_IRQ 0x00000080 +#define BF_PXP_IRQ_DITHER_CH1_STORE_IRQ(v) \ + (((v) << 7) & BM_PXP_IRQ_DITHER_CH1_STORE_IRQ) +#define BM_PXP_IRQ_DITHER_CH0_STORE_IRQ 0x00000040 +#define BF_PXP_IRQ_DITHER_CH0_STORE_IRQ(v) \ + (((v) << 6) & BM_PXP_IRQ_DITHER_CH0_STORE_IRQ) +#define BM_PXP_IRQ_DITHER_CH1_PREFETCH_IRQ 0x00000020 +#define BF_PXP_IRQ_DITHER_CH1_PREFETCH_IRQ(v) \ + (((v) << 5) & BM_PXP_IRQ_DITHER_CH1_PREFETCH_IRQ) +#define BM_PXP_IRQ_DITHER_CH0_PREFETCH_IRQ 0x00000010 +#define BF_PXP_IRQ_DITHER_CH0_PREFETCH_IRQ(v) \ + (((v) << 4) & BM_PXP_IRQ_DITHER_CH0_PREFETCH_IRQ) +#define BM_PXP_IRQ_FIRST_CH1_STORE_IRQ 0x00000008 +#define BF_PXP_IRQ_FIRST_CH1_STORE_IRQ(v) \ + (((v) << 3) & BM_PXP_IRQ_FIRST_CH1_STORE_IRQ) +#define BM_PXP_IRQ_FIRST_CH0_STORE_IRQ 0x00000004 +#define BF_PXP_IRQ_FIRST_CH0_STORE_IRQ(v) \ + (((v) << 2) & BM_PXP_IRQ_FIRST_CH0_STORE_IRQ) +#define BM_PXP_IRQ_FIRST_CH1_PREFETCH_IRQ 0x00000002 +#define BF_PXP_IRQ_FIRST_CH1_PREFETCH_IRQ(v) \ + (((v) << 1) & BM_PXP_IRQ_FIRST_CH1_PREFETCH_IRQ) +#define BM_PXP_IRQ_FIRST_CH0_PREFETCH_IRQ 0x00000001 +#define BF_PXP_IRQ_FIRST_CH0_PREFETCH_IRQ(v) \ + (((v) << 0) & BM_PXP_IRQ_FIRST_CH0_PREFETCH_IRQ) + +#define HW_PXP_NEXT (0x00000400) + +#define BP_PXP_NEXT_POINTER 2 +#define BM_PXP_NEXT_POINTER 0xFFFFFFFC +#define BF_PXP_NEXT_POINTER(v) \ + (((v) << 2) & BM_PXP_NEXT_POINTER) +#define BM_PXP_NEXT_RSVD 0x00000002 +#define BF_PXP_NEXT_RSVD(v) \ + (((v) << 1) & BM_PXP_NEXT_RSVD) +#define BM_PXP_NEXT_ENABLED 0x00000001 +#define BF_PXP_NEXT_ENABLED(v) \ + (((v) << 0) & BM_PXP_NEXT_ENABLED) + +#define HW_PXP_DEBUGCTRL (0x00000410) + +#define BP_PXP_DEBUGCTRL_RSVD 12 +#define BM_PXP_DEBUGCTRL_RSVD 0xFFFFF000 +#define BF_PXP_DEBUGCTRL_RSVD(v) \ + (((v) << 12) & BM_PXP_DEBUGCTRL_RSVD) +#define BP_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT 8 +#define BM_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT 0x00000F00 +#define BF_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT(v) \ + (((v) << 8) & BM_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT) +#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__NONE 0x0 +#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__MISS_CNT 0x1 +#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__HIT_CNT 0x2 +#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__LAT_CNT 0x4 +#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__MAX_LAT 0x8 +#define BP_PXP_DEBUGCTRL_SELECT 0 +#define BM_PXP_DEBUGCTRL_SELECT 0x000000FF +#define BF_PXP_DEBUGCTRL_SELECT(v) \ + (((v) << 0) & BM_PXP_DEBUGCTRL_SELECT) +#define BV_PXP_DEBUGCTRL_SELECT__NONE 0x0 +#define BV_PXP_DEBUGCTRL_SELECT__CTRL 0x1 +#define BV_PXP_DEBUGCTRL_SELECT__PSBUF 0x2 +#define BV_PXP_DEBUGCTRL_SELECT__PSBAX 0x3 +#define BV_PXP_DEBUGCTRL_SELECT__PSBAY 0x4 +#define BV_PXP_DEBUGCTRL_SELECT__ASBUF 0x5 +#define BV_PXP_DEBUGCTRL_SELECT__ROTATION 0x6 +#define BV_PXP_DEBUGCTRL_SELECT__OUTBUF0 0x7 +#define BV_PXP_DEBUGCTRL_SELECT__OUTBUF1 0x8 +#define BV_PXP_DEBUGCTRL_SELECT__OUTBUF2 0x9 +#define BV_PXP_DEBUGCTRL_SELECT__LUT_STAT 0x10 +#define BV_PXP_DEBUGCTRL_SELECT__LUT_MISS 0x11 +#define BV_PXP_DEBUGCTRL_SELECT__LUT_HIT 0x12 +#define BV_PXP_DEBUGCTRL_SELECT__LUT_LAT 0x13 +#define BV_PXP_DEBUGCTRL_SELECT__LUT_MAX_LAT 0x14 + +#define HW_PXP_DEBUG (0x00000420) + +#define BP_PXP_DEBUG_DATA 0 +#define BM_PXP_DEBUG_DATA 0xFFFFFFFF +#define BF_PXP_DEBUG_DATA(v) (v) + +#define HW_PXP_VERSION (0x00000430) + +#define BP_PXP_VERSION_MAJOR 24 +#define BM_PXP_VERSION_MAJOR 0xFF000000 +#define BF_PXP_VERSION_MAJOR(v) \ + (((v) << 24) & BM_PXP_VERSION_MAJOR) +#define BP_PXP_VERSION_MINOR 16 +#define BM_PXP_VERSION_MINOR 0x00FF0000 +#define BF_PXP_VERSION_MINOR(v) \ + (((v) << 16) & BM_PXP_VERSION_MINOR) +#define BP_PXP_VERSION_STEP 0 +#define BM_PXP_VERSION_STEP 0x0000FFFF +#define BF_PXP_VERSION_STEP(v) \ + (((v) << 0) & BM_PXP_VERSION_STEP) + +#endif /* __IMX_PXP_H__ */ diff --git a/drivers/media/platform/m2m-deinterlace.c b/drivers/media/platform/m2m-deinterlace.c index 5f84d2aa47ab..c62e598ee7d0 100644 --- a/drivers/media/platform/m2m-deinterlace.c +++ b/drivers/media/platform/m2m-deinterlace.c @@ -438,9 +438,9 @@ static void deinterlace_device_run(void *priv) static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - strlcpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver)); - strlcpy(cap->card, MEM2MEM_NAME, sizeof(cap->card)); - strlcpy(cap->bus_info, MEM2MEM_NAME, sizeof(cap->card)); + strscpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver)); + strscpy(cap->card, MEM2MEM_NAME, sizeof(cap->card)); + strscpy(cap->bus_info, MEM2MEM_NAME, sizeof(cap->card)); /* * This is only a mem-to-mem video device. The capture and output * device capability flags are left only for backward compatibility @@ -474,7 +474,7 @@ static int enum_fmt(struct v4l2_fmtdesc *f, u32 type) if (i < NUM_FORMATS) { /* Format found */ fmt = &formats[i]; - strlcpy(f->description, fmt->name, sizeof(f->description)); + strscpy(f->description, fmt->name, sizeof(f->description)); f->pixelformat = fmt->fourcc; return 0; } diff --git a/drivers/media/platform/marvell-ccic/cafe-driver.c b/drivers/media/platform/marvell-ccic/cafe-driver.c index 57d2c483ad09..2986cb4b88d0 100644 --- a/drivers/media/platform/marvell-ccic/cafe-driver.c +++ b/drivers/media/platform/marvell-ccic/cafe-driver.c @@ -341,7 +341,7 @@ static int cafe_smbus_setup(struct cafe_camera *cam) return -ENOMEM; adap->owner = THIS_MODULE; adap->algo = &cafe_smbus_algo; - strcpy(adap->name, "cafe_ccic"); + strscpy(adap->name, "cafe_ccic", sizeof(adap->name)); adap->dev.parent = &cam->pdev->dev; i2c_set_adapdata(adap, cam); ret = i2c_add_adapter(adap); diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c index dfdbd4354b74..f1b301810260 100644 --- a/drivers/media/platform/marvell-ccic/mcam-core.c +++ b/drivers/media/platform/marvell-ccic/mcam-core.c @@ -794,7 +794,7 @@ static void mcam_ctlr_image(struct mcam_camera *cam) /* * This field controls the generation of EOF(DVP only) */ - if (cam->bus_type != V4L2_MBUS_CSI2) + if (cam->bus_type != V4L2_MBUS_CSI2_DPHY) mcam_reg_set_bit(cam, REG_CTRL0, C0_EOF_VSYNC | C0_VEDGE_CTRL); } @@ -1023,7 +1023,7 @@ static int mcam_read_setup(struct mcam_camera *cam) cam->calc_dphy(cam); cam_dbg(cam, "camera: DPHY sets: dphy3=0x%x, dphy5=0x%x, dphy6=0x%x\n", cam->dphy[0], cam->dphy[1], cam->dphy[2]); - if (cam->bus_type == V4L2_MBUS_CSI2) + if (cam->bus_type == V4L2_MBUS_CSI2_DPHY) mcam_enable_mipi(cam); else mcam_disable_mipi(cam); @@ -1303,9 +1303,9 @@ static int mcam_vidioc_querycap(struct file *file, void *priv, { struct mcam_camera *cam = video_drvdata(file); - strcpy(cap->driver, "marvell_ccic"); - strcpy(cap->card, "marvell_ccic"); - strlcpy(cap->bus_info, cam->bus_info, sizeof(cap->bus_info)); + strscpy(cap->driver, "marvell_ccic", sizeof(cap->driver)); + strscpy(cap->card, "marvell_ccic", sizeof(cap->card)); + strscpy(cap->bus_info, cam->bus_info, sizeof(cap->bus_info)); cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; @@ -1318,8 +1318,8 @@ static int mcam_vidioc_enum_fmt_vid_cap(struct file *filp, { if (fmt->index >= N_MCAM_FMTS) return -EINVAL; - strlcpy(fmt->description, mcam_formats[fmt->index].desc, - sizeof(fmt->description)); + strscpy(fmt->description, mcam_formats[fmt->index].desc, + sizeof(fmt->description)); fmt->pixelformat = mcam_formats[fmt->index].pixelformat; return 0; } @@ -1421,7 +1421,7 @@ static int mcam_vidioc_enum_input(struct file *filp, void *priv, return -EINVAL; input->type = V4L2_INPUT_TYPE_CAMERA; - strcpy(input->name, "Camera"); + strscpy(input->name, "Camera", sizeof(input->name)); return 0; } diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c b/drivers/media/platform/marvell-ccic/mmp-driver.c index 6d9f0abb2660..70a2833db0d1 100644 --- a/drivers/media/platform/marvell-ccic/mmp-driver.c +++ b/drivers/media/platform/marvell-ccic/mmp-driver.c @@ -362,7 +362,7 @@ static int mmpcam_probe(struct platform_device *pdev) mcam->mclk_div = pdata->mclk_div; mcam->bus_type = pdata->bus_type; mcam->dphy = pdata->dphy; - if (mcam->bus_type == V4L2_MBUS_CSI2) { + if (mcam->bus_type == V4L2_MBUS_CSI2_DPHY) { cam->mipi_clk = devm_clk_get(mcam->dev, "mipi"); if ((IS_ERR(cam->mipi_clk) && mcam->dphy[2] == 0)) return PTR_ERR(cam->mipi_clk); @@ -371,7 +371,7 @@ static int mmpcam_probe(struct platform_device *pdev) mcam->lane = pdata->lane; mcam->chip_id = MCAM_ARMADA610; mcam->buffer_mode = B_DMA_sg; - strlcpy(mcam->bus_info, "platform:mmp-camera", sizeof(mcam->bus_info)); + strscpy(mcam->bus_info, "platform:mmp-camera", sizeof(mcam->bus_info)); spin_lock_init(&mcam->dev_lock); /* * Get our I/O memory. diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c index 4f24da8afecc..2a5d5002c27e 100644 --- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c +++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c @@ -94,8 +94,8 @@ static int mtk_jpeg_querycap(struct file *file, void *priv, { struct mtk_jpeg_dev *jpeg = video_drvdata(file); - strlcpy(cap->driver, MTK_JPEG_NAME " decoder", sizeof(cap->driver)); - strlcpy(cap->card, MTK_JPEG_NAME " decoder", sizeof(cap->card)); + strscpy(cap->driver, MTK_JPEG_NAME " decoder", sizeof(cap->driver)); + strscpy(cap->card, MTK_JPEG_NAME " decoder", sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", dev_name(jpeg->dev)); diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c b/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c index ceffc31cc6eb..51a13466261e 100644 --- a/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c +++ b/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c @@ -619,9 +619,9 @@ static int mtk_mdp_m2m_querycap(struct file *file, void *fh, struct mtk_mdp_ctx *ctx = fh_to_ctx(fh); struct mtk_mdp_dev *mdp = ctx->mdp_dev; - strlcpy(cap->driver, MTK_MDP_MODULE_NAME, sizeof(cap->driver)); - strlcpy(cap->card, mdp->pdev->name, sizeof(cap->card)); - strlcpy(cap->bus_info, "platform:mt8173", sizeof(cap->bus_info)); + strscpy(cap->driver, MTK_MDP_MODULE_NAME, sizeof(cap->driver)); + strscpy(cap->card, mdp->pdev->name, sizeof(cap->card)); + strscpy(cap->bus_info, "platform:mt8173", sizeof(cap->bus_info)); return 0; } diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c index 0c8a8b4c4e1c..ba619647bc10 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c @@ -613,9 +613,9 @@ static int vidioc_vdec_dqbuf(struct file *file, void *priv, static int vidioc_vdec_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - strlcpy(cap->driver, MTK_VCODEC_DEC_NAME, sizeof(cap->driver)); - strlcpy(cap->bus_info, MTK_PLATFORM_STR, sizeof(cap->bus_info)); - strlcpy(cap->card, MTK_PLATFORM_STR, sizeof(cap->card)); + strscpy(cap->driver, MTK_VCODEC_DEC_NAME, sizeof(cap->driver)); + strscpy(cap->bus_info, MTK_PLATFORM_STR, sizeof(cap->bus_info)); + strscpy(cap->card, MTK_PLATFORM_STR, sizeof(cap->card)); return 0; } diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c index 6ad408514a99..54631ad1c71e 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c @@ -222,9 +222,9 @@ static int vidioc_enum_fmt_vid_out_mplane(struct file *file, void *prov, static int vidioc_venc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - strlcpy(cap->driver, MTK_VCODEC_ENC_NAME, sizeof(cap->driver)); - strlcpy(cap->bus_info, MTK_PLATFORM_STR, sizeof(cap->bus_info)); - strlcpy(cap->card, MTK_PLATFORM_STR, sizeof(cap->card)); + strscpy(cap->driver, MTK_VCODEC_ENC_NAME, sizeof(cap->driver)); + strscpy(cap->bus_info, MTK_PLATFORM_STR, sizeof(cap->bus_info)); + strscpy(cap->card, MTK_PLATFORM_STR, sizeof(cap->card)); return 0; } diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c index 0c28d0b995cc..e80123cba406 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c @@ -49,16 +49,13 @@ int mtk_vcodec_mem_alloc(struct mtk_vcodec_ctx *data, struct mtk_vcodec_ctx *ctx = (struct mtk_vcodec_ctx *)data; struct device *dev = &ctx->dev->plat_dev->dev; - mem->va = dma_alloc_coherent(dev, size, &mem->dma_addr, GFP_KERNEL); - + mem->va = dma_zalloc_coherent(dev, size, &mem->dma_addr, GFP_KERNEL); if (!mem->va) { mtk_v4l2_err("%s dma_alloc size=%ld failed!", dev_name(dev), size); return -ENOMEM; } - memset(mem->va, 0, size); - mtk_v4l2_debug(3, "[%d] - va = %p", ctx->id, mem->va); mtk_v4l2_debug(3, "[%d] - dma = 0x%lx", ctx->id, (unsigned long)mem->dma_addr); diff --git a/drivers/media/platform/mtk-vpu/mtk_vpu.c b/drivers/media/platform/mtk-vpu/mtk_vpu.c index f8d35e3ac1dc..616f78b24a79 100644 --- a/drivers/media/platform/mtk-vpu/mtk_vpu.c +++ b/drivers/media/platform/mtk-vpu/mtk_vpu.c @@ -480,12 +480,12 @@ EXPORT_SYMBOL_GPL(vpu_get_plat_device); /* load vpu program/data memory */ static int load_requested_vpu(struct mtk_vpu *vpu, - const struct firmware *vpu_fw, u8 fw_type) { size_t tcm_size = fw_type ? VPU_DTCM_SIZE : VPU_PTCM_SIZE; size_t fw_size = fw_type ? VPU_D_FW_SIZE : VPU_P_FW_SIZE; char *fw_name = fw_type ? VPU_D_FW : VPU_P_FW; + const struct firmware *vpu_fw; size_t dl_size = 0; size_t extra_fw_size = 0; void *dest; @@ -539,7 +539,6 @@ int vpu_load_firmware(struct platform_device *pdev) struct mtk_vpu *vpu; struct device *dev = &pdev->dev; struct vpu_run *run; - const struct firmware *vpu_fw = NULL; int ret; if (!pdev) { @@ -568,14 +567,14 @@ int vpu_load_firmware(struct platform_device *pdev) run->signaled = false; dev_dbg(vpu->dev, "firmware request\n"); /* Downloading program firmware to device*/ - ret = load_requested_vpu(vpu, vpu_fw, P_FW); + ret = load_requested_vpu(vpu, P_FW); if (ret < 0) { dev_err(dev, "Failed to request %s, %d\n", VPU_P_FW, ret); goto OUT_LOAD_FW; } /* Downloading data firmware to device */ - ret = load_requested_vpu(vpu, vpu_fw, D_FW); + ret = load_requested_vpu(vpu, D_FW); if (ret < 0) { dev_err(dev, "Failed to request %s, %d\n", VPU_D_FW, ret); goto OUT_LOAD_FW; diff --git a/drivers/media/platform/mx2_emmaprp.c b/drivers/media/platform/mx2_emmaprp.c index 64195c4ddeaf..27b078cf98e3 100644 --- a/drivers/media/platform/mx2_emmaprp.c +++ b/drivers/media/platform/mx2_emmaprp.c @@ -413,7 +413,7 @@ static int enum_fmt(struct v4l2_fmtdesc *f, u32 type) if (i < NUM_FORMATS) { /* Format found */ fmt = &formats[i]; - strlcpy(f->description, fmt->name, sizeof(f->description) - 1); + strscpy(f->description, fmt->name, sizeof(f->description) - 1); f->pixelformat = fmt->fourcc; return 0; } diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c index 5700b7818621..f447ae3bb465 100644 --- a/drivers/media/platform/omap/omap_vout.c +++ b/drivers/media/platform/omap/omap_vout.c @@ -1041,8 +1041,8 @@ static int vidioc_querycap(struct file *file, void *fh, { struct omap_vout_device *vout = fh; - strlcpy(cap->driver, VOUT_NAME, sizeof(cap->driver)); - strlcpy(cap->card, vout->vfd->name, sizeof(cap->card)); + strscpy(cap->driver, VOUT_NAME, sizeof(cap->driver)); + strscpy(cap->card, vout->vfd->name, sizeof(cap->card)); cap->bus_info[0] = '\0'; cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_OVERLAY; @@ -1060,8 +1060,8 @@ static int vidioc_enum_fmt_vid_out(struct file *file, void *fh, return -EINVAL; fmt->flags = omap_formats[index].flags; - strlcpy(fmt->description, omap_formats[index].description, - sizeof(fmt->description)); + strscpy(fmt->description, omap_formats[index].description, + sizeof(fmt->description)); fmt->pixelformat = omap_formats[index].pixelformat; return 0; @@ -1868,7 +1868,7 @@ static int __init omap_vout_setup_video_data(struct omap_vout_device *vout) vfd->release = video_device_release; vfd->ioctl_ops = &vout_ioctl_ops; - strlcpy(vfd->name, VOUT_NAME, sizeof(vfd->name)); + strscpy(vfd->name, VOUT_NAME, sizeof(vfd->name)); vfd->fops = &omap_vout_fops; vfd->v4l2_dev = &vout->vid_dev->v4l2_dev; diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 842e2235047d..77fb7987b42f 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -1677,7 +1677,7 @@ static int isp_register_entities(struct isp_device *isp) int ret; isp->media_dev.dev = isp->dev; - strlcpy(isp->media_dev.model, "TI OMAP3 ISP", + strscpy(isp->media_dev.model, "TI OMAP3 ISP", sizeof(isp->media_dev.model)); isp->media_dev.hw_revision = isp->revision; isp->media_dev.ops = &isp_media_ops; @@ -2054,7 +2054,7 @@ static int isp_fwnode_parse(struct device *dev, dev_dbg(dev, "CSI-1/CCP-2 configuration\n"); csi1 = true; break; - case V4L2_MBUS_CSI2: + case V4L2_MBUS_CSI2_DPHY: dev_dbg(dev, "CSI-2 configuration\n"); csi1 = false; break; @@ -2220,6 +2220,7 @@ static int isp_probe(struct platform_device *pdev) mutex_init(&isp->isp_mutex); spin_lock_init(&isp->stat_lock); + v4l2_async_notifier_init(&isp->notifier); ret = v4l2_async_notifier_parse_fwnode_endpoints( &pdev->dev, &isp->notifier, sizeof(struct isp_async_subdev), diff --git a/drivers/media/platform/omap3isp/ispccdc.c b/drivers/media/platform/omap3isp/ispccdc.c index 77b73e27a274..14a1c24037c4 100644 --- a/drivers/media/platform/omap3isp/ispccdc.c +++ b/drivers/media/platform/omap3isp/ispccdc.c @@ -2641,7 +2641,7 @@ static int ccdc_init_entities(struct isp_ccdc_device *ccdc) v4l2_subdev_init(sd, &ccdc_v4l2_ops); sd->internal_ops = &ccdc_v4l2_internal_ops; - strlcpy(sd->name, "OMAP3 ISP CCDC", sizeof(sd->name)); + strscpy(sd->name, "OMAP3 ISP CCDC", sizeof(sd->name)); sd->grp_id = 1 << 16; /* group ID for isp subdevs */ v4l2_set_subdevdata(sd, ccdc); sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE; diff --git a/drivers/media/platform/omap3isp/ispccp2.c b/drivers/media/platform/omap3isp/ispccp2.c index e062939d0d05..2dea423ffc0e 100644 --- a/drivers/media/platform/omap3isp/ispccp2.c +++ b/drivers/media/platform/omap3isp/ispccp2.c @@ -1070,7 +1070,7 @@ static int ccp2_init_entities(struct isp_ccp2_device *ccp2) v4l2_subdev_init(sd, &ccp2_sd_ops); sd->internal_ops = &ccp2_sd_internal_ops; - strlcpy(sd->name, "OMAP3 ISP CCP2", sizeof(sd->name)); + strscpy(sd->name, "OMAP3 ISP CCP2", sizeof(sd->name)); sd->grp_id = 1 << 16; /* group ID for isp subdevs */ v4l2_set_subdevdata(sd, ccp2); sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; diff --git a/drivers/media/platform/omap3isp/ispcsi2.c b/drivers/media/platform/omap3isp/ispcsi2.c index a4d3d030e81e..9c180f607bcb 100644 --- a/drivers/media/platform/omap3isp/ispcsi2.c +++ b/drivers/media/platform/omap3isp/ispcsi2.c @@ -1234,7 +1234,7 @@ static int csi2_init_entities(struct isp_csi2_device *csi2) v4l2_subdev_init(sd, &csi2_ops); sd->internal_ops = &csi2_internal_ops; - strlcpy(sd->name, "OMAP3 ISP CSI2a", sizeof(sd->name)); + strscpy(sd->name, "OMAP3 ISP CSI2a", sizeof(sd->name)); sd->grp_id = 1 << 16; /* group ID for isp subdevs */ v4l2_set_subdevdata(sd, csi2); diff --git a/drivers/media/platform/omap3isp/isppreview.c b/drivers/media/platform/omap3isp/isppreview.c index 3195f7c8b8b7..6ea6aeafd751 100644 --- a/drivers/media/platform/omap3isp/isppreview.c +++ b/drivers/media/platform/omap3isp/isppreview.c @@ -2267,7 +2267,7 @@ static int preview_init_entities(struct isp_prev_device *prev) v4l2_subdev_init(sd, &preview_v4l2_ops); sd->internal_ops = &preview_v4l2_internal_ops; - strlcpy(sd->name, "OMAP3 ISP preview", sizeof(sd->name)); + strscpy(sd->name, "OMAP3 ISP preview", sizeof(sd->name)); sd->grp_id = 1 << 16; /* group ID for isp subdevs */ v4l2_set_subdevdata(sd, prev); sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; diff --git a/drivers/media/platform/omap3isp/ispresizer.c b/drivers/media/platform/omap3isp/ispresizer.c index 0b6a87508584..b281cae036b3 100644 --- a/drivers/media/platform/omap3isp/ispresizer.c +++ b/drivers/media/platform/omap3isp/ispresizer.c @@ -1723,7 +1723,7 @@ static int resizer_init_entities(struct isp_res_device *res) v4l2_subdev_init(sd, &resizer_v4l2_ops); sd->internal_ops = &resizer_v4l2_internal_ops; - strlcpy(sd->name, "OMAP3 ISP resizer", sizeof(sd->name)); + strscpy(sd->name, "OMAP3 ISP resizer", sizeof(sd->name)); sd->grp_id = 1 << 16; /* group ID for isp subdevs */ v4l2_set_subdevdata(sd, res); sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c index 9d228eac24ea..5658f6a326f7 100644 --- a/drivers/media/platform/omap3isp/ispvideo.c +++ b/drivers/media/platform/omap3isp/ispvideo.c @@ -654,9 +654,9 @@ isp_video_querycap(struct file *file, void *fh, struct v4l2_capability *cap) { struct isp_video *video = video_drvdata(file); - strlcpy(cap->driver, ISP_VIDEO_DRIVER_NAME, sizeof(cap->driver)); - strlcpy(cap->card, video->video.name, sizeof(cap->card)); - strlcpy(cap->bus_info, "media", sizeof(cap->bus_info)); + strscpy(cap->driver, ISP_VIDEO_DRIVER_NAME, sizeof(cap->driver)); + strscpy(cap->card, video->video.name, sizeof(cap->card)); + strscpy(cap->bus_info, "media", sizeof(cap->bus_info)); cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING | V4L2_CAP_DEVICE_CAPS; @@ -1251,7 +1251,7 @@ isp_video_enum_input(struct file *file, void *fh, struct v4l2_input *input) if (input->index > 0) return -EINVAL; - strlcpy(input->name, "camera", sizeof(input->name)); + strscpy(input->name, "camera", sizeof(input->name)); input->type = V4L2_INPUT_TYPE_CAMERA; return 0; diff --git a/drivers/media/platform/pxa_camera.c b/drivers/media/platform/pxa_camera.c index b6e9e93bde7a..5f930560eb30 100644 --- a/drivers/media/platform/pxa_camera.c +++ b/drivers/media/platform/pxa_camera.c @@ -633,7 +633,7 @@ static unsigned int pxa_mbus_config_compatible(const struct v4l2_mbus_config *cf mode = common_flags & (V4L2_MBUS_MASTER | V4L2_MBUS_SLAVE); return (!hsync || !vsync || !pclk || !data || !mode) ? 0 : common_flags; - case V4L2_MBUS_CSI2: + case V4L2_MBUS_CSI2_DPHY: mipi_lanes = common_flags & V4L2_MBUS_CSI2_LANES; mipi_clock = common_flags & (V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK | V4L2_MBUS_CSI2_CONTINUOUS_CLOCK); @@ -697,7 +697,6 @@ struct pxa_camera_dev { struct v4l2_pix_format current_pix; struct v4l2_async_subdev asd; - struct v4l2_async_subdev *asds[1]; /* * PXA27x is only supposed to handle one camera on its Quick Capture @@ -1994,9 +1993,9 @@ static int pxac_vidioc_s_fmt_vid_cap(struct file *filp, void *priv, static int pxac_vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - strlcpy(cap->bus_info, "platform:pxa-camera", sizeof(cap->bus_info)); - strlcpy(cap->driver, PXA_CAM_DRV_NAME, sizeof(cap->driver)); - strlcpy(cap->card, pxa_cam_driver_description, sizeof(cap->card)); + strscpy(cap->bus_info, "platform:pxa-camera", sizeof(cap->bus_info)); + strscpy(cap->driver, PXA_CAM_DRV_NAME, sizeof(cap->driver)); + strscpy(cap->card, pxa_cam_driver_description, sizeof(cap->card)); cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; @@ -2010,7 +2009,7 @@ static int pxac_vidioc_enum_input(struct file *file, void *priv, return -EINVAL; i->type = V4L2_INPUT_TYPE_CAMERA; - strlcpy(i->name, "Camera", sizeof(i->name)); + strscpy(i->name, "Camera", sizeof(i->name)); return 0; } @@ -2299,7 +2298,7 @@ static int pxa_camera_pdata_from_dt(struct device *dev, { u32 mclk_rate; struct device_node *remote, *np = dev->of_node; - struct v4l2_fwnode_endpoint ep; + struct v4l2_fwnode_endpoint ep = { .bus_type = 0 }; int err = of_property_read_u32(np, "clock-frequency", &mclk_rate); if (!err) { @@ -2352,12 +2351,10 @@ static int pxa_camera_pdata_from_dt(struct device *dev, asd->match_type = V4L2_ASYNC_MATCH_FWNODE; remote = of_graph_get_remote_port(np); - if (remote) { + if (remote) asd->match.fwnode = of_fwnode_handle(remote); - of_node_put(remote); - } else { + else dev_notice(dev, "no remote for %pOF\n", np); - } out: of_node_put(np); @@ -2397,7 +2394,7 @@ static int pxa_camera_probe(struct platform_device *pdev) pcdev->res = res; pcdev->pdata = pdev->dev.platform_data; - if (&pdev->dev.of_node && !pcdev->pdata) { + if (pdev->dev.of_node && !pcdev->pdata) { err = pxa_camera_pdata_from_dt(&pdev->dev, pcdev, &pcdev->asd); } else { pcdev->platform_flags = pcdev->pdata->flags; @@ -2495,9 +2492,14 @@ static int pxa_camera_probe(struct platform_device *pdev) if (err) goto exit_deactivate; - pcdev->asds[0] = &pcdev->asd; - pcdev->notifier.subdevs = pcdev->asds; - pcdev->notifier.num_subdevs = 1; + v4l2_async_notifier_init(&pcdev->notifier); + + err = v4l2_async_notifier_add_subdev(&pcdev->notifier, &pcdev->asd); + if (err) { + fwnode_handle_put(pcdev->asd.match.fwnode); + goto exit_free_v4l2dev; + } + pcdev->notifier.ops = &pxa_camera_sensor_ops; if (!of_have_populated_dt()) @@ -2505,7 +2507,7 @@ static int pxa_camera_probe(struct platform_device *pdev) err = pxa_camera_init_videobuf2(pcdev); if (err) - goto exit_free_v4l2dev; + goto exit_notifier_cleanup; if (pcdev->mclk) { v4l2_clk_name_i2c(clk_name, sizeof(clk_name), @@ -2516,7 +2518,7 @@ static int pxa_camera_probe(struct platform_device *pdev) clk_name, NULL); if (IS_ERR(pcdev->mclk_clk)) { err = PTR_ERR(pcdev->mclk_clk); - goto exit_free_v4l2dev; + goto exit_notifier_cleanup; } } @@ -2527,6 +2529,8 @@ static int pxa_camera_probe(struct platform_device *pdev) return 0; exit_free_clk: v4l2_clk_unregister(pcdev->mclk_clk); +exit_notifier_cleanup: + v4l2_async_notifier_cleanup(&pcdev->notifier); exit_free_v4l2dev: v4l2_device_unregister(&pcdev->v4l2_dev); exit_deactivate: @@ -2550,6 +2554,7 @@ static int pxa_camera_remove(struct platform_device *pdev) dma_release_channel(pcdev->dma_chans[2]); v4l2_async_notifier_unregister(&pcdev->notifier); + v4l2_async_notifier_cleanup(&pcdev->notifier); if (pcdev->mclk_clk) { v4l2_clk_unregister(pcdev->mclk_clk); diff --git a/drivers/media/platform/qcom/camss/camss-video.c b/drivers/media/platform/qcom/camss/camss-video.c index c9bb0d023db4..58aebe7114cd 100644 --- a/drivers/media/platform/qcom/camss/camss-video.c +++ b/drivers/media/platform/qcom/camss/camss-video.c @@ -521,8 +521,8 @@ static int video_querycap(struct file *file, void *fh, { struct camss_video *video = video_drvdata(file); - strlcpy(cap->driver, "qcom-camss", sizeof(cap->driver)); - strlcpy(cap->card, "Qualcomm Camera Subsystem", sizeof(cap->card)); + strscpy(cap->driver, "qcom-camss", sizeof(cap->driver)); + strscpy(cap->card, "Qualcomm Camera Subsystem", sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", dev_name(video->camss->dev)); @@ -683,7 +683,7 @@ static int video_enum_input(struct file *file, void *fh, if (input->index > 0) return -EINVAL; - strlcpy(input->name, "camera", sizeof(input->name)); + strscpy(input->name, "camera", sizeof(input->name)); input->type = V4L2_INPUT_TYPE_CAMERA; return 0; @@ -919,7 +919,7 @@ int msm_video_register(struct camss_video *video, struct v4l2_device *v4l2_dev, vdev->vfl_dir = VFL_DIR_RX; vdev->queue = &video->vb2_q; vdev->lock = &video->lock; - strlcpy(vdev->name, name, sizeof(vdev->name)); + strscpy(vdev->name, name, sizeof(vdev->name)); ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1); if (ret < 0) { diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 669615fff6a0..45978db3b0be 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -462,61 +462,51 @@ static int camss_of_parse_endpoint_node(struct device *dev, * * Return number of "port" nodes found in "ports" node */ -static int camss_of_parse_ports(struct device *dev, - struct v4l2_async_notifier *notifier) +static int camss_of_parse_ports(struct camss *camss) { + struct device *dev = camss->dev; struct device_node *node = NULL; struct device_node *remote = NULL; - unsigned int size, i; - int ret; - - while ((node = of_graph_get_next_endpoint(dev->of_node, node))) - if (of_device_is_available(node)) - notifier->num_subdevs++; - - of_node_put(node); - size = sizeof(*notifier->subdevs) * notifier->num_subdevs; - notifier->subdevs = devm_kzalloc(dev, size, GFP_KERNEL); - if (!notifier->subdevs) { - dev_err(dev, "Failed to allocate memory\n"); - return -ENOMEM; - } + int ret, num_subdevs = 0; - i = 0; - while ((node = of_graph_get_next_endpoint(dev->of_node, node))) { + for_each_endpoint_of_node(dev->of_node, node) { struct camss_async_subdev *csd; + struct v4l2_async_subdev *asd; if (!of_device_is_available(node)) continue; - csd = devm_kzalloc(dev, sizeof(*csd), GFP_KERNEL); - if (!csd) { - of_node_put(node); - dev_err(dev, "Failed to allocate memory\n"); - return -ENOMEM; - } - - notifier->subdevs[i++] = &csd->asd; - - ret = camss_of_parse_endpoint_node(dev, node, csd); - if (ret < 0) { - of_node_put(node); - return ret; - } - remote = of_graph_get_remote_port_parent(node); if (!remote) { dev_err(dev, "Cannot get remote parent\n"); - of_node_put(node); - return -EINVAL; + ret = -EINVAL; + goto err_cleanup; } - csd->asd.match_type = V4L2_ASYNC_MATCH_FWNODE; - csd->asd.match.fwnode = of_fwnode_handle(remote); + asd = v4l2_async_notifier_add_fwnode_subdev( + &camss->notifier, of_fwnode_handle(remote), + sizeof(*csd)); + if (IS_ERR(asd)) { + ret = PTR_ERR(asd); + of_node_put(remote); + goto err_cleanup; + } + + csd = container_of(asd, struct camss_async_subdev, asd); + + ret = camss_of_parse_endpoint_node(dev, node, csd); + if (ret < 0) + goto err_cleanup; + + num_subdevs++; } - of_node_put(node); - return notifier->num_subdevs; + return num_subdevs; + +err_cleanup: + v4l2_async_notifier_cleanup(&camss->notifier); + of_node_put(node); + return ret; } /* @@ -823,7 +813,7 @@ static int camss_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct camss *camss; - int ret; + int num_subdevs, ret; camss = kzalloc(sizeof(*camss), GFP_KERNEL); if (!camss) @@ -863,20 +853,22 @@ static int camss_probe(struct platform_device *pdev) if (!camss->vfe) return -ENOMEM; - ret = camss_of_parse_ports(dev, &camss->notifier); - if (ret < 0) - return ret; + v4l2_async_notifier_init(&camss->notifier); + + num_subdevs = camss_of_parse_ports(camss); + if (num_subdevs < 0) + return num_subdevs; ret = camss_init_subdevices(camss); if (ret < 0) - return ret; + goto err_cleanup; ret = dma_set_mask_and_coherent(dev, 0xffffffff); if (ret) - return ret; + goto err_cleanup; camss->media_dev.dev = camss->dev; - strlcpy(camss->media_dev.model, "Qualcomm Camera Subsystem", + strscpy(camss->media_dev.model, "Qualcomm Camera Subsystem", sizeof(camss->media_dev.model)); camss->media_dev.ops = &camss_media_ops; media_device_init(&camss->media_dev); @@ -885,14 +877,14 @@ static int camss_probe(struct platform_device *pdev) ret = v4l2_device_register(camss->dev, &camss->v4l2_dev); if (ret < 0) { dev_err(dev, "Failed to register V4L2 device: %d\n", ret); - return ret; + goto err_cleanup; } ret = camss_register_entities(camss); if (ret < 0) goto err_register_entities; - if (camss->notifier.num_subdevs) { + if (num_subdevs) { camss->notifier.ops = &camss_subdev_notifier_ops; ret = v4l2_async_notifier_register(&camss->v4l2_dev, @@ -942,6 +934,8 @@ err_register_subdevs: camss_unregister_entities(camss); err_register_entities: v4l2_device_unregister(&camss->v4l2_dev); +err_cleanup: + v4l2_async_notifier_cleanup(&camss->notifier); return ret; } @@ -978,6 +972,7 @@ static int camss_remove(struct platform_device *pdev) msm_vfe_stop_streaming(&camss->vfe[i]); v4l2_async_notifier_unregister(&camss->notifier); + v4l2_async_notifier_cleanup(&camss->notifier); camss_unregister_entities(camss); if (atomic_read(&camss->ref_count) == 0) diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h index 418996d8dad8..57b269ca93fd 100644 --- a/drivers/media/platform/qcom/camss/camss.h +++ b/drivers/media/platform/qcom/camss/camss.h @@ -17,7 +17,6 @@ #include <media/v4l2-subdev.h> #include <media/media-device.h> #include <media/media-entity.h> -#include <linux/device.h> #include "camss-csid.h" #include "camss-csiphy.h" @@ -92,8 +91,8 @@ struct camss_camera_interface { }; struct camss_async_subdev { + struct v4l2_async_subdev asd; /* must be first */ struct camss_camera_interface interface; - struct v4l2_async_subdev asd; }; struct camss_clock { diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index cd3b96e6f24b..e436385bc5ab 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -472,7 +472,7 @@ static bool is_dynamic_bufmode(struct venus_inst *inst) caps = venus_caps_by_codec(core, inst->hfi_codec, inst->session_type); if (!caps) - return 0; + return false; return caps->cap_bufs_mode_dynamic; } diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index dfbbbf0f746f..189ec975c6bb 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -341,9 +341,9 @@ vdec_g_selection(struct file *file, void *fh, struct v4l2_selection *s) static int vdec_querycap(struct file *file, void *fh, struct v4l2_capability *cap) { - strlcpy(cap->driver, "qcom-venus", sizeof(cap->driver)); - strlcpy(cap->card, "Qualcomm Venus video decoder", sizeof(cap->card)); - strlcpy(cap->bus_info, "platform:qcom-venus", sizeof(cap->bus_info)); + strscpy(cap->driver, "qcom-venus", sizeof(cap->driver)); + strscpy(cap->card, "Qualcomm Venus video decoder", sizeof(cap->card)); + strscpy(cap->bus_info, "platform:qcom-venus", sizeof(cap->bus_info)); return 0; } @@ -888,8 +888,7 @@ static void vdec_buf_done(struct venus_inst *inst, unsigned int buf_type, unsigned int opb_sz = venus_helper_get_opb_size(inst); vb = &vbuf->vb2_buf; - vb->planes[0].bytesused = - max_t(unsigned int, opb_sz, bytesused); + vb2_set_plane_payload(vb, 0, bytesused ? : opb_sz); vb->planes[0].data_offset = data_offset; vb->timestamp = timestamp_us * NSEC_PER_USEC; vbuf->sequence = inst->sequence_cap++; @@ -1153,7 +1152,7 @@ static int vdec_probe(struct platform_device *pdev) if (!vdev) return -ENOMEM; - strlcpy(vdev->name, "qcom-venus-decoder", sizeof(vdev->name)); + strscpy(vdev->name, "qcom-venus-decoder", sizeof(vdev->name)); vdev->release = video_device_release; vdev->fops = &vdec_fops; vdev->ioctl_ops = &vdec_ioctl_ops; diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c index 41249d1443fa..ce85962b6adc 100644 --- a/drivers/media/platform/qcom/venus/venc.c +++ b/drivers/media/platform/qcom/venus/venc.c @@ -273,9 +273,9 @@ static int venc_v4l2_to_hfi(int id, int value) static int venc_querycap(struct file *file, void *fh, struct v4l2_capability *cap) { - strlcpy(cap->driver, "qcom-venus", sizeof(cap->driver)); - strlcpy(cap->card, "Qualcomm Venus video encoder", sizeof(cap->card)); - strlcpy(cap->bus_info, "platform:qcom-venus", sizeof(cap->bus_info)); + strscpy(cap->driver, "qcom-venus", sizeof(cap->driver)); + strscpy(cap->card, "Qualcomm Venus video encoder", sizeof(cap->card)); + strscpy(cap->bus_info, "platform:qcom-venus", sizeof(cap->bus_info)); return 0; } @@ -1257,7 +1257,7 @@ static int venc_probe(struct platform_device *pdev) if (!vdev) return -ENOMEM; - strlcpy(vdev->name, "qcom-venus-encoder", sizeof(vdev->name)); + strscpy(vdev->name, "qcom-venus-encoder", sizeof(vdev->name)); vdev->release = video_device_release; vdev->fops = &venc_fops; vdev->ioctl_ops = &venc_ioctl_ops; diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c index ce09799976ef..a3f135364474 100644 --- a/drivers/media/platform/rcar-vin/rcar-core.c +++ b/drivers/media/platform/rcar-vin/rcar-core.c @@ -170,7 +170,6 @@ static int rvin_group_link_notify(struct media_link *link, u32 flags, if (csi_id == -ENODEV) { struct v4l2_subdev *sd; - unsigned int i; /* * Make sure the source entity subdevice is registered as @@ -268,8 +267,8 @@ static int rvin_group_init(struct rvin_group *group, struct rvin_dev *vin) match = of_match_node(vin->dev->driver->of_match_table, vin->dev->of_node); - strlcpy(mdev->driver_name, KBUILD_MODNAME, sizeof(mdev->driver_name)); - strlcpy(mdev->model, match->compatible, sizeof(mdev->model)); + strscpy(mdev->driver_name, KBUILD_MODNAME, sizeof(mdev->driver_name)); + strscpy(mdev->model, match->compatible, sizeof(mdev->model)); snprintf(mdev->bus_info, sizeof(mdev->bus_info), "platform:%s", dev_name(mdev->dev)); @@ -611,6 +610,8 @@ static int rvin_parallel_init(struct rvin_dev *vin) { int ret; + v4l2_async_notifier_init(&vin->notifier); + ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port( vin->dev, &vin->notifier, sizeof(struct rvin_parallel_entity), 0, rvin_parallel_parse_v4l2); @@ -803,6 +804,8 @@ static int rvin_mc_parse_of_graph(struct rvin_dev *vin) return 0; } + v4l2_async_notifier_init(&vin->group->notifier); + /* * Have all VIN's look for CSI-2 subdevices. Some subdevices will * overlap but the parser function can handle it, so each subdevice @@ -824,7 +827,7 @@ static int rvin_mc_parse_of_graph(struct rvin_dev *vin) mutex_unlock(&vin->group->lock); - if (!vin->group->notifier.num_subdevs) + if (list_empty(&vin->group->notifier.asd_list)) return 0; vin->group->notifier.ops = &rvin_group_notify_ops; diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c index dc5ae8025832..b0044a08e71e 100644 --- a/drivers/media/platform/rcar-vin/rcar-csi2.c +++ b/drivers/media/platform/rcar-vin/rcar-csi2.c @@ -714,7 +714,7 @@ static int rcsi2_parse_v4l2(struct rcar_csi2 *priv, if (vep->base.port || vep->base.id) return -ENOTCONN; - if (vep->bus_type != V4L2_MBUS_CSI2) { + if (vep->bus_type != V4L2_MBUS_CSI2_DPHY) { dev_err(priv->dev, "Unsupported bus: %u\n", vep->bus_type); return -EINVAL; } @@ -743,7 +743,7 @@ static int rcsi2_parse_v4l2(struct rcar_csi2 *priv, static int rcsi2_parse_dt(struct rcar_csi2 *priv) { struct device_node *ep; - struct v4l2_fwnode_endpoint v4l2_ep; + struct v4l2_fwnode_endpoint v4l2_ep = { .bus_type = 0 }; int ret; ep = of_graph_get_endpoint_by_regs(priv->dev->of_node, 0, 0); @@ -771,21 +771,25 @@ static int rcsi2_parse_dt(struct rcar_csi2 *priv) of_node_put(ep); - priv->notifier.subdevs = devm_kzalloc(priv->dev, - sizeof(*priv->notifier.subdevs), - GFP_KERNEL); - if (!priv->notifier.subdevs) - return -ENOMEM; + v4l2_async_notifier_init(&priv->notifier); + + ret = v4l2_async_notifier_add_subdev(&priv->notifier, &priv->asd); + if (ret) { + fwnode_handle_put(priv->asd.match.fwnode); + return ret; + } - priv->notifier.num_subdevs = 1; - priv->notifier.subdevs[0] = &priv->asd; priv->notifier.ops = &rcar_csi2_notify_ops; dev_dbg(priv->dev, "Found '%pOF'\n", to_of_node(priv->asd.match.fwnode)); - return v4l2_async_subdev_notifier_register(&priv->subdev, - &priv->notifier); + ret = v4l2_async_subdev_notifier_register(&priv->subdev, + &priv->notifier); + if (ret) + v4l2_async_notifier_cleanup(&priv->notifier); + + return ret; } /* ----------------------------------------------------------------------------- diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c b/drivers/media/platform/rcar-vin/rcar-v4l2.c index 5a54779cfc27..dc77682b4785 100644 --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c @@ -238,8 +238,8 @@ static int rvin_querycap(struct file *file, void *priv, { struct rvin_dev *vin = video_drvdata(file); - strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver)); - strlcpy(cap->card, "R_Car_VIN", sizeof(cap->card)); + strscpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver)); + strscpy(cap->card, "R_Car_VIN", sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", dev_name(vin->dev)); return 0; @@ -440,7 +440,7 @@ static int rvin_enum_input(struct file *file, void *priv, i->std = vin->vdev.tvnorms; } - strlcpy(i->name, "Camera", sizeof(i->name)); + strscpy(i->name, "Camera", sizeof(i->name)); return 0; } @@ -714,7 +714,7 @@ static int rvin_mc_enum_input(struct file *file, void *priv, return -EINVAL; i->type = V4L2_INPUT_TYPE_CAMERA; - strlcpy(i->name, "Camera", sizeof(i->name)); + strscpy(i->name, "Camera", sizeof(i->name)); return 0; } diff --git a/drivers/media/platform/rcar_drif.c b/drivers/media/platform/rcar_drif.c index 81413ab52475..8483dc36715d 100644 --- a/drivers/media/platform/rcar_drif.c +++ b/drivers/media/platform/rcar_drif.c @@ -870,8 +870,8 @@ static int rcar_drif_querycap(struct file *file, void *fh, { struct rcar_drif_sdr *sdr = video_drvdata(file); - strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver)); - strlcpy(cap->card, sdr->vdev->name, sizeof(cap->card)); + strscpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver)); + strscpy(cap->card, sdr->vdev->name, sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", sdr->vdev->name); @@ -1213,18 +1213,15 @@ static int rcar_drif_parse_subdevs(struct rcar_drif_sdr *sdr) { struct v4l2_async_notifier *notifier = &sdr->notifier; struct fwnode_handle *fwnode, *ep; + int ret; - notifier->subdevs = devm_kzalloc(sdr->dev, sizeof(*notifier->subdevs), - GFP_KERNEL); - if (!notifier->subdevs) - return -ENOMEM; + v4l2_async_notifier_init(notifier); ep = fwnode_graph_get_next_endpoint(of_fwnode_handle(sdr->dev->of_node), NULL); if (!ep) return 0; - notifier->subdevs[notifier->num_subdevs] = &sdr->ep.asd; fwnode = fwnode_graph_get_remote_port_parent(ep); if (!fwnode) { dev_warn(sdr->dev, "bad remote port parent\n"); @@ -1234,7 +1231,11 @@ static int rcar_drif_parse_subdevs(struct rcar_drif_sdr *sdr) sdr->ep.asd.match.fwnode = fwnode; sdr->ep.asd.match_type = V4L2_ASYNC_MATCH_FWNODE; - notifier->num_subdevs++; + ret = v4l2_async_notifier_add_subdev(notifier, &sdr->ep.asd); + if (ret) { + fwnode_handle_put(fwnode); + return ret; + } /* Get the endpoint properties */ rcar_drif_get_ep_properties(sdr, ep); @@ -1356,11 +1357,13 @@ static int rcar_drif_sdr_probe(struct rcar_drif_sdr *sdr) ret = v4l2_async_notifier_register(&sdr->v4l2_dev, &sdr->notifier); if (ret < 0) { dev_err(sdr->dev, "failed: notifier register ret %d\n", ret); - goto error; + goto cleanup; } return ret; +cleanup: + v4l2_async_notifier_cleanup(&sdr->notifier); error: v4l2_device_unregister(&sdr->v4l2_dev); @@ -1371,6 +1374,7 @@ error: static void rcar_drif_sdr_remove(struct rcar_drif_sdr *sdr) { v4l2_async_notifier_unregister(&sdr->notifier); + v4l2_async_notifier_cleanup(&sdr->notifier); v4l2_device_unregister(&sdr->v4l2_dev); } diff --git a/drivers/media/platform/rcar_fdp1.c b/drivers/media/platform/rcar_fdp1.c index 2a15b7cca338..6bda1eee9170 100644 --- a/drivers/media/platform/rcar_fdp1.c +++ b/drivers/media/platform/rcar_fdp1.c @@ -1359,8 +1359,8 @@ static void device_frame_end(struct fdp1_dev *fdp1, static int fdp1_vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - strlcpy(cap->driver, DRIVER_NAME, sizeof(cap->driver)); - strlcpy(cap->card, DRIVER_NAME, sizeof(cap->card)); + strscpy(cap->driver, DRIVER_NAME, sizeof(cap->driver)); + strscpy(cap->card, DRIVER_NAME, sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", DRIVER_NAME); return 0; @@ -2339,7 +2339,7 @@ static int fdp1_probe(struct platform_device *pdev) vfd->lock = &fdp1->dev_mutex; vfd->v4l2_dev = &fdp1->v4l2_dev; video_set_drvdata(vfd, fdp1); - strlcpy(vfd->name, fdp1_videodev.name, sizeof(vfd->name)); + strscpy(vfd->name, fdp1_videodev.name, sizeof(vfd->name)); ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); if (ret) { diff --git a/drivers/media/platform/rcar_jpu.c b/drivers/media/platform/rcar_jpu.c index e5c882423f57..1dfd2eb65920 100644 --- a/drivers/media/platform/rcar_jpu.c +++ b/drivers/media/platform/rcar_jpu.c @@ -664,11 +664,11 @@ static int jpu_querycap(struct file *file, void *priv, struct jpu_ctx *ctx = fh_to_ctx(priv); if (ctx->encoder) - strlcpy(cap->card, DRV_NAME " encoder", sizeof(cap->card)); + strscpy(cap->card, DRV_NAME " encoder", sizeof(cap->card)); else - strlcpy(cap->card, DRV_NAME " decoder", sizeof(cap->card)); + strscpy(cap->card, DRV_NAME " decoder", sizeof(cap->card)); - strlcpy(cap->driver, DRV_NAME, sizeof(cap->driver)); + strscpy(cap->driver, DRV_NAME, sizeof(cap->driver)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", dev_name(ctx->jpu->dev)); cap->device_caps |= V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE; @@ -1654,7 +1654,7 @@ static int jpu_probe(struct platform_device *pdev) for (i = 0; i < JPU_MAX_QUALITY; i++) jpu_generate_hdr(i, (unsigned char *)jpeg_hdrs[i]); - strlcpy(jpu->vfd_encoder.name, DRV_NAME, sizeof(jpu->vfd_encoder.name)); + strscpy(jpu->vfd_encoder.name, DRV_NAME, sizeof(jpu->vfd_encoder.name)); jpu->vfd_encoder.fops = &jpu_fops; jpu->vfd_encoder.ioctl_ops = &jpu_ioctl_ops; jpu->vfd_encoder.minor = -1; @@ -1671,7 +1671,7 @@ static int jpu_probe(struct platform_device *pdev) video_set_drvdata(&jpu->vfd_encoder, jpu); - strlcpy(jpu->vfd_decoder.name, DRV_NAME, sizeof(jpu->vfd_decoder.name)); + strscpy(jpu->vfd_decoder.name, DRV_NAME, sizeof(jpu->vfd_decoder.name)); jpu->vfd_decoder.fops = &jpu_fops; jpu->vfd_decoder.ioctl_ops = &jpu_ioctl_ops; jpu->vfd_decoder.minor = -1; diff --git a/drivers/media/platform/renesas-ceu.c b/drivers/media/platform/renesas-ceu.c index ad782901cd7a..150196f7cf96 100644 --- a/drivers/media/platform/renesas-ceu.c +++ b/drivers/media/platform/renesas-ceu.c @@ -189,8 +189,6 @@ struct ceu_device { /* async subdev notification helpers */ struct v4l2_async_notifier notifier; - /* pointers to "struct ceu_subdevice -> asd" */ - struct v4l2_async_subdev **asds; /* vb2 queue, capture buffer list and active buffer pointer */ struct vb2_queue vb2_vq; @@ -1137,8 +1135,8 @@ static int ceu_querycap(struct file *file, void *priv, { struct ceu_device *ceudev = video_drvdata(file); - strlcpy(cap->card, "Renesas CEU", sizeof(cap->card)); - strlcpy(cap->driver, DRIVER_NAME, sizeof(cap->driver)); + strscpy(cap->card, "Renesas CEU", sizeof(cap->card)); + strscpy(cap->driver, DRIVER_NAME, sizeof(cap->driver)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:renesas-ceu-%s", dev_name(ceudev->dev)); @@ -1440,7 +1438,7 @@ static int ceu_notify_complete(struct v4l2_async_notifier *notifier) return ret; /* Register the video device. */ - strlcpy(vdev->name, DRIVER_NAME, sizeof(vdev->name)); + strscpy(vdev->name, DRIVER_NAME, sizeof(vdev->name)); vdev->v4l2_dev = v4l2_dev; vdev->lock = &ceudev->mlock; vdev->queue = &ceudev->vb2_vq; @@ -1482,15 +1480,6 @@ static int ceu_init_async_subdevs(struct ceu_device *ceudev, unsigned int n_sd) if (!ceudev->subdevs) return -ENOMEM; - /* - * Reserve memory for 'n_sd' pointers to async_subdevices. - * ceudev->asds members will point to &ceu_subdev.asd - */ - ceudev->asds = devm_kcalloc(ceudev->dev, n_sd, - sizeof(*ceudev->asds), GFP_KERNEL); - if (!ceudev->asds) - return -ENOMEM; - ceudev->sd = NULL; ceudev->sd_index = 0; ceudev->num_sd = 0; @@ -1518,6 +1507,7 @@ static int ceu_parse_platform_data(struct ceu_device *ceudev, return ret; for (i = 0; i < pdata->num_subdevs; i++) { + /* Setup the ceu subdevice and the async subdevice. */ async_sd = &pdata->subdevs[i]; ceu_sd = &ceudev->subdevs[i]; @@ -1529,7 +1519,12 @@ static int ceu_parse_platform_data(struct ceu_device *ceudev, ceu_sd->asd.match.i2c.adapter_id = async_sd->i2c_adapter_id; ceu_sd->asd.match.i2c.address = async_sd->i2c_address; - ceudev->asds[i] = &ceu_sd->asd; + ret = v4l2_async_notifier_add_subdev(&ceudev->notifier, + &ceu_sd->asd); + if (ret) { + v4l2_async_notifier_cleanup(&ceudev->notifier); + return ret; + } } return pdata->num_subdevs; @@ -1541,9 +1536,8 @@ static int ceu_parse_platform_data(struct ceu_device *ceudev, static int ceu_parse_dt(struct ceu_device *ceudev) { struct device_node *of = ceudev->dev->of_node; - struct v4l2_fwnode_endpoint fw_ep; + struct device_node *ep, *remote; struct ceu_subdev *ceu_sd; - struct device_node *ep; unsigned int i; int num_ep; int ret; @@ -1557,45 +1551,55 @@ static int ceu_parse_dt(struct ceu_device *ceudev) return ret; for (i = 0; i < num_ep; i++) { + struct v4l2_fwnode_endpoint fw_ep = { + .bus_type = V4L2_MBUS_PARALLEL, + .bus = { + .parallel = { + .flags = V4L2_MBUS_HSYNC_ACTIVE_HIGH | + V4L2_MBUS_VSYNC_ACTIVE_HIGH, + .bus_width = 8, + }, + }, + }; + ep = of_graph_get_endpoint_by_regs(of, 0, i); if (!ep) { dev_err(ceudev->dev, "No subdevice connected on endpoint %u.\n", i); ret = -ENODEV; - goto error_put_node; + goto error_cleanup; } ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &fw_ep); if (ret) { dev_err(ceudev->dev, - "Unable to parse endpoint #%u.\n", i); - goto error_put_node; - } - - if (fw_ep.bus_type != V4L2_MBUS_PARALLEL) { - dev_err(ceudev->dev, - "Only parallel input supported.\n"); - ret = -EINVAL; - goto error_put_node; + "Unable to parse endpoint #%u: %d.\n", i, ret); + goto error_cleanup; } /* Setup the ceu subdevice and the async subdevice. */ ceu_sd = &ceudev->subdevs[i]; INIT_LIST_HEAD(&ceu_sd->asd.list); + remote = of_graph_get_remote_port_parent(ep); ceu_sd->mbus_flags = fw_ep.bus.parallel.flags; ceu_sd->asd.match_type = V4L2_ASYNC_MATCH_FWNODE; - ceu_sd->asd.match.fwnode = - fwnode_graph_get_remote_port_parent( - of_fwnode_handle(ep)); + ceu_sd->asd.match.fwnode = of_fwnode_handle(remote); + + ret = v4l2_async_notifier_add_subdev(&ceudev->notifier, + &ceu_sd->asd); + if (ret) { + of_node_put(remote); + goto error_cleanup; + } - ceudev->asds[i] = &ceu_sd->asd; of_node_put(ep); } return num_ep; -error_put_node: +error_cleanup: + v4l2_async_notifier_cleanup(&ceudev->notifier); of_node_put(ep); return ret; } @@ -1674,6 +1678,8 @@ static int ceu_probe(struct platform_device *pdev) if (ret) goto error_pm_disable; + v4l2_async_notifier_init(&ceudev->notifier); + if (IS_ENABLED(CONFIG_OF) && dev->of_node) { ceu_data = of_match_device(ceu_of_match, dev)->data; num_subdevs = ceu_parse_dt(ceudev); @@ -1693,18 +1699,18 @@ static int ceu_probe(struct platform_device *pdev) ceudev->irq_mask = ceu_data->irq_mask; ceudev->notifier.v4l2_dev = &ceudev->v4l2_dev; - ceudev->notifier.subdevs = ceudev->asds; - ceudev->notifier.num_subdevs = num_subdevs; ceudev->notifier.ops = &ceu_notify_ops; ret = v4l2_async_notifier_register(&ceudev->v4l2_dev, &ceudev->notifier); if (ret) - goto error_v4l2_unregister; + goto error_cleanup; dev_info(dev, "Renesas Capture Engine Unit %s\n", dev_name(dev)); return 0; +error_cleanup: + v4l2_async_notifier_cleanup(&ceudev->notifier); error_v4l2_unregister: v4l2_device_unregister(&ceudev->v4l2_dev); error_pm_disable: @@ -1723,6 +1729,8 @@ static int ceu_remove(struct platform_device *pdev) v4l2_async_notifier_unregister(&ceudev->notifier); + v4l2_async_notifier_cleanup(&ceudev->notifier); + v4l2_device_unregister(&ceudev->v4l2_dev); video_unregister_device(&ceudev->vdev); diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c index ab5a6f95044a..9cc9db083870 100644 --- a/drivers/media/platform/rockchip/rga/rga.c +++ b/drivers/media/platform/rockchip/rga/rga.c @@ -447,9 +447,9 @@ static const struct v4l2_file_operations rga_fops = { static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - strlcpy(cap->driver, RGA_NAME, sizeof(cap->driver)); - strlcpy(cap->card, "rockchip-rga", sizeof(cap->card)); - strlcpy(cap->bus_info, "platform:rga", sizeof(cap->bus_info)); + strscpy(cap->driver, RGA_NAME, sizeof(cap->driver)); + strscpy(cap->card, "rockchip-rga", sizeof(cap->card)); + strscpy(cap->bus_info, "platform:rga", sizeof(cap->bus_info)); return 0; } diff --git a/drivers/media/platform/s3c-camif/camif-capture.c b/drivers/media/platform/s3c-camif/camif-capture.c index c02dce8b4c6c..23b008d1a47b 100644 --- a/drivers/media/platform/s3c-camif/camif-capture.c +++ b/drivers/media/platform/s3c-camif/camif-capture.c @@ -640,8 +640,8 @@ static int s3c_camif_vidioc_querycap(struct file *file, void *priv, { struct camif_vp *vp = video_drvdata(file); - strlcpy(cap->driver, S3C_CAMIF_DRIVER_NAME, sizeof(cap->driver)); - strlcpy(cap->card, S3C_CAMIF_DRIVER_NAME, sizeof(cap->card)); + strscpy(cap->driver, S3C_CAMIF_DRIVER_NAME, sizeof(cap->driver)); + strscpy(cap->card, S3C_CAMIF_DRIVER_NAME, sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s.%d", dev_name(vp->camif->dev), vp->id); @@ -661,7 +661,7 @@ static int s3c_camif_vidioc_enum_input(struct file *file, void *priv, return -EINVAL; input->type = V4L2_INPUT_TYPE_CAMERA; - strlcpy(input->name, sensor->name, sizeof(input->name)); + strscpy(input->name, sensor->name, sizeof(input->name)); return 0; } @@ -688,7 +688,7 @@ static int s3c_camif_vidioc_enum_fmt(struct file *file, void *priv, if (!fmt) return -EINVAL; - strlcpy(f->description, fmt->name, sizeof(f->description)); + strscpy(f->description, fmt->name, sizeof(f->description)); f->pixelformat = fmt->fourcc; pr_debug("fmt(%d): %s\n", f->index, f->description); @@ -1555,7 +1555,7 @@ int s3c_camif_create_subdev(struct camif_dev *camif) v4l2_subdev_init(sd, &s3c_camif_subdev_ops); sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - strlcpy(sd->name, "S3C-CAMIF", sizeof(sd->name)); + strscpy(sd->name, "S3C-CAMIF", sizeof(sd->name)); camif->pads[CAMIF_SD_PAD_SINK].flags = MEDIA_PAD_FL_SINK; camif->pads[CAMIF_SD_PAD_SOURCE_C].flags = MEDIA_PAD_FL_SOURCE; diff --git a/drivers/media/platform/s3c-camif/camif-core.c b/drivers/media/platform/s3c-camif/camif-core.c index 79bc0ef6bb41..31759f16458e 100644 --- a/drivers/media/platform/s3c-camif/camif-core.c +++ b/drivers/media/platform/s3c-camif/camif-core.c @@ -316,12 +316,12 @@ static int camif_media_dev_init(struct camif_dev *camif) memset(md, 0, sizeof(*md)); snprintf(md->model, sizeof(md->model), "SAMSUNG S3C%s CAMIF", ip_rev == S3C6410_CAMIF_IP_REV ? "6410" : "244X"); - strlcpy(md->bus_info, "platform", sizeof(md->bus_info)); + strscpy(md->bus_info, "platform", sizeof(md->bus_info)); md->hw_revision = ip_rev; md->dev = camif->dev; - strlcpy(v4l2_dev->name, "s3c-camif", sizeof(v4l2_dev->name)); + strscpy(v4l2_dev->name, "s3c-camif", sizeof(v4l2_dev->name)); v4l2_dev->mdev = md; media_device_init(md); diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index 04fd2e0493c0..3f9000b70385 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -1276,14 +1276,14 @@ static int s5p_jpeg_querycap(struct file *file, void *priv, struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv); if (ctx->mode == S5P_JPEG_ENCODE) { - strlcpy(cap->driver, S5P_JPEG_M2M_NAME, + strscpy(cap->driver, S5P_JPEG_M2M_NAME, sizeof(cap->driver)); - strlcpy(cap->card, S5P_JPEG_M2M_NAME " encoder", + strscpy(cap->card, S5P_JPEG_M2M_NAME " encoder", sizeof(cap->card)); } else { - strlcpy(cap->driver, S5P_JPEG_M2M_NAME, + strscpy(cap->driver, S5P_JPEG_M2M_NAME, sizeof(cap->driver)); - strlcpy(cap->card, S5P_JPEG_M2M_NAME " decoder", + strscpy(cap->card, S5P_JPEG_M2M_NAME " decoder", sizeof(cap->card)); } snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", @@ -1314,7 +1314,7 @@ static int enum_fmt(struct s5p_jpeg_fmt *sjpeg_formats, int n, if (i >= n) return -EINVAL; - strlcpy(f->description, sjpeg_formats[i].name, sizeof(f->description)); + strscpy(f->description, sjpeg_formats[i].name, sizeof(f->description)); f->pixelformat = sjpeg_formats[i].fourcc; return 0; diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c index 6a3cc4f86c5d..670ca869babb 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c @@ -271,8 +271,8 @@ static int vidioc_querycap(struct file *file, void *priv, { struct s5p_mfc_dev *dev = video_drvdata(file); - strlcpy(cap->driver, S5P_MFC_NAME, sizeof(cap->driver)); - strlcpy(cap->card, dev->vfd_dec->name, sizeof(cap->card)); + strscpy(cap->driver, S5P_MFC_NAME, sizeof(cap->driver)); + strscpy(cap->card, dev->vfd_dec->name, sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", dev_name(&dev->plat_dev->dev)); /* @@ -308,7 +308,7 @@ static int vidioc_enum_fmt(struct file *file, struct v4l2_fmtdesc *f, if (i == ARRAY_SIZE(formats)) return -EINVAL; fmt = &formats[i]; - strlcpy(f->description, fmt->name, sizeof(f->description)); + strscpy(f->description, fmt->name, sizeof(f->description)); f->pixelformat = fmt->fourcc; return 0; } diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c index 3ad4f5073002..7037d48bdc2c 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c @@ -1313,8 +1313,8 @@ static int vidioc_querycap(struct file *file, void *priv, { struct s5p_mfc_dev *dev = video_drvdata(file); - strlcpy(cap->driver, S5P_MFC_NAME, sizeof(cap->driver)); - strlcpy(cap->card, dev->vfd_enc->name, sizeof(cap->card)); + strscpy(cap->driver, S5P_MFC_NAME, sizeof(cap->driver)); + strscpy(cap->card, dev->vfd_enc->name, sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", dev_name(&dev->plat_dev->dev)); /* @@ -1344,7 +1344,7 @@ static int vidioc_enum_fmt(struct file *file, struct v4l2_fmtdesc *f, if (j == f->index) { fmt = &formats[i]; - strlcpy(f->description, fmt->name, + strscpy(f->description, fmt->name, sizeof(f->description)); f->pixelformat = fmt->fourcc; return 0; diff --git a/drivers/media/platform/sh_veu.c b/drivers/media/platform/sh_veu.c index 1d274c64de09..09ae64a0004c 100644 --- a/drivers/media/platform/sh_veu.c +++ b/drivers/media/platform/sh_veu.c @@ -345,9 +345,9 @@ static int sh_veu_context_init(struct sh_veu_dev *veu) static int sh_veu_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - strlcpy(cap->driver, "sh-veu", sizeof(cap->driver)); - strlcpy(cap->card, "sh-mobile VEU", sizeof(cap->card)); - strlcpy(cap->bus_info, "platform:sh-veu", sizeof(cap->bus_info)); + strscpy(cap->driver, "sh-veu", sizeof(cap->driver)); + strscpy(cap->card, "sh-mobile VEU", sizeof(cap->card)); + strscpy(cap->bus_info, "platform:sh-veu", sizeof(cap->bus_info)); cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; @@ -359,7 +359,8 @@ static int sh_veu_enum_fmt(struct v4l2_fmtdesc *f, const int *fmt, int fmt_num) if (f->index >= fmt_num) return -EINVAL; - strlcpy(f->description, sh_veu_fmt[fmt[f->index]].name, sizeof(f->description)); + strscpy(f->description, sh_veu_fmt[fmt[f->index]].name, + sizeof(f->description)); f->pixelformat = sh_veu_fmt[fmt[f->index]].fourcc; return 0; } diff --git a/drivers/media/platform/sh_vou.c b/drivers/media/platform/sh_vou.c index 6135e13e24d4..cee58b125548 100644 --- a/drivers/media/platform/sh_vou.c +++ b/drivers/media/platform/sh_vou.c @@ -378,9 +378,9 @@ static int sh_vou_querycap(struct file *file, void *priv, dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); - strlcpy(cap->card, "SuperH VOU", sizeof(cap->card)); - strlcpy(cap->driver, "sh-vou", sizeof(cap->driver)); - strlcpy(cap->bus_info, "platform:sh-vou", sizeof(cap->bus_info)); + strscpy(cap->card, "SuperH VOU", sizeof(cap->card)); + strscpy(cap->driver, "sh-vou", sizeof(cap->driver)); + strscpy(cap->bus_info, "platform:sh-vou", sizeof(cap->bus_info)); cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; @@ -399,7 +399,7 @@ static int sh_vou_enum_fmt_vid_out(struct file *file, void *priv, dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__); fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - strlcpy(fmt->description, vou_fmt[fmt->index].desc, + strscpy(fmt->description, vou_fmt[fmt->index].desc, sizeof(fmt->description)); fmt->pixelformat = vou_fmt[fmt->index].pfmt; @@ -790,7 +790,7 @@ static int sh_vou_enum_output(struct file *file, void *fh, if (a->index) return -EINVAL; - strlcpy(a->name, "Video Out", sizeof(a->name)); + strscpy(a->name, "Video Out", sizeof(a->name)); a->type = V4L2_OUTPUT_TYPE_ANALOG; a->std = vou_dev->vdev.tvnorms; return 0; diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c index 0a2c0daaffef..6803f744e307 100644 --- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c +++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c @@ -1564,9 +1564,9 @@ static __poll_t sh_mobile_ceu_poll(struct file *file, poll_table *pt) static int sh_mobile_ceu_querycap(struct soc_camera_host *ici, struct v4l2_capability *cap) { - strlcpy(cap->card, "SuperH_Mobile_CEU", sizeof(cap->card)); - strlcpy(cap->driver, "sh_mobile_ceu", sizeof(cap->driver)); - strlcpy(cap->bus_info, "platform:sh_mobile_ceu", sizeof(cap->bus_info)); + strscpy(cap->card, "SuperH_Mobile_CEU", sizeof(cap->card)); + strscpy(cap->driver, "sh_mobile_ceu", sizeof(cap->driver)); + strscpy(cap->bus_info, "platform:sh_mobile_ceu", sizeof(cap->bus_info)); cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c index 66d613629167..0a70fb67c401 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c @@ -312,7 +312,7 @@ static int soc_camera_enum_input(struct file *file, void *priv, /* default is camera */ inp->type = V4L2_INPUT_TYPE_CAMERA; inp->std = icd->vdev->tvnorms; - strcpy(inp->name, "Camera"); + strscpy(inp->name, "Camera", sizeof(inp->name)); return 0; } @@ -874,7 +874,7 @@ static int soc_camera_enum_fmt_vid_cap(struct file *file, void *priv, format = icd->user_formats[f->index].host_fmt; if (format->name) - strlcpy(f->description, format->name, sizeof(f->description)); + strscpy(f->description, format->name, sizeof(f->description)); f->pixelformat = format->fourcc; return 0; } @@ -910,7 +910,7 @@ static int soc_camera_querycap(struct file *file, void *priv, WARN_ON(priv != file->private_data); - strlcpy(cap->driver, ici->drv_name, sizeof(cap->driver)); + strscpy(cap->driver, ici->drv_name, sizeof(cap->driver)); return ici->ops->querycap(ici, cap); } @@ -1442,8 +1442,14 @@ static int scan_async_group(struct soc_camera_host *ici, goto eaddpdev; } - sasc->notifier.subdevs = asd; - sasc->notifier.num_subdevs = size; + v4l2_async_notifier_init(&sasc->notifier); + + for (i = 0; i < size; i++) { + ret = v4l2_async_notifier_add_subdev(&sasc->notifier, asd[i]); + if (ret) + goto eaddasd; + } + sasc->notifier.ops = &soc_camera_async_ops; icd->sasc = sasc; @@ -1466,6 +1472,8 @@ static int scan_async_group(struct soc_camera_host *ici, v4l2_clk_unregister(icd->clk); eclkreg: icd->clk = NULL; +eaddasd: + v4l2_async_notifier_cleanup(&sasc->notifier); platform_device_del(sasc->pdev); eaddpdev: platform_device_put(sasc->pdev); @@ -1540,8 +1548,14 @@ static int soc_of_bind(struct soc_camera_host *ici, goto eaddpdev; } - sasc->notifier.subdevs = &info->subdev; - sasc->notifier.num_subdevs = 1; + v4l2_async_notifier_init(&sasc->notifier); + + ret = v4l2_async_notifier_add_subdev(&sasc->notifier, info->subdev); + if (ret) { + of_node_put(remote); + goto eaddasd; + } + sasc->notifier.ops = &soc_camera_async_ops; icd->sasc = sasc; @@ -1568,6 +1582,8 @@ static int soc_of_bind(struct soc_camera_host *ici, v4l2_clk_unregister(icd->clk); eclkreg: icd->clk = NULL; +eaddasd: + v4l2_async_notifier_cleanup(&sasc->notifier); platform_device_del(sasc->pdev); eaddpdev: platform_device_put(sasc->pdev); @@ -1582,7 +1598,7 @@ static void scan_of_host(struct soc_camera_host *ici) { struct device *dev = ici->v4l2_dev.dev; struct device_node *np = dev->of_node; - struct device_node *epn = NULL, *ren; + struct device_node *epn = NULL, *rem; unsigned int i; for (i = 0; ; i++) { @@ -1590,17 +1606,15 @@ static void scan_of_host(struct soc_camera_host *ici) if (!epn) break; - ren = of_graph_get_remote_port(epn); - if (!ren) { + rem = of_graph_get_remote_port_parent(epn); + if (!rem) { dev_notice(dev, "no remote for %pOF\n", epn); continue; } /* so we now have a remote node to connect */ if (!i) - soc_of_bind(ici, epn, ren->parent); - - of_node_put(ren); + soc_of_bind(ici, epn, rem); if (i) { dev_err(dev, "multiple subdevices aren't supported yet!\n"); @@ -1926,6 +1940,7 @@ void soc_camera_host_unregister(struct soc_camera_host *ici) list_for_each_entry(sasc, ¬ifiers, list) { /* Must call unlocked to avoid AB-BA dead-lock */ v4l2_async_notifier_unregister(&sasc->notifier); + v4l2_async_notifier_cleanup(&sasc->notifier); put_device(&sasc->pdev->dev); } @@ -2026,7 +2041,7 @@ static int video_dev_create(struct soc_camera_device *icd) if (!vdev) return -ENOMEM; - strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name)); + strscpy(vdev->name, ici->drv_name, sizeof(vdev->name)); vdev->v4l2_dev = &ici->v4l2_dev; vdev->fops = &soc_camera_fops; diff --git a/drivers/media/platform/soc_camera/soc_camera_platform.c b/drivers/media/platform/soc_camera/soc_camera_platform.c index 6745a6e3f464..79fbe1fea95f 100644 --- a/drivers/media/platform/soc_camera/soc_camera_platform.c +++ b/drivers/media/platform/soc_camera/soc_camera_platform.c @@ -156,7 +156,7 @@ static int soc_camera_platform_probe(struct platform_device *pdev) v4l2_subdev_init(&priv->subdev, &platform_subdev_ops); v4l2_set_subdevdata(&priv->subdev, p); - strlcpy(priv->subdev.name, dev_name(&pdev->dev), + strscpy(priv->subdev.name, dev_name(&pdev->dev), sizeof(priv->subdev.name)); return v4l2_device_register_subdev(&ici->v4l2_dev, &priv->subdev); diff --git a/drivers/media/platform/soc_camera/soc_mediabus.c b/drivers/media/platform/soc_camera/soc_mediabus.c index 0ad4b28266e4..be74008ec0ca 100644 --- a/drivers/media/platform/soc_camera/soc_mediabus.c +++ b/drivers/media/platform/soc_camera/soc_mediabus.c @@ -503,7 +503,7 @@ unsigned int soc_mbus_config_compatible(const struct v4l2_mbus_config *cfg, mode = common_flags & (V4L2_MBUS_MASTER | V4L2_MBUS_SLAVE); return (!hsync || !vsync || !pclk || !data || !mode) ? 0 : common_flags; - case V4L2_MBUS_CSI2: + case V4L2_MBUS_CSI2_DPHY: mipi_lanes = common_flags & V4L2_MBUS_CSI2_LANES; mipi_clock = common_flags & (V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK | V4L2_MBUS_CSI2_CONTINUOUS_CLOCK); diff --git a/drivers/media/platform/soc_camera/soc_scale_crop.c b/drivers/media/platform/soc_camera/soc_scale_crop.c index 6164102e6f9f..8d25ca0490f7 100644 --- a/drivers/media/platform/soc_camera/soc_scale_crop.c +++ b/drivers/media/platform/soc_camera/soc_scale_crop.c @@ -52,7 +52,7 @@ int soc_camera_client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect) return ret; } - sdsel.target = V4L2_SEL_TGT_CROP_DEFAULT; + sdsel.target = V4L2_SEL_TGT_CROP_BOUNDS; ret = v4l2_subdev_call(sd, pad, get_selection, NULL, &sdsel); if (!ret) *rect = sdsel.r; diff --git a/drivers/media/platform/sti/bdisp/bdisp-v4l2.c b/drivers/media/platform/sti/bdisp/bdisp-v4l2.c index 66b64096f5de..79f7db1a9d18 100644 --- a/drivers/media/platform/sti/bdisp/bdisp-v4l2.c +++ b/drivers/media/platform/sti/bdisp/bdisp-v4l2.c @@ -688,8 +688,8 @@ static int bdisp_querycap(struct file *file, void *fh, struct bdisp_ctx *ctx = fh_to_ctx(fh); struct bdisp_dev *bdisp = ctx->bdisp_dev; - strlcpy(cap->driver, bdisp->pdev->name, sizeof(cap->driver)); - strlcpy(cap->card, bdisp->pdev->name, sizeof(cap->card)); + strscpy(cap->driver, bdisp->pdev->name, sizeof(cap->driver)); + strscpy(cap->card, bdisp->pdev->name, sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s%d", BDISP_NAME, bdisp->id); diff --git a/drivers/media/platform/sti/delta/delta-v4l2.c b/drivers/media/platform/sti/delta/delta-v4l2.c index 0b42acd4e3a6..91369fb3ffaa 100644 --- a/drivers/media/platform/sti/delta/delta-v4l2.c +++ b/drivers/media/platform/sti/delta/delta-v4l2.c @@ -385,8 +385,8 @@ static int delta_querycap(struct file *file, void *priv, struct delta_ctx *ctx = to_ctx(file->private_data); struct delta_dev *delta = ctx->dev; - strlcpy(cap->driver, DELTA_NAME, sizeof(cap->driver)); - strlcpy(cap->card, delta->vdev->name, sizeof(cap->card)); + strscpy(cap->driver, DELTA_NAME, sizeof(cap->driver)); + strscpy(cap->card, delta->vdev->name, sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", delta->pdev->name); diff --git a/drivers/media/platform/sti/hva/hva-v4l2.c b/drivers/media/platform/sti/hva/hva-v4l2.c index 5a807c7c5e79..c42623dccfd6 100644 --- a/drivers/media/platform/sti/hva/hva-v4l2.c +++ b/drivers/media/platform/sti/hva/hva-v4l2.c @@ -257,8 +257,8 @@ static int hva_querycap(struct file *file, void *priv, struct hva_ctx *ctx = fh_to_ctx(file->private_data); struct hva_dev *hva = ctx_to_hdev(ctx); - strlcpy(cap->driver, HVA_NAME, sizeof(cap->driver)); - strlcpy(cap->card, hva->vdev->name, sizeof(cap->card)); + strscpy(cap->driver, HVA_NAME, sizeof(cap->driver)); + strscpy(cap->card, hva->vdev->name, sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", hva->pdev->name); diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c index 721564176d8c..6732874114cf 100644 --- a/drivers/media/platform/stm32/stm32-dcmi.c +++ b/drivers/media/platform/stm32/stm32-dcmi.c @@ -659,7 +659,10 @@ static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count) } /* Enable interruptions */ - reg_set(dcmi->regs, DCMI_IER, IT_FRAME | IT_OVR | IT_ERR); + if (dcmi->sd_format->fourcc == V4L2_PIX_FMT_JPEG) + reg_set(dcmi->regs, DCMI_IER, IT_FRAME | IT_OVR | IT_ERR); + else + reg_set(dcmi->regs, DCMI_IER, IT_OVR | IT_ERR); return 0; @@ -1147,10 +1150,10 @@ static int dcmi_s_selection(struct file *file, void *priv, static int dcmi_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { - strlcpy(cap->driver, DRV_NAME, sizeof(cap->driver)); - strlcpy(cap->card, "STM32 Camera Memory Interface", + strscpy(cap->driver, DRV_NAME, sizeof(cap->driver)); + strscpy(cap->card, "STM32 Camera Memory Interface", sizeof(cap->card)); - strlcpy(cap->bus_info, "platform:dcmi", sizeof(cap->bus_info)); + strscpy(cap->bus_info, "platform:dcmi", sizeof(cap->bus_info)); return 0; } @@ -1161,7 +1164,7 @@ static int dcmi_enum_input(struct file *file, void *priv, return -EINVAL; i->type = V4L2_INPUT_TYPE_CAMERA; - strlcpy(i->name, "Camera", sizeof(i->name)); + strscpy(i->name, "Camera", sizeof(i->name)); return 0; } @@ -1587,7 +1590,6 @@ static int dcmi_graph_parse(struct stm32_dcmi *dcmi, struct device_node *node) static int dcmi_graph_init(struct stm32_dcmi *dcmi) { - struct v4l2_async_subdev **subdevs = NULL; int ret; /* Parse the graph to extract a list of subdevice DT nodes. */ @@ -1597,23 +1599,21 @@ static int dcmi_graph_init(struct stm32_dcmi *dcmi) return ret; } - /* Register the subdevices notifier. */ - subdevs = devm_kzalloc(dcmi->dev, sizeof(*subdevs), GFP_KERNEL); - if (!subdevs) { + v4l2_async_notifier_init(&dcmi->notifier); + + ret = v4l2_async_notifier_add_subdev(&dcmi->notifier, + &dcmi->entity.asd); + if (ret) { of_node_put(dcmi->entity.node); - return -ENOMEM; + return ret; } - subdevs[0] = &dcmi->entity.asd; - - dcmi->notifier.subdevs = subdevs; - dcmi->notifier.num_subdevs = 1; dcmi->notifier.ops = &dcmi_graph_notify_ops; ret = v4l2_async_notifier_register(&dcmi->v4l2_dev, &dcmi->notifier); if (ret < 0) { dev_err(dcmi->dev, "Notifier registration failed\n"); - of_node_put(dcmi->entity.node); + v4l2_async_notifier_cleanup(&dcmi->notifier); return ret; } @@ -1624,7 +1624,7 @@ static int dcmi_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; const struct of_device_id *match = NULL; - struct v4l2_fwnode_endpoint ep; + struct v4l2_fwnode_endpoint ep = { .bus_type = 0 }; struct stm32_dcmi *dcmi; struct vb2_queue *q; struct dma_chan *chan; @@ -1663,7 +1663,7 @@ static int dcmi_probe(struct platform_device *pdev) return -ENODEV; } - if (ep.bus_type == V4L2_MBUS_CSI2) { + if (ep.bus_type == V4L2_MBUS_CSI2_DPHY) { dev_err(&pdev->dev, "CSI bus not supported\n"); return -ENODEV; } @@ -1736,7 +1736,7 @@ static int dcmi_probe(struct platform_device *pdev) dcmi->vdev->fops = &dcmi_fops; dcmi->vdev->v4l2_dev = &dcmi->v4l2_dev; dcmi->vdev->queue = &dcmi->queue; - strlcpy(dcmi->vdev->name, KBUILD_MODNAME, sizeof(dcmi->vdev->name)); + strscpy(dcmi->vdev->name, KBUILD_MODNAME, sizeof(dcmi->vdev->name)); dcmi->vdev->release = video_device_release; dcmi->vdev->ioctl_ops = &dcmi_ioctl_ops; dcmi->vdev->lock = &dcmi->lock; @@ -1770,7 +1770,7 @@ static int dcmi_probe(struct platform_device *pdev) ret = reset_control_assert(dcmi->rstc); if (ret) { dev_err(&pdev->dev, "Failed to assert the reset line\n"); - goto err_device_release; + goto err_cleanup; } usleep_range(3000, 5000); @@ -1778,7 +1778,7 @@ static int dcmi_probe(struct platform_device *pdev) ret = reset_control_deassert(dcmi->rstc); if (ret) { dev_err(&pdev->dev, "Failed to deassert the reset line\n"); - goto err_device_release; + goto err_cleanup; } dev_info(&pdev->dev, "Probe done\n"); @@ -1789,6 +1789,8 @@ static int dcmi_probe(struct platform_device *pdev) return 0; +err_cleanup: + v4l2_async_notifier_cleanup(&dcmi->notifier); err_device_release: video_device_release(dcmi->vdev); err_device_unregister: @@ -1806,6 +1808,7 @@ static int dcmi_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); v4l2_async_notifier_unregister(&dcmi->notifier); + v4l2_async_notifier_cleanup(&dcmi->notifier); v4l2_device_unregister(&dcmi->v4l2_dev); dma_release_channel(dcmi->dma_chan); diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c index d1febe5baa6d..95a093f41905 100644 --- a/drivers/media/platform/ti-vpe/cal.c +++ b/drivers/media/platform/ti-vpe/cal.c @@ -270,7 +270,6 @@ struct cal_ctx { struct v4l2_fwnode_endpoint endpoint; struct v4l2_async_subdev asd; - struct v4l2_async_subdev *asd_list[1]; struct v4l2_fh fh; struct cal_dev *dev; @@ -912,8 +911,8 @@ static int cal_querycap(struct file *file, void *priv, { struct cal_ctx *ctx = video_drvdata(file); - strlcpy(cap->driver, CAL_MODULE_NAME, sizeof(cap->driver)); - strlcpy(cap->card, CAL_MODULE_NAME, sizeof(cap->card)); + strscpy(cap->driver, CAL_MODULE_NAME, sizeof(cap->driver)); + strscpy(cap->card, CAL_MODULE_NAME, sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", ctx->v4l2_dev.name); @@ -1711,9 +1710,9 @@ static int of_cal_create_instance(struct cal_ctx *ctx, int inst) } v4l2_fwnode_endpoint_parse(of_fwnode_handle(remote_ep), endpoint); - if (endpoint->bus_type != V4L2_MBUS_CSI2) { - ctx_err(ctx, "Port:%d sub-device %s is not a CSI2 device\n", - inst, sensor_node->name); + if (endpoint->bus_type != V4L2_MBUS_CSI2_DPHY) { + ctx_err(ctx, "Port:%d sub-device %pOFn is not a CSI2 device\n", + inst, sensor_node); goto cleanup_exit; } @@ -1732,29 +1731,38 @@ static int of_cal_create_instance(struct cal_ctx *ctx, int inst) endpoint->bus.mipi_csi2.data_lanes[lane]); ctx_dbg(3, ctx, "\t>\n"); - ctx_dbg(1, ctx, "Port: %d found sub-device %s\n", - inst, sensor_node->name); + ctx_dbg(1, ctx, "Port: %d found sub-device %pOFn\n", + inst, sensor_node); + + v4l2_async_notifier_init(&ctx->notifier); + + ret = v4l2_async_notifier_add_subdev(&ctx->notifier, asd); + if (ret) { + ctx_err(ctx, "Error adding asd\n"); + goto cleanup_exit; + } - ctx->asd_list[0] = asd; - ctx->notifier.subdevs = ctx->asd_list; - ctx->notifier.num_subdevs = 1; ctx->notifier.ops = &cal_async_ops; ret = v4l2_async_notifier_register(&ctx->v4l2_dev, &ctx->notifier); if (ret) { ctx_err(ctx, "Error registering async notifier\n"); + v4l2_async_notifier_cleanup(&ctx->notifier); ret = -EINVAL; } + /* + * On success we need to keep reference on sensor_node, or + * if notifier_cleanup was called above, sensor_node was + * already put. + */ + sensor_node = NULL; + cleanup_exit: - if (remote_ep) - of_node_put(remote_ep); - if (sensor_node) - of_node_put(sensor_node); - if (ep_node) - of_node_put(ep_node); - if (port) - of_node_put(port); + of_node_put(remote_ep); + of_node_put(sensor_node); + of_node_put(ep_node); + of_node_put(port); return ret; } @@ -1810,15 +1818,17 @@ err_exit: static int cal_probe(struct platform_device *pdev) { struct cal_dev *dev; + struct cal_ctx *ctx; int ret; int irq; + int i; dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); if (!dev) return -ENOMEM; /* set pseudo v4l2 device name so we can use v4l2_printk */ - strlcpy(dev->v4l2_dev.name, CAL_MODULE_NAME, + strscpy(dev->v4l2_dev.name, CAL_MODULE_NAME, sizeof(dev->v4l2_dev.name)); /* save pdev pointer */ @@ -1879,6 +1889,16 @@ static int cal_probe(struct platform_device *pdev) runtime_disable: pm_runtime_disable(&pdev->dev); + for (i = 0; i < CAL_NUM_CONTEXT; i++) { + ctx = dev->ctx[i]; + if (ctx) { + v4l2_async_notifier_unregister(&ctx->notifier); + v4l2_async_notifier_cleanup(&ctx->notifier); + v4l2_ctrl_handler_free(&ctx->ctrl_handler); + v4l2_device_unregister(&ctx->v4l2_dev); + } + } + return ret; } @@ -1900,6 +1920,7 @@ static int cal_remove(struct platform_device *pdev) video_device_node_name(&ctx->vdev)); camerarx_phy_disable(ctx); v4l2_async_notifier_unregister(&ctx->notifier); + v4l2_async_notifier_cleanup(&ctx->notifier); v4l2_ctrl_handler_free(&ctx->ctrl_handler); v4l2_device_unregister(&ctx->v4l2_dev); video_unregister_device(&ctx->vdev); diff --git a/drivers/media/platform/via-camera.c b/drivers/media/platform/via-camera.c index c8bb82fe0b9d..24d5759501a5 100644 --- a/drivers/media/platform/via-camera.c +++ b/drivers/media/platform/via-camera.c @@ -812,7 +812,7 @@ static int viacam_enum_input(struct file *filp, void *priv, input->type = V4L2_INPUT_TYPE_CAMERA; input->std = V4L2_STD_ALL; /* Not sure what should go here */ - strcpy(input->name, "Camera"); + strscpy(input->name, "Camera", sizeof(input->name)); return 0; } @@ -860,8 +860,8 @@ static int viacam_enum_fmt_vid_cap(struct file *filp, void *priv, { if (fmt->index >= N_VIA_FMTS) return -EINVAL; - strlcpy(fmt->description, via_formats[fmt->index].desc, - sizeof(fmt->description)); + strscpy(fmt->description, via_formats[fmt->index].desc, + sizeof(fmt->description)); fmt->pixelformat = via_formats[fmt->index].pixelformat; return 0; } @@ -990,8 +990,8 @@ out: static int viacam_querycap(struct file *filp, void *priv, struct v4l2_capability *cap) { - strcpy(cap->driver, "via-camera"); - strcpy(cap->card, "via-camera"); + strscpy(cap->driver, "via-camera", sizeof(cap->driver)); + strscpy(cap->card, "via-camera", sizeof(cap->card)); cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; diff --git a/drivers/media/platform/vicodec/Kconfig b/drivers/media/platform/vicodec/Kconfig index 2503bcb1529f..ad13329e3461 100644 --- a/drivers/media/platform/vicodec/Kconfig +++ b/drivers/media/platform/vicodec/Kconfig @@ -1,6 +1,6 @@ config VIDEO_VICODEC tristate "Virtual Codec Driver" - depends on VIDEO_DEV && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API + depends on VIDEO_DEV && VIDEO_V4L2 select VIDEOBUF2_VMALLOC select V4L2_MEM2MEM_DEV default n diff --git a/drivers/media/platform/vicodec/Makefile b/drivers/media/platform/vicodec/Makefile index 197229428953..01bf7e9308a6 100644 --- a/drivers/media/platform/vicodec/Makefile +++ b/drivers/media/platform/vicodec/Makefile @@ -1,4 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 -vicodec-objs := vicodec-core.o vicodec-codec.o +vicodec-objs := vicodec-core.o codec-fwht.o codec-v4l2-fwht.o obj-$(CONFIG_VIDEO_VICODEC) += vicodec.o diff --git a/drivers/media/platform/vicodec/vicodec-codec.c b/drivers/media/platform/vicodec/codec-fwht.c index 2d047646f614..36656031b295 100644 --- a/drivers/media/platform/vicodec/vicodec-codec.c +++ b/drivers/media/platform/vicodec/codec-fwht.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +// SPDX-License-Identifier: LGPL-2.1+ /* * Copyright 2016 Tom aan de Wiel * Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved. @@ -10,10 +10,20 @@ */ #include <linux/string.h> -#include "vicodec-codec.h" +#include "codec-fwht.h" + +/* + * Note: bit 0 of the header must always be 0. Otherwise it cannot + * be guaranteed that the magic 8 byte sequence (see below) can + * never occur in the rlc output. + */ +#define PFRAME_BIT BIT(15) +#define DUPS_MASK 0x1ffe + +#define PBLOCK 0 +#define IBLOCK 1 #define ALL_ZEROS 15 -#define DEADZONE_WIDTH 20 static const uint8_t zigzag[64] = { 0, @@ -164,7 +174,7 @@ static const int quant_table_p[] = { 3, 3, 3, 6, 6, 9, 9, 10, }; -static void quantize_intra(s16 *coeff, s16 *de_coeff) +static void quantize_intra(s16 *coeff, s16 *de_coeff, u16 qp) { const int *quant = quant_table; int i, j; @@ -172,8 +182,7 @@ static void quantize_intra(s16 *coeff, s16 *de_coeff) for (j = 0; j < 8; j++) { for (i = 0; i < 8; i++, quant++, coeff++, de_coeff++) { *coeff >>= *quant; - if (*coeff >= -DEADZONE_WIDTH && - *coeff <= DEADZONE_WIDTH) + if (*coeff >= -qp && *coeff <= qp) *coeff = *de_coeff = 0; else *de_coeff = *coeff << *quant; @@ -191,7 +200,7 @@ static void dequantize_intra(s16 *coeff) *coeff <<= *quant; } -static void quantize_inter(s16 *coeff, s16 *de_coeff) +static void quantize_inter(s16 *coeff, s16 *de_coeff, u16 qp) { const int *quant = quant_table_p; int i, j; @@ -199,8 +208,7 @@ static void quantize_inter(s16 *coeff, s16 *de_coeff) for (j = 0; j < 8; j++) { for (i = 0; i < 8; i++, quant++, coeff++, de_coeff++) { *coeff >>= *quant; - if (*coeff >= -DEADZONE_WIDTH && - *coeff <= DEADZONE_WIDTH) + if (*coeff >= -qp && *coeff <= qp) *coeff = *de_coeff = 0; else *de_coeff = *coeff << *quant; @@ -232,7 +240,8 @@ static void fwht(const u8 *block, s16 *output_block, unsigned int stride, stride *= input_step; for (i = 0; i < 8; i++, tmp += stride, out += 8) { - if (input_step == 1) { + switch (input_step) { + case 1: workspace1[0] = tmp[0] + tmp[1] - add; workspace1[1] = tmp[0] - tmp[1]; @@ -244,7 +253,8 @@ static void fwht(const u8 *block, s16 *output_block, unsigned int stride, workspace1[6] = tmp[6] + tmp[7] - add; workspace1[7] = tmp[6] - tmp[7]; - } else { + break; + case 2: workspace1[0] = tmp[0] + tmp[2] - add; workspace1[1] = tmp[0] - tmp[2]; @@ -256,6 +266,33 @@ static void fwht(const u8 *block, s16 *output_block, unsigned int stride, workspace1[6] = tmp[12] + tmp[14] - add; workspace1[7] = tmp[12] - tmp[14]; + break; + case 3: + workspace1[0] = tmp[0] + tmp[3] - add; + workspace1[1] = tmp[0] - tmp[3]; + + workspace1[2] = tmp[6] + tmp[9] - add; + workspace1[3] = tmp[6] - tmp[9]; + + workspace1[4] = tmp[12] + tmp[15] - add; + workspace1[5] = tmp[12] - tmp[15]; + + workspace1[6] = tmp[18] + tmp[21] - add; + workspace1[7] = tmp[18] - tmp[21]; + break; + default: + workspace1[0] = tmp[0] + tmp[4] - add; + workspace1[1] = tmp[0] - tmp[4]; + + workspace1[2] = tmp[8] + tmp[12] - add; + workspace1[3] = tmp[8] - tmp[12]; + + workspace1[4] = tmp[16] + tmp[20] - add; + workspace1[5] = tmp[16] - tmp[20]; + + workspace1[6] = tmp[24] + tmp[28] - add; + workspace1[7] = tmp[24] - tmp[28]; + break; } /* stage 2 */ @@ -588,8 +625,14 @@ static void fill_decoder_block(u8 *dst, const s16 *input, int stride) int i, j; for (i = 0; i < 8; i++) { - for (j = 0; j < 8; j++) - *dst++ = *input++; + for (j = 0; j < 8; j++, input++, dst++) { + if (*input < 0) + *dst = 0; + else if (*input > 255) + *dst = 255; + else + *dst = *input; + } dst += stride - 8; } } @@ -616,7 +659,7 @@ static void add_deltas(s16 *deltas, const u8 *ref, int stride) } static u32 encode_plane(u8 *input, u8 *refp, __be16 **rlco, __be16 *rlco_max, - struct cframe *cf, u32 height, u32 width, + struct fwht_cframe *cf, u32 height, u32 width, unsigned int input_step, bool is_intra, bool next_is_intra) { @@ -637,15 +680,16 @@ static u32 encode_plane(u8 *input, u8 *refp, __be16 **rlco, __be16 *rlco_max, if (!is_intra) blocktype = decide_blocktype(input, refp, deltablock, width, input_step); - if (is_intra || blocktype == IBLOCK) { + if (blocktype == IBLOCK) { fwht(input, cf->coeffs, width, input_step, 1); - quantize_intra(cf->coeffs, cf->de_coeffs); - blocktype = IBLOCK; + quantize_intra(cf->coeffs, cf->de_coeffs, + cf->i_frame_qp); } else { /* inter code */ - encoding |= FRAME_PCODED; + encoding |= FWHT_FRAME_PCODED; fwht16(deltablock, cf->coeffs, 8, 0); - quantize_inter(cf->coeffs, cf->de_coeffs); + quantize_inter(cf->coeffs, cf->de_coeffs, + cf->p_frame_qp); } if (!next_is_intra) { ifwht(cf->de_coeffs, cf->de_fwht, blocktype); @@ -658,9 +702,6 @@ static u32 encode_plane(u8 *input, u8 *refp, __be16 **rlco, __be16 *rlco_max, input += 8 * input_step; refp += 8 * 8; - if (encoding & FRAME_UNENCODED) - continue; - size = rlc(cf->coeffs, *rlco, blocktype); if (last_size == size && !memcmp(*rlco + 1, *rlco - size + 1, 2 * size - 2)) { @@ -675,13 +716,17 @@ static u32 encode_plane(u8 *input, u8 *refp, __be16 **rlco, __be16 *rlco_max, } else { *rlco += size; } - if (*rlco >= rlco_max) - encoding |= FRAME_UNENCODED; + if (*rlco >= rlco_max) { + encoding |= FWHT_FRAME_UNENCODED; + goto exit_loop; + } last_size = size; } input += width * 7 * input_step; } - if (encoding & FRAME_UNENCODED) { + +exit_loop: + if (encoding & FWHT_FRAME_UNENCODED) { u8 *out = (u8 *)rlco_start; input = input_start; @@ -694,44 +739,50 @@ static u32 encode_plane(u8 *input, u8 *refp, __be16 **rlco, __be16 *rlco_max, for (i = 0; i < height * width; i++, input += input_step) *out++ = (*input == 0xff) ? 0xfe : *input; *rlco = (__be16 *)out; + encoding &= ~FWHT_FRAME_PCODED; } return encoding; } -u32 encode_frame(struct raw_frame *frm, struct raw_frame *ref_frm, - struct cframe *cf, bool is_intra, bool next_is_intra) +u32 fwht_encode_frame(struct fwht_raw_frame *frm, + struct fwht_raw_frame *ref_frm, + struct fwht_cframe *cf, + bool is_intra, bool next_is_intra) { unsigned int size = frm->height * frm->width; __be16 *rlco = cf->rlc_data; __be16 *rlco_max; u32 encoding; + u32 chroma_h = frm->height / frm->height_div; + u32 chroma_w = frm->width / frm->width_div; + unsigned int chroma_size = chroma_h * chroma_w; rlco_max = rlco + size / 2 - 256; encoding = encode_plane(frm->luma, ref_frm->luma, &rlco, rlco_max, cf, - frm->height, frm->width, - 1, is_intra, next_is_intra); - if (encoding & FRAME_UNENCODED) - encoding |= LUMA_UNENCODED; - encoding &= ~FRAME_UNENCODED; - rlco_max = rlco + size / 8 - 256; + frm->height, frm->width, + frm->luma_step, is_intra, next_is_intra); + if (encoding & FWHT_FRAME_UNENCODED) + encoding |= FWHT_LUMA_UNENCODED; + encoding &= ~FWHT_FRAME_UNENCODED; + rlco_max = rlco + chroma_size / 2 - 256; encoding |= encode_plane(frm->cb, ref_frm->cb, &rlco, rlco_max, cf, - frm->height / 2, frm->width / 2, - frm->chroma_step, is_intra, next_is_intra); - if (encoding & FRAME_UNENCODED) - encoding |= CB_UNENCODED; - encoding &= ~FRAME_UNENCODED; - rlco_max = rlco + size / 8 - 256; + chroma_h, chroma_w, + frm->chroma_step, is_intra, next_is_intra); + if (encoding & FWHT_FRAME_UNENCODED) + encoding |= FWHT_CB_UNENCODED; + encoding &= ~FWHT_FRAME_UNENCODED; + rlco_max = rlco + chroma_size / 2 - 256; encoding |= encode_plane(frm->cr, ref_frm->cr, &rlco, rlco_max, cf, - frm->height / 2, frm->width / 2, - frm->chroma_step, is_intra, next_is_intra); - if (encoding & FRAME_UNENCODED) - encoding |= CR_UNENCODED; - encoding &= ~FRAME_UNENCODED; + chroma_h, chroma_w, + frm->chroma_step, is_intra, next_is_intra); + if (encoding & FWHT_FRAME_UNENCODED) + encoding |= FWHT_CR_UNENCODED; + encoding &= ~FWHT_FRAME_UNENCODED; cf->size = (rlco - cf->rlc_data) * sizeof(*rlco); return encoding; } -static void decode_plane(struct cframe *cf, const __be16 **rlco, u8 *ref, +static void decode_plane(struct fwht_cframe *cf, const __be16 **rlco, u8 *ref, u32 height, u32 width, bool uncompressed) { unsigned int copies = 0; @@ -784,14 +835,21 @@ static void decode_plane(struct cframe *cf, const __be16 **rlco, u8 *ref, } } -void decode_frame(struct cframe *cf, struct raw_frame *ref, u32 hdr_flags) +void fwht_decode_frame(struct fwht_cframe *cf, struct fwht_raw_frame *ref, + u32 hdr_flags) { const __be16 *rlco = cf->rlc_data; + u32 h = cf->height / 2; + u32 w = cf->width / 2; + if (hdr_flags & FWHT_FL_CHROMA_FULL_HEIGHT) + h *= 2; + if (hdr_flags & FWHT_FL_CHROMA_FULL_WIDTH) + w *= 2; decode_plane(cf, &rlco, ref->luma, cf->height, cf->width, - hdr_flags & VICODEC_FL_LUMA_IS_UNCOMPRESSED); - decode_plane(cf, &rlco, ref->cb, cf->height / 2, cf->width / 2, - hdr_flags & VICODEC_FL_CB_IS_UNCOMPRESSED); - decode_plane(cf, &rlco, ref->cr, cf->height / 2, cf->width / 2, - hdr_flags & VICODEC_FL_CR_IS_UNCOMPRESSED); + hdr_flags & FWHT_FL_LUMA_IS_UNCOMPRESSED); + decode_plane(cf, &rlco, ref->cb, h, w, + hdr_flags & FWHT_FL_CB_IS_UNCOMPRESSED); + decode_plane(cf, &rlco, ref->cr, h, w, + hdr_flags & FWHT_FL_CR_IS_UNCOMPRESSED); } diff --git a/drivers/media/platform/vicodec/vicodec-codec.h b/drivers/media/platform/vicodec/codec-fwht.h index cdfad1332a3e..3e9391fec5fe 100644 --- a/drivers/media/platform/vicodec/vicodec-codec.h +++ b/drivers/media/platform/vicodec/codec-fwht.h @@ -1,18 +1,18 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: LGPL-2.1+ */ /* * Copyright 2016 Tom aan de Wiel * Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved. */ -#ifndef VICODEC_RLC_H -#define VICODEC_RLC_H +#ifndef CODEC_FWHT_H +#define CODEC_FWHT_H #include <linux/types.h> #include <linux/bitops.h> #include <asm/byteorder.h> /* - * The compressed format consists of a cframe_hdr struct followed by the + * The compressed format consists of a fwht_cframe_hdr struct followed by the * compressed frame data. The header contains the size of that data. * Each Y, Cb and Cr plane is compressed separately. If the compressed * size of each plane becomes larger than the uncompressed size, then @@ -35,7 +35,7 @@ * * All 16 and 32 bit values are stored in big-endian (network) order. * - * Each cframe_hdr starts with an 8 byte magic header that is + * Each fwht_cframe_hdr starts with an 8 byte magic header that is * guaranteed not to occur in the compressed frame data. This header * can be used to sync to the next frame. * @@ -47,48 +47,36 @@ */ /* - * Note: bit 0 of the header must always be 0. Otherwise it cannot - * be guaranteed that the magic 8 byte sequence (see below) can - * never occur in the rlc output. - */ -#define PFRAME_BIT (1 << 15) -#define DUPS_MASK 0x1ffe - -/* * This is a sequence of 8 bytes with the low 4 bits set to 0xf. * * This sequence cannot occur in the encoded data + * + * Note that these two magic values are symmetrical so endian issues here. */ -#define VICODEC_MAGIC1 0x4f4f4f4f -#define VICODEC_MAGIC2 0xffffffff - -#define VICODEC_VERSION 1 - -#define VICODEC_MAX_WIDTH 3840 -#define VICODEC_MAX_HEIGHT 2160 -#define VICODEC_MIN_WIDTH 640 -#define VICODEC_MIN_HEIGHT 480 +#define FWHT_MAGIC1 0x4f4f4f4f +#define FWHT_MAGIC2 0xffffffff -#define PBLOCK 0 -#define IBLOCK 1 +#define FWHT_VERSION 1 /* Set if this is an interlaced format */ -#define VICODEC_FL_IS_INTERLACED BIT(0) +#define FWHT_FL_IS_INTERLACED BIT(0) /* Set if this is a bottom-first (NTSC) interlaced format */ -#define VICODEC_FL_IS_BOTTOM_FIRST BIT(1) +#define FWHT_FL_IS_BOTTOM_FIRST BIT(1) /* Set if each 'frame' contains just one field */ -#define VICODEC_FL_IS_ALTERNATE BIT(2) +#define FWHT_FL_IS_ALTERNATE BIT(2) /* - * If VICODEC_FL_IS_ALTERNATE was set, then this is set if this + * If FWHT_FL_IS_ALTERNATE was set, then this is set if this * 'frame' is the bottom field, else it is the top field. */ -#define VICODEC_FL_IS_BOTTOM_FIELD BIT(3) +#define FWHT_FL_IS_BOTTOM_FIELD BIT(3) /* Set if this frame is uncompressed */ -#define VICODEC_FL_LUMA_IS_UNCOMPRESSED BIT(4) -#define VICODEC_FL_CB_IS_UNCOMPRESSED BIT(5) -#define VICODEC_FL_CR_IS_UNCOMPRESSED BIT(6) +#define FWHT_FL_LUMA_IS_UNCOMPRESSED BIT(4) +#define FWHT_FL_CB_IS_UNCOMPRESSED BIT(5) +#define FWHT_FL_CR_IS_UNCOMPRESSED BIT(6) +#define FWHT_FL_CHROMA_FULL_HEIGHT BIT(7) +#define FWHT_FL_CHROMA_FULL_WIDTH BIT(8) -struct cframe_hdr { +struct fwht_cframe_hdr { u32 magic1; u32 magic2; __be32 version; @@ -101,8 +89,10 @@ struct cframe_hdr { __be32 size; }; -struct cframe { +struct fwht_cframe { unsigned int width, height; + u16 i_frame_qp; + u16 p_frame_qp; __be16 *rlc_data; s16 coeffs[8 * 8]; s16 de_coeffs[8 * 8]; @@ -110,20 +100,26 @@ struct cframe { u32 size; }; -struct raw_frame { +struct fwht_raw_frame { unsigned int width, height; + unsigned int width_div; + unsigned int height_div; + unsigned int luma_step; unsigned int chroma_step; u8 *luma, *cb, *cr; }; -#define FRAME_PCODED BIT(0) -#define FRAME_UNENCODED BIT(1) -#define LUMA_UNENCODED BIT(2) -#define CB_UNENCODED BIT(3) -#define CR_UNENCODED BIT(4) +#define FWHT_FRAME_PCODED BIT(0) +#define FWHT_FRAME_UNENCODED BIT(1) +#define FWHT_LUMA_UNENCODED BIT(2) +#define FWHT_CB_UNENCODED BIT(3) +#define FWHT_CR_UNENCODED BIT(4) -u32 encode_frame(struct raw_frame *frm, struct raw_frame *ref_frm, - struct cframe *cf, bool is_intra, bool next_is_intra); -void decode_frame(struct cframe *cf, struct raw_frame *ref, u32 hdr_flags); +u32 fwht_encode_frame(struct fwht_raw_frame *frm, + struct fwht_raw_frame *ref_frm, + struct fwht_cframe *cf, + bool is_intra, bool next_is_intra); +void fwht_decode_frame(struct fwht_cframe *cf, struct fwht_raw_frame *ref, + u32 hdr_flags); #endif diff --git a/drivers/media/platform/vicodec/codec-v4l2-fwht.c b/drivers/media/platform/vicodec/codec-v4l2-fwht.c new file mode 100644 index 000000000000..e5b68fb38aac --- /dev/null +++ b/drivers/media/platform/vicodec/codec-v4l2-fwht.c @@ -0,0 +1,332 @@ +// SPDX-License-Identifier: LGPL-2.1 +/* + * A V4L2 frontend for the FWHT codec + * + * Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + */ + +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/videodev2.h> +#include "codec-v4l2-fwht.h" + +static const struct v4l2_fwht_pixfmt_info v4l2_fwht_pixfmts[] = { + { V4L2_PIX_FMT_YUV420, 1, 3, 2, 1, 1, 2, 2 }, + { V4L2_PIX_FMT_YVU420, 1, 3, 2, 1, 1, 2, 2 }, + { V4L2_PIX_FMT_YUV422P, 1, 2, 1, 1, 1, 2, 1 }, + { V4L2_PIX_FMT_NV12, 1, 3, 2, 1, 2, 2, 2 }, + { V4L2_PIX_FMT_NV21, 1, 3, 2, 1, 2, 2, 2 }, + { V4L2_PIX_FMT_NV16, 1, 2, 1, 1, 2, 2, 1 }, + { V4L2_PIX_FMT_NV61, 1, 2, 1, 1, 2, 2, 1 }, + { V4L2_PIX_FMT_NV24, 1, 3, 1, 1, 2, 1, 1 }, + { V4L2_PIX_FMT_NV42, 1, 3, 1, 1, 2, 1, 1 }, + { V4L2_PIX_FMT_YUYV, 2, 2, 1, 2, 4, 2, 1 }, + { V4L2_PIX_FMT_YVYU, 2, 2, 1, 2, 4, 2, 1 }, + { V4L2_PIX_FMT_UYVY, 2, 2, 1, 2, 4, 2, 1 }, + { V4L2_PIX_FMT_VYUY, 2, 2, 1, 2, 4, 2, 1 }, + { V4L2_PIX_FMT_BGR24, 3, 3, 1, 3, 3, 1, 1 }, + { V4L2_PIX_FMT_RGB24, 3, 3, 1, 3, 3, 1, 1 }, + { V4L2_PIX_FMT_HSV24, 3, 3, 1, 3, 3, 1, 1 }, + { V4L2_PIX_FMT_BGR32, 4, 4, 1, 4, 4, 1, 1 }, + { V4L2_PIX_FMT_XBGR32, 4, 4, 1, 4, 4, 1, 1 }, + { V4L2_PIX_FMT_RGB32, 4, 4, 1, 4, 4, 1, 1 }, + { V4L2_PIX_FMT_XRGB32, 4, 4, 1, 4, 4, 1, 1 }, + { V4L2_PIX_FMT_HSV32, 4, 4, 1, 4, 4, 1, 1 }, +}; + +const struct v4l2_fwht_pixfmt_info *v4l2_fwht_find_pixfmt(u32 pixelformat) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(v4l2_fwht_pixfmts); i++) + if (v4l2_fwht_pixfmts[i].id == pixelformat) + return v4l2_fwht_pixfmts + i; + return NULL; +} + +const struct v4l2_fwht_pixfmt_info *v4l2_fwht_get_pixfmt(u32 idx) +{ + if (idx >= ARRAY_SIZE(v4l2_fwht_pixfmts)) + return NULL; + return v4l2_fwht_pixfmts + idx; +} + +int v4l2_fwht_encode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out) +{ + unsigned int size = state->width * state->height; + const struct v4l2_fwht_pixfmt_info *info = state->info; + struct fwht_cframe_hdr *p_hdr; + struct fwht_cframe cf; + struct fwht_raw_frame rf; + u32 encoding; + u32 flags = 0; + + if (!info) + return -EINVAL; + rf.width = state->width; + rf.height = state->height; + rf.luma = p_in; + rf.width_div = info->width_div; + rf.height_div = info->height_div; + rf.luma_step = info->luma_step; + rf.chroma_step = info->chroma_step; + + switch (info->id) { + case V4L2_PIX_FMT_YUV420: + rf.cb = rf.luma + size; + rf.cr = rf.cb + size / 4; + break; + case V4L2_PIX_FMT_YVU420: + rf.cr = rf.luma + size; + rf.cb = rf.cr + size / 4; + break; + case V4L2_PIX_FMT_YUV422P: + rf.cb = rf.luma + size; + rf.cr = rf.cb + size / 2; + break; + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_NV24: + rf.cb = rf.luma + size; + rf.cr = rf.cb + 1; + break; + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV61: + case V4L2_PIX_FMT_NV42: + rf.cr = rf.luma + size; + rf.cb = rf.cr + 1; + break; + case V4L2_PIX_FMT_YUYV: + rf.cb = rf.luma + 1; + rf.cr = rf.cb + 2; + break; + case V4L2_PIX_FMT_YVYU: + rf.cr = rf.luma + 1; + rf.cb = rf.cr + 2; + break; + case V4L2_PIX_FMT_UYVY: + rf.cb = rf.luma; + rf.cr = rf.cb + 2; + rf.luma++; + break; + case V4L2_PIX_FMT_VYUY: + rf.cr = rf.luma; + rf.cb = rf.cr + 2; + rf.luma++; + break; + case V4L2_PIX_FMT_RGB24: + case V4L2_PIX_FMT_HSV24: + rf.cr = rf.luma; + rf.cb = rf.cr + 2; + rf.luma++; + break; + case V4L2_PIX_FMT_BGR24: + rf.cb = rf.luma; + rf.cr = rf.cb + 2; + rf.luma++; + break; + case V4L2_PIX_FMT_RGB32: + case V4L2_PIX_FMT_XRGB32: + case V4L2_PIX_FMT_HSV32: + rf.cr = rf.luma + 1; + rf.cb = rf.cr + 2; + rf.luma += 2; + break; + case V4L2_PIX_FMT_BGR32: + case V4L2_PIX_FMT_XBGR32: + rf.cb = rf.luma; + rf.cr = rf.cb + 2; + rf.luma++; + break; + default: + return -EINVAL; + } + + cf.width = state->width; + cf.height = state->height; + cf.i_frame_qp = state->i_frame_qp; + cf.p_frame_qp = state->p_frame_qp; + cf.rlc_data = (__be16 *)(p_out + sizeof(*p_hdr)); + + encoding = fwht_encode_frame(&rf, &state->ref_frame, &cf, + !state->gop_cnt, + state->gop_cnt == state->gop_size - 1); + if (!(encoding & FWHT_FRAME_PCODED)) + state->gop_cnt = 0; + if (++state->gop_cnt >= state->gop_size) + state->gop_cnt = 0; + + p_hdr = (struct fwht_cframe_hdr *)p_out; + p_hdr->magic1 = FWHT_MAGIC1; + p_hdr->magic2 = FWHT_MAGIC2; + p_hdr->version = htonl(FWHT_VERSION); + p_hdr->width = htonl(cf.width); + p_hdr->height = htonl(cf.height); + if (encoding & FWHT_LUMA_UNENCODED) + flags |= FWHT_FL_LUMA_IS_UNCOMPRESSED; + if (encoding & FWHT_CB_UNENCODED) + flags |= FWHT_FL_CB_IS_UNCOMPRESSED; + if (encoding & FWHT_CR_UNENCODED) + flags |= FWHT_FL_CR_IS_UNCOMPRESSED; + if (rf.height_div == 1) + flags |= FWHT_FL_CHROMA_FULL_HEIGHT; + if (rf.width_div == 1) + flags |= FWHT_FL_CHROMA_FULL_WIDTH; + p_hdr->flags = htonl(flags); + p_hdr->colorspace = htonl(state->colorspace); + p_hdr->xfer_func = htonl(state->xfer_func); + p_hdr->ycbcr_enc = htonl(state->ycbcr_enc); + p_hdr->quantization = htonl(state->quantization); + p_hdr->size = htonl(cf.size); + state->ref_frame.width = cf.width; + state->ref_frame.height = cf.height; + return cf.size + sizeof(*p_hdr); +} + +int v4l2_fwht_decode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out) +{ + unsigned int size = state->width * state->height; + unsigned int chroma_size = size; + unsigned int i; + u32 flags; + struct fwht_cframe_hdr *p_hdr; + struct fwht_cframe cf; + u8 *p; + + if (!state->info) + return -EINVAL; + + p_hdr = (struct fwht_cframe_hdr *)p_in; + cf.width = ntohl(p_hdr->width); + cf.height = ntohl(p_hdr->height); + flags = ntohl(p_hdr->flags); + state->colorspace = ntohl(p_hdr->colorspace); + state->xfer_func = ntohl(p_hdr->xfer_func); + state->ycbcr_enc = ntohl(p_hdr->ycbcr_enc); + state->quantization = ntohl(p_hdr->quantization); + cf.rlc_data = (__be16 *)(p_in + sizeof(*p_hdr)); + + if (p_hdr->magic1 != FWHT_MAGIC1 || + p_hdr->magic2 != FWHT_MAGIC2 || + ntohl(p_hdr->version) != FWHT_VERSION || + (cf.width & 7) || (cf.height & 7)) + return -EINVAL; + + /* TODO: support resolution changes */ + if (cf.width != state->width || cf.height != state->height) + return -EINVAL; + + if (!(flags & FWHT_FL_CHROMA_FULL_WIDTH)) + chroma_size /= 2; + if (!(flags & FWHT_FL_CHROMA_FULL_HEIGHT)) + chroma_size /= 2; + + fwht_decode_frame(&cf, &state->ref_frame, flags); + + switch (state->info->id) { + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_YUV422P: + memcpy(p_out, state->ref_frame.luma, size); + p_out += size; + memcpy(p_out, state->ref_frame.cb, chroma_size); + p_out += chroma_size; + memcpy(p_out, state->ref_frame.cr, chroma_size); + break; + case V4L2_PIX_FMT_YVU420: + memcpy(p_out, state->ref_frame.luma, size); + p_out += size; + memcpy(p_out, state->ref_frame.cr, chroma_size); + p_out += chroma_size; + memcpy(p_out, state->ref_frame.cb, chroma_size); + break; + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_NV24: + memcpy(p_out, state->ref_frame.luma, size); + p_out += size; + for (i = 0, p = p_out; i < chroma_size; i++) { + *p++ = state->ref_frame.cb[i]; + *p++ = state->ref_frame.cr[i]; + } + break; + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV61: + case V4L2_PIX_FMT_NV42: + memcpy(p_out, state->ref_frame.luma, size); + p_out += size; + for (i = 0, p = p_out; i < chroma_size; i++) { + *p++ = state->ref_frame.cr[i]; + *p++ = state->ref_frame.cb[i]; + } + break; + case V4L2_PIX_FMT_YUYV: + for (i = 0, p = p_out; i < size; i += 2) { + *p++ = state->ref_frame.luma[i]; + *p++ = state->ref_frame.cb[i / 2]; + *p++ = state->ref_frame.luma[i + 1]; + *p++ = state->ref_frame.cr[i / 2]; + } + break; + case V4L2_PIX_FMT_YVYU: + for (i = 0, p = p_out; i < size; i += 2) { + *p++ = state->ref_frame.luma[i]; + *p++ = state->ref_frame.cr[i / 2]; + *p++ = state->ref_frame.luma[i + 1]; + *p++ = state->ref_frame.cb[i / 2]; + } + break; + case V4L2_PIX_FMT_UYVY: + for (i = 0, p = p_out; i < size; i += 2) { + *p++ = state->ref_frame.cb[i / 2]; + *p++ = state->ref_frame.luma[i]; + *p++ = state->ref_frame.cr[i / 2]; + *p++ = state->ref_frame.luma[i + 1]; + } + break; + case V4L2_PIX_FMT_VYUY: + for (i = 0, p = p_out; i < size; i += 2) { + *p++ = state->ref_frame.cr[i / 2]; + *p++ = state->ref_frame.luma[i]; + *p++ = state->ref_frame.cb[i / 2]; + *p++ = state->ref_frame.luma[i + 1]; + } + break; + case V4L2_PIX_FMT_RGB24: + case V4L2_PIX_FMT_HSV24: + for (i = 0, p = p_out; i < size; i++) { + *p++ = state->ref_frame.cr[i]; + *p++ = state->ref_frame.luma[i]; + *p++ = state->ref_frame.cb[i]; + } + break; + case V4L2_PIX_FMT_BGR24: + for (i = 0, p = p_out; i < size; i++) { + *p++ = state->ref_frame.cb[i]; + *p++ = state->ref_frame.luma[i]; + *p++ = state->ref_frame.cr[i]; + } + break; + case V4L2_PIX_FMT_RGB32: + case V4L2_PIX_FMT_XRGB32: + case V4L2_PIX_FMT_HSV32: + for (i = 0, p = p_out; i < size; i++) { + *p++ = 0; + *p++ = state->ref_frame.cr[i]; + *p++ = state->ref_frame.luma[i]; + *p++ = state->ref_frame.cb[i]; + } + break; + case V4L2_PIX_FMT_BGR32: + case V4L2_PIX_FMT_XBGR32: + for (i = 0, p = p_out; i < size; i++) { + *p++ = state->ref_frame.cb[i]; + *p++ = state->ref_frame.luma[i]; + *p++ = state->ref_frame.cr[i]; + *p++ = 0; + } + break; + default: + return -EINVAL; + } + return 0; +} diff --git a/drivers/media/platform/vicodec/codec-v4l2-fwht.h b/drivers/media/platform/vicodec/codec-v4l2-fwht.h new file mode 100644 index 000000000000..162465b78067 --- /dev/null +++ b/drivers/media/platform/vicodec/codec-v4l2-fwht.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: LGPL-2.1 */ +/* + * Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + */ + +#ifndef CODEC_V4L2_FWHT_H +#define CODEC_V4L2_FWHT_H + +#include "codec-fwht.h" + +struct v4l2_fwht_pixfmt_info { + u32 id; + unsigned int bytesperline_mult; + unsigned int sizeimage_mult; + unsigned int sizeimage_div; + unsigned int luma_step; + unsigned int chroma_step; + /* Chroma plane subsampling */ + unsigned int width_div; + unsigned int height_div; +}; + +struct v4l2_fwht_state { + const struct v4l2_fwht_pixfmt_info *info; + unsigned int width; + unsigned int height; + unsigned int gop_size; + unsigned int gop_cnt; + u16 i_frame_qp; + u16 p_frame_qp; + + enum v4l2_colorspace colorspace; + enum v4l2_ycbcr_encoding ycbcr_enc; + enum v4l2_xfer_func xfer_func; + enum v4l2_quantization quantization; + + struct fwht_raw_frame ref_frame; + u8 *compressed_frame; +}; + +const struct v4l2_fwht_pixfmt_info *v4l2_fwht_find_pixfmt(u32 pixelformat); +const struct v4l2_fwht_pixfmt_info *v4l2_fwht_get_pixfmt(u32 idx); + +int v4l2_fwht_encode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out); +int v4l2_fwht_decode(struct v4l2_fwht_state *state, u8 *p_in, u8 *p_out); + +#endif diff --git a/drivers/media/platform/vicodec/vicodec-core.c b/drivers/media/platform/vicodec/vicodec-core.c index 408cd55d3580..1eb9132bfc85 100644 --- a/drivers/media/platform/vicodec/vicodec-core.c +++ b/drivers/media/platform/vicodec/vicodec-core.c @@ -23,7 +23,7 @@ #include <media/v4l2-event.h> #include <media/videobuf2-vmalloc.h> -#include "vicodec-codec.h" +#include "codec-v4l2-fwht.h" MODULE_DESCRIPTION("Virtual codec device"); MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>"); @@ -48,6 +48,22 @@ MODULE_PARM_DESC(debug, " activates debug info"); v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg) +struct pixfmt_info { + u32 id; + unsigned int bytesperline_mult; + unsigned int sizeimage_mult; + unsigned int sizeimage_div; + unsigned int luma_step; + unsigned int chroma_step; + /* Chroma plane subsampling */ + unsigned int width_div; + unsigned int height_div; +}; + +static const struct v4l2_fwht_pixfmt_info pixfmt_fwht = { + V4L2_PIX_FMT_FWHT, 0, 3, 1, 1, 1, 1, 1 +}; + static void vicodec_dev_release(struct device *dev) { } @@ -61,10 +77,9 @@ static struct platform_device vicodec_pdev = { struct vicodec_q_data { unsigned int width; unsigned int height; - unsigned int flags; unsigned int sizeimage; unsigned int sequence; - u32 fourcc; + const struct v4l2_fwht_pixfmt_info *info; }; enum { @@ -96,24 +111,14 @@ struct vicodec_ctx { spinlock_t *lock; struct v4l2_ctrl_handler hdl; - struct v4l2_ctrl *ctrl_gop_size; - unsigned int gop_size; - unsigned int gop_cnt; - /* Abort requested by m2m */ - int aborting; struct vb2_v4l2_buffer *last_src_buf; struct vb2_v4l2_buffer *last_dst_buf; - enum v4l2_colorspace colorspace; - enum v4l2_ycbcr_encoding ycbcr_enc; - enum v4l2_xfer_func xfer_func; - enum v4l2_quantization quantization; - /* Source and destination queue data */ struct vicodec_q_data q_data[2]; - struct raw_frame ref_frame; - u8 *compressed_frame; + struct v4l2_fwht_state state; + u32 cur_buf_offset; u32 comp_max_size; u32 comp_size; @@ -123,13 +128,6 @@ struct vicodec_ctx { bool comp_has_next_frame; }; -static const u32 pixfmts_yuv[] = { - V4L2_PIX_FMT_YUV420, - V4L2_PIX_FMT_YVU420, - V4L2_PIX_FMT_NV12, - V4L2_PIX_FMT_NV21, -}; - static inline struct vicodec_ctx *file2ctx(struct file *file) { return container_of(file->private_data, struct vicodec_ctx, fh); @@ -152,156 +150,21 @@ static struct vicodec_q_data *get_q_data(struct vicodec_ctx *ctx, return NULL; } -static void encode(struct vicodec_ctx *ctx, - struct vicodec_q_data *q_data, - u8 *p_in, u8 *p_out) -{ - unsigned int size = q_data->width * q_data->height; - struct cframe_hdr *p_hdr; - struct cframe cf; - struct raw_frame rf; - u32 encoding; - - rf.width = q_data->width; - rf.height = q_data->height; - rf.luma = p_in; - - switch (q_data->fourcc) { - case V4L2_PIX_FMT_YUV420: - rf.cb = rf.luma + size; - rf.cr = rf.cb + size / 4; - rf.chroma_step = 1; - break; - case V4L2_PIX_FMT_YVU420: - rf.cr = rf.luma + size; - rf.cb = rf.cr + size / 4; - rf.chroma_step = 1; - break; - case V4L2_PIX_FMT_NV12: - rf.cb = rf.luma + size; - rf.cr = rf.cb + 1; - rf.chroma_step = 2; - break; - case V4L2_PIX_FMT_NV21: - rf.cr = rf.luma + size; - rf.cb = rf.cr + 1; - rf.chroma_step = 2; - break; - } - - cf.width = q_data->width; - cf.height = q_data->height; - cf.rlc_data = (__be16 *)(p_out + sizeof(*p_hdr)); - - encoding = encode_frame(&rf, &ctx->ref_frame, &cf, !ctx->gop_cnt, - ctx->gop_cnt == ctx->gop_size - 1); - if (encoding != FRAME_PCODED) - ctx->gop_cnt = 0; - if (++ctx->gop_cnt == ctx->gop_size) - ctx->gop_cnt = 0; - - p_hdr = (struct cframe_hdr *)p_out; - p_hdr->magic1 = VICODEC_MAGIC1; - p_hdr->magic2 = VICODEC_MAGIC2; - p_hdr->version = htonl(VICODEC_VERSION); - p_hdr->width = htonl(cf.width); - p_hdr->height = htonl(cf.height); - p_hdr->flags = htonl(q_data->flags); - if (encoding & LUMA_UNENCODED) - p_hdr->flags |= htonl(VICODEC_FL_LUMA_IS_UNCOMPRESSED); - if (encoding & CB_UNENCODED) - p_hdr->flags |= htonl(VICODEC_FL_CB_IS_UNCOMPRESSED); - if (encoding & CR_UNENCODED) - p_hdr->flags |= htonl(VICODEC_FL_CR_IS_UNCOMPRESSED); - p_hdr->colorspace = htonl(ctx->colorspace); - p_hdr->xfer_func = htonl(ctx->xfer_func); - p_hdr->ycbcr_enc = htonl(ctx->ycbcr_enc); - p_hdr->quantization = htonl(ctx->quantization); - p_hdr->size = htonl(cf.size); - ctx->ref_frame.width = cf.width; - ctx->ref_frame.height = cf.height; -} - -static int decode(struct vicodec_ctx *ctx, - struct vicodec_q_data *q_data, - u8 *p_in, u8 *p_out) -{ - unsigned int size = q_data->width * q_data->height; - unsigned int i; - struct cframe_hdr *p_hdr; - struct cframe cf; - u8 *p; - - p_hdr = (struct cframe_hdr *)p_in; - cf.width = ntohl(p_hdr->width); - cf.height = ntohl(p_hdr->height); - q_data->flags = ntohl(p_hdr->flags); - ctx->colorspace = ntohl(p_hdr->colorspace); - ctx->xfer_func = ntohl(p_hdr->xfer_func); - ctx->ycbcr_enc = ntohl(p_hdr->ycbcr_enc); - ctx->quantization = ntohl(p_hdr->quantization); - cf.rlc_data = (__be16 *)(p_in + sizeof(*p_hdr)); - - if (p_hdr->magic1 != VICODEC_MAGIC1 || - p_hdr->magic2 != VICODEC_MAGIC2 || - ntohl(p_hdr->version) != VICODEC_VERSION || - cf.width < VICODEC_MIN_WIDTH || - cf.width > VICODEC_MAX_WIDTH || - cf.height < VICODEC_MIN_HEIGHT || - cf.height > VICODEC_MAX_HEIGHT || - (cf.width & 7) || (cf.height & 7)) - return -EINVAL; - - /* TODO: support resolution changes */ - if (cf.width != q_data->width || cf.height != q_data->height) - return -EINVAL; - - decode_frame(&cf, &ctx->ref_frame, q_data->flags); - memcpy(p_out, ctx->ref_frame.luma, size); - p_out += size; - - switch (q_data->fourcc) { - case V4L2_PIX_FMT_YUV420: - memcpy(p_out, ctx->ref_frame.cb, size / 4); - p_out += size / 4; - memcpy(p_out, ctx->ref_frame.cr, size / 4); - break; - case V4L2_PIX_FMT_YVU420: - memcpy(p_out, ctx->ref_frame.cr, size / 4); - p_out += size / 4; - memcpy(p_out, ctx->ref_frame.cb, size / 4); - break; - case V4L2_PIX_FMT_NV12: - for (i = 0, p = p_out; i < size / 4; i++, p += 2) - *p = ctx->ref_frame.cb[i]; - for (i = 0, p = p_out + 1; i < size / 4; i++, p += 2) - *p = ctx->ref_frame.cr[i]; - break; - case V4L2_PIX_FMT_NV21: - for (i = 0, p = p_out; i < size / 4; i++, p += 2) - *p = ctx->ref_frame.cr[i]; - for (i = 0, p = p_out + 1; i < size / 4; i++, p += 2) - *p = ctx->ref_frame.cb[i]; - break; - } - return 0; -} - static int device_process(struct vicodec_ctx *ctx, struct vb2_v4l2_buffer *in_vb, struct vb2_v4l2_buffer *out_vb) { struct vicodec_dev *dev = ctx->dev; - struct vicodec_q_data *q_out, *q_cap; + struct vicodec_q_data *q_cap; + struct v4l2_fwht_state *state = &ctx->state; u8 *p_in, *p_out; int ret; - q_out = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); q_cap = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); if (ctx->is_enc) p_in = vb2_plane_vaddr(&in_vb->vb2_buf, 0); else - p_in = ctx->compressed_frame; + p_in = state->compressed_frame; p_out = vb2_plane_vaddr(&out_vb->vb2_buf, 0); if (!p_in || !p_out) { v4l2_err(&dev->v4l2_dev, @@ -310,17 +173,20 @@ static int device_process(struct vicodec_ctx *ctx, } if (ctx->is_enc) { - struct cframe_hdr *p_hdr = (struct cframe_hdr *)p_out; + struct vicodec_q_data *q_out; - encode(ctx, q_out, p_in, p_out); - vb2_set_plane_payload(&out_vb->vb2_buf, 0, - sizeof(*p_hdr) + ntohl(p_hdr->size)); + q_out = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); + state->info = q_out->info; + ret = v4l2_fwht_encode(state, p_in, p_out); + if (ret < 0) + return ret; + vb2_set_plane_payload(&out_vb->vb2_buf, 0, ret); } else { - ret = decode(ctx, q_cap, p_in, p_out); - if (ret) + state->info = q_cap->info; + ret = v4l2_fwht_decode(state, p_in, p_out); + if (ret < 0) return ret; - vb2_set_plane_payload(&out_vb->vb2_buf, 0, - q_cap->width * q_cap->height * 3 / 2); + vb2_set_plane_payload(&out_vb->vb2_buf, 0, q_cap->sizeimage); } out_vb->sequence = q_cap->sequence++; @@ -446,10 +312,11 @@ restart: copy = sizeof(magic) - ctx->comp_magic_cnt; if (p_out + sz - p < copy) copy = p_out + sz - p; - memcpy(ctx->compressed_frame + ctx->comp_magic_cnt, + memcpy(ctx->state.compressed_frame + ctx->comp_magic_cnt, p, copy); ctx->comp_magic_cnt += copy; - if (!memcmp(ctx->compressed_frame, magic, ctx->comp_magic_cnt)) { + if (!memcmp(ctx->state.compressed_frame, magic, + ctx->comp_magic_cnt)) { p += copy; state = VB2_BUF_STATE_DONE; break; @@ -462,17 +329,18 @@ restart: } ctx->comp_size = sizeof(magic); } - if (ctx->comp_size < sizeof(struct cframe_hdr)) { - struct cframe_hdr *p_hdr = (struct cframe_hdr *)ctx->compressed_frame; - u32 copy = sizeof(struct cframe_hdr) - ctx->comp_size; + if (ctx->comp_size < sizeof(struct fwht_cframe_hdr)) { + struct fwht_cframe_hdr *p_hdr = + (struct fwht_cframe_hdr *)ctx->state.compressed_frame; + u32 copy = sizeof(struct fwht_cframe_hdr) - ctx->comp_size; if (copy > p_out + sz - p) copy = p_out + sz - p; - memcpy(ctx->compressed_frame + ctx->comp_size, + memcpy(ctx->state.compressed_frame + ctx->comp_size, p, copy); p += copy; ctx->comp_size += copy; - if (ctx->comp_size < sizeof(struct cframe_hdr)) { + if (ctx->comp_size < sizeof(struct fwht_cframe_hdr)) { job_remove_out_buf(ctx, state); goto restart; } @@ -485,7 +353,7 @@ restart: if (copy > p_out + sz - p) copy = p_out + sz - p; - memcpy(ctx->compressed_frame + ctx->comp_size, + memcpy(ctx->state.compressed_frame + ctx->comp_size, p, copy); p += copy; ctx->comp_size += copy; @@ -497,8 +365,8 @@ restart: ctx->cur_buf_offset = p - p_out; ctx->comp_has_frame = true; ctx->comp_has_next_frame = false; - if (sz - ctx->cur_buf_offset >= sizeof(struct cframe_hdr)) { - struct cframe_hdr *p_hdr = (struct cframe_hdr *)p; + if (sz - ctx->cur_buf_offset >= sizeof(struct fwht_cframe_hdr)) { + struct fwht_cframe_hdr *p_hdr = (struct fwht_cframe_hdr *)p; u32 frame_size = ntohl(p_hdr->size); u32 remaining = sz - ctx->cur_buf_offset - sizeof(*p_hdr); @@ -508,26 +376,18 @@ restart: return 1; } -static void job_abort(void *priv) -{ - struct vicodec_ctx *ctx = priv; - - /* Will cancel the transaction in the next interrupt handler */ - ctx->aborting = 1; -} - /* * video ioctls */ -static u32 find_fmt(u32 fmt) +static const struct v4l2_fwht_pixfmt_info *find_fmt(u32 fmt) { - unsigned int i; + const struct v4l2_fwht_pixfmt_info *info = + v4l2_fwht_find_pixfmt(fmt); - for (i = 0; i < ARRAY_SIZE(pixfmts_yuv); i++) - if (pixfmts_yuv[i] == fmt) - return fmt; - return pixfmts_yuv[0]; + if (!info) + info = v4l2_fwht_get_pixfmt(0); + return info; } static int vidioc_querycap(struct file *file, void *priv, @@ -547,19 +407,25 @@ static int vidioc_querycap(struct file *file, void *priv, static int enum_fmt(struct v4l2_fmtdesc *f, bool is_enc, bool is_out) { - bool is_yuv = (is_enc && is_out) || (!is_enc && !is_out); + bool is_uncomp = (is_enc && is_out) || (!is_enc && !is_out); if (V4L2_TYPE_IS_MULTIPLANAR(f->type) && !multiplanar) return -EINVAL; if (!V4L2_TYPE_IS_MULTIPLANAR(f->type) && multiplanar) return -EINVAL; - if (f->index >= (is_yuv ? ARRAY_SIZE(pixfmts_yuv) : 1)) - return -EINVAL; - if (is_yuv) - f->pixelformat = pixfmts_yuv[f->index]; - else + if (is_uncomp) { + const struct v4l2_fwht_pixfmt_info *info = + v4l2_fwht_get_pixfmt(f->index); + + if (!info) + return -EINVAL; + f->pixelformat = info->id; + } else { + if (f->index) + return -EINVAL; f->pixelformat = V4L2_PIX_FMT_FWHT; + } return 0; } @@ -585,12 +451,14 @@ static int vidioc_g_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f) struct vicodec_q_data *q_data; struct v4l2_pix_format_mplane *pix_mp; struct v4l2_pix_format *pix; + const struct v4l2_fwht_pixfmt_info *info; vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); if (!vq) return -EINVAL; q_data = get_q_data(ctx, f->type); + info = q_data->info; switch (f->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: @@ -601,16 +469,13 @@ static int vidioc_g_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f) pix->width = q_data->width; pix->height = q_data->height; pix->field = V4L2_FIELD_NONE; - pix->pixelformat = q_data->fourcc; - if (q_data->fourcc == V4L2_PIX_FMT_FWHT) - pix->bytesperline = 0; - else - pix->bytesperline = q_data->width; + pix->pixelformat = info->id; + pix->bytesperline = q_data->width * info->bytesperline_mult; pix->sizeimage = q_data->sizeimage; - pix->colorspace = ctx->colorspace; - pix->xfer_func = ctx->xfer_func; - pix->ycbcr_enc = ctx->ycbcr_enc; - pix->quantization = ctx->quantization; + pix->colorspace = ctx->state.colorspace; + pix->xfer_func = ctx->state.xfer_func; + pix->ycbcr_enc = ctx->state.ycbcr_enc; + pix->quantization = ctx->state.quantization; break; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: @@ -621,17 +486,15 @@ static int vidioc_g_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f) pix_mp->width = q_data->width; pix_mp->height = q_data->height; pix_mp->field = V4L2_FIELD_NONE; - pix_mp->pixelformat = q_data->fourcc; + pix_mp->pixelformat = info->id; pix_mp->num_planes = 1; - if (q_data->fourcc == V4L2_PIX_FMT_FWHT) - pix_mp->plane_fmt[0].bytesperline = 0; - else - pix_mp->plane_fmt[0].bytesperline = q_data->width; + pix_mp->plane_fmt[0].bytesperline = + q_data->width * info->bytesperline_mult; pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage; - pix_mp->colorspace = ctx->colorspace; - pix_mp->xfer_func = ctx->xfer_func; - pix_mp->ycbcr_enc = ctx->ycbcr_enc; - pix_mp->quantization = ctx->quantization; + pix_mp->colorspace = ctx->state.colorspace; + pix_mp->xfer_func = ctx->state.xfer_func; + pix_mp->ycbcr_enc = ctx->state.ycbcr_enc; + pix_mp->quantization = ctx->state.quantization; memset(pix_mp->reserved, 0, sizeof(pix_mp->reserved)); memset(pix_mp->plane_fmt[0].reserved, 0, sizeof(pix_mp->plane_fmt[0].reserved)); @@ -658,40 +521,44 @@ static int vidioc_try_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f) { struct v4l2_pix_format_mplane *pix_mp; struct v4l2_pix_format *pix; + struct v4l2_plane_pix_format *plane; + const struct v4l2_fwht_pixfmt_info *info = &pixfmt_fwht; switch (f->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: case V4L2_BUF_TYPE_VIDEO_OUTPUT: pix = &f->fmt.pix; + if (pix->pixelformat != V4L2_PIX_FMT_FWHT) + info = find_fmt(pix->pixelformat); pix->width = clamp(pix->width, MIN_WIDTH, MAX_WIDTH) & ~7; pix->height = clamp(pix->height, MIN_HEIGHT, MAX_HEIGHT) & ~7; - pix->bytesperline = pix->width; - pix->sizeimage = pix->width * pix->height * 3 / 2; pix->field = V4L2_FIELD_NONE; - if (pix->pixelformat == V4L2_PIX_FMT_FWHT) { - pix->bytesperline = 0; - pix->sizeimage += sizeof(struct cframe_hdr); - } + pix->bytesperline = + pix->width * info->bytesperline_mult; + pix->sizeimage = pix->width * pix->height * + info->sizeimage_mult / info->sizeimage_div; + if (pix->pixelformat == V4L2_PIX_FMT_FWHT) + pix->sizeimage += sizeof(struct fwht_cframe_hdr); break; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: pix_mp = &f->fmt.pix_mp; + plane = pix_mp->plane_fmt; + if (pix_mp->pixelformat != V4L2_PIX_FMT_FWHT) + info = find_fmt(pix_mp->pixelformat); + pix_mp->num_planes = 1; pix_mp->width = clamp(pix_mp->width, MIN_WIDTH, MAX_WIDTH) & ~7; pix_mp->height = clamp(pix_mp->height, MIN_HEIGHT, MAX_HEIGHT) & ~7; - pix_mp->plane_fmt[0].bytesperline = pix_mp->width; - pix_mp->plane_fmt[0].sizeimage = - pix_mp->width * pix_mp->height * 3 / 2; pix_mp->field = V4L2_FIELD_NONE; - pix_mp->num_planes = 1; - if (pix_mp->pixelformat == V4L2_PIX_FMT_FWHT) { - pix_mp->plane_fmt[0].bytesperline = 0; - pix_mp->plane_fmt[0].sizeimage += - sizeof(struct cframe_hdr); - } + plane->bytesperline = + pix_mp->width * info->bytesperline_mult; + plane->sizeimage = pix_mp->width * pix_mp->height * + info->sizeimage_mult / info->sizeimage_div; + if (pix_mp->pixelformat == V4L2_PIX_FMT_FWHT) + plane->sizeimage += sizeof(struct fwht_cframe_hdr); memset(pix_mp->reserved, 0, sizeof(pix_mp->reserved)); - memset(pix_mp->plane_fmt[0].reserved, 0, - sizeof(pix_mp->plane_fmt[0].reserved)); + memset(plane->reserved, 0, sizeof(plane->reserved)); break; default: return -EINVAL; @@ -713,25 +580,22 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, return -EINVAL; pix = &f->fmt.pix; pix->pixelformat = ctx->is_enc ? V4L2_PIX_FMT_FWHT : - find_fmt(f->fmt.pix.pixelformat); - pix->colorspace = ctx->colorspace; - pix->xfer_func = ctx->xfer_func; - pix->ycbcr_enc = ctx->ycbcr_enc; - pix->quantization = ctx->quantization; + find_fmt(f->fmt.pix.pixelformat)->id; + pix->colorspace = ctx->state.colorspace; + pix->xfer_func = ctx->state.xfer_func; + pix->ycbcr_enc = ctx->state.ycbcr_enc; + pix->quantization = ctx->state.quantization; break; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: if (!multiplanar) return -EINVAL; pix_mp = &f->fmt.pix_mp; pix_mp->pixelformat = ctx->is_enc ? V4L2_PIX_FMT_FWHT : - find_fmt(pix_mp->pixelformat); - pix_mp->colorspace = ctx->colorspace; - pix_mp->xfer_func = ctx->xfer_func; - pix_mp->ycbcr_enc = ctx->ycbcr_enc; - pix_mp->quantization = ctx->quantization; - memset(pix_mp->reserved, 0, sizeof(pix_mp->reserved)); - memset(pix_mp->plane_fmt[0].reserved, 0, - sizeof(pix_mp->plane_fmt[0].reserved)); + find_fmt(pix_mp->pixelformat)->id; + pix_mp->colorspace = ctx->state.colorspace; + pix_mp->xfer_func = ctx->state.xfer_func; + pix_mp->ycbcr_enc = ctx->state.ycbcr_enc; + pix_mp->quantization = ctx->state.quantization; break; default: return -EINVAL; @@ -753,7 +617,7 @@ static int vidioc_try_fmt_vid_out(struct file *file, void *priv, return -EINVAL; pix = &f->fmt.pix; pix->pixelformat = !ctx->is_enc ? V4L2_PIX_FMT_FWHT : - find_fmt(pix->pixelformat); + find_fmt(pix->pixelformat)->id; if (!pix->colorspace) pix->colorspace = V4L2_COLORSPACE_REC709; break; @@ -762,7 +626,7 @@ static int vidioc_try_fmt_vid_out(struct file *file, void *priv, return -EINVAL; pix_mp = &f->fmt.pix_mp; pix_mp->pixelformat = !ctx->is_enc ? V4L2_PIX_FMT_FWHT : - find_fmt(pix_mp->pixelformat); + find_fmt(pix_mp->pixelformat)->id; if (!pix_mp->colorspace) pix_mp->colorspace = V4L2_COLORSPACE_REC709; break; @@ -795,14 +659,17 @@ static int vidioc_s_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f) pix = &f->fmt.pix; if (ctx->is_enc && V4L2_TYPE_IS_OUTPUT(f->type)) fmt_changed = - q_data->fourcc != pix->pixelformat || + q_data->info->id != pix->pixelformat || q_data->width != pix->width || q_data->height != pix->height; if (vb2_is_busy(vq) && fmt_changed) return -EBUSY; - q_data->fourcc = pix->pixelformat; + if (pix->pixelformat == V4L2_PIX_FMT_FWHT) + q_data->info = &pixfmt_fwht; + else + q_data->info = find_fmt(pix->pixelformat); q_data->width = pix->width; q_data->height = pix->height; q_data->sizeimage = pix->sizeimage; @@ -812,14 +679,17 @@ static int vidioc_s_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f) pix_mp = &f->fmt.pix_mp; if (ctx->is_enc && V4L2_TYPE_IS_OUTPUT(f->type)) fmt_changed = - q_data->fourcc != pix_mp->pixelformat || + q_data->info->id != pix_mp->pixelformat || q_data->width != pix_mp->width || q_data->height != pix_mp->height; if (vb2_is_busy(vq) && fmt_changed) return -EBUSY; - q_data->fourcc = pix_mp->pixelformat; + if (pix_mp->pixelformat == V4L2_PIX_FMT_FWHT) + q_data->info = &pixfmt_fwht; + else + q_data->info = find_fmt(pix_mp->pixelformat); q_data->width = pix_mp->width; q_data->height = pix_mp->height; q_data->sizeimage = pix_mp->plane_fmt[0].sizeimage; @@ -830,7 +700,7 @@ static int vidioc_s_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f) dprintk(ctx->dev, "Setting format for type %d, wxh: %dx%d, fourcc: %08x\n", - f->type, q_data->width, q_data->height, q_data->fourcc); + f->type, q_data->width, q_data->height, q_data->info->id); return 0; } @@ -865,18 +735,18 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *priv, case V4L2_BUF_TYPE_VIDEO_CAPTURE: case V4L2_BUF_TYPE_VIDEO_OUTPUT: pix = &f->fmt.pix; - ctx->colorspace = pix->colorspace; - ctx->xfer_func = pix->xfer_func; - ctx->ycbcr_enc = pix->ycbcr_enc; - ctx->quantization = pix->quantization; + ctx->state.colorspace = pix->colorspace; + ctx->state.xfer_func = pix->xfer_func; + ctx->state.ycbcr_enc = pix->ycbcr_enc; + ctx->state.quantization = pix->quantization; break; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: pix_mp = &f->fmt.pix_mp; - ctx->colorspace = pix_mp->colorspace; - ctx->xfer_func = pix_mp->xfer_func; - ctx->ycbcr_enc = pix_mp->ycbcr_enc; - ctx->quantization = pix_mp->quantization; + ctx->state.colorspace = pix_mp->colorspace; + ctx->state.xfer_func = pix_mp->xfer_func; + ctx->state.ycbcr_enc = pix_mp->ycbcr_enc; + ctx->state.quantization = pix_mp->quantization; break; default: break; @@ -962,7 +832,7 @@ static int vicodec_enum_framesizes(struct file *file, void *fh, case V4L2_PIX_FMT_FWHT: break; default: - if (find_fmt(fsize->pixel_format) == fsize->pixel_format) + if (find_fmt(fsize->pixel_format)->id == fsize->pixel_format) break; return -EINVAL; } @@ -1119,30 +989,35 @@ static int vicodec_start_streaming(struct vb2_queue *q, { struct vicodec_ctx *ctx = vb2_get_drv_priv(q); struct vicodec_q_data *q_data = get_q_data(ctx, q->type); + struct v4l2_fwht_state *state = &ctx->state; unsigned int size = q_data->width * q_data->height; + const struct v4l2_fwht_pixfmt_info *info = q_data->info; + unsigned int chroma_div = info->width_div * info->height_div; q_data->sequence = 0; if (!V4L2_TYPE_IS_OUTPUT(q->type)) return 0; - ctx->ref_frame.width = ctx->ref_frame.height = 0; - ctx->ref_frame.luma = kvmalloc(size * 3 / 2, GFP_KERNEL); - ctx->comp_max_size = size * 3 / 2 + sizeof(struct cframe_hdr); - ctx->compressed_frame = kvmalloc(ctx->comp_max_size, GFP_KERNEL); - if (!ctx->ref_frame.luma || !ctx->compressed_frame) { - kvfree(ctx->ref_frame.luma); - kvfree(ctx->compressed_frame); + state->width = q_data->width; + state->height = q_data->height; + state->ref_frame.width = state->ref_frame.height = 0; + state->ref_frame.luma = kvmalloc(size + 2 * size / chroma_div, + GFP_KERNEL); + ctx->comp_max_size = size + 2 * size / chroma_div + + sizeof(struct fwht_cframe_hdr); + state->compressed_frame = kvmalloc(ctx->comp_max_size, GFP_KERNEL); + if (!state->ref_frame.luma || !state->compressed_frame) { + kvfree(state->ref_frame.luma); + kvfree(state->compressed_frame); vicodec_return_bufs(q, VB2_BUF_STATE_QUEUED); return -ENOMEM; } - ctx->ref_frame.cb = ctx->ref_frame.luma + size; - ctx->ref_frame.cr = ctx->ref_frame.cb + size / 4; + state->ref_frame.cb = state->ref_frame.luma + size; + state->ref_frame.cr = state->ref_frame.cb + size / chroma_div; ctx->last_src_buf = NULL; ctx->last_dst_buf = NULL; - v4l2_ctrl_grab(ctx->ctrl_gop_size, true); - ctx->gop_size = v4l2_ctrl_g_ctrl(ctx->ctrl_gop_size); - ctx->gop_cnt = 0; + state->gop_cnt = 0; ctx->cur_buf_offset = 0; ctx->comp_size = 0; ctx->comp_magic_cnt = 0; @@ -1160,9 +1035,8 @@ static void vicodec_stop_streaming(struct vb2_queue *q) if (!V4L2_TYPE_IS_OUTPUT(q->type)) return; - kvfree(ctx->ref_frame.luma); - kvfree(ctx->compressed_frame); - v4l2_ctrl_grab(ctx->ctrl_gop_size, false); + kvfree(ctx->state.ref_frame.luma); + kvfree(ctx->state.compressed_frame); } static const struct vb2_ops vicodec_qops = { @@ -1211,6 +1085,55 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, return vb2_queue_init(dst_vq); } +#define VICODEC_CID_CUSTOM_BASE (V4L2_CID_MPEG_BASE | 0xf000) +#define VICODEC_CID_I_FRAME_QP (VICODEC_CID_CUSTOM_BASE + 0) +#define VICODEC_CID_P_FRAME_QP (VICODEC_CID_CUSTOM_BASE + 1) + +static int vicodec_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct vicodec_ctx *ctx = container_of(ctrl->handler, + struct vicodec_ctx, hdl); + + switch (ctrl->id) { + case V4L2_CID_MPEG_VIDEO_GOP_SIZE: + ctx->state.gop_size = ctrl->val; + return 0; + case VICODEC_CID_I_FRAME_QP: + ctx->state.i_frame_qp = ctrl->val; + return 0; + case VICODEC_CID_P_FRAME_QP: + ctx->state.p_frame_qp = ctrl->val; + return 0; + } + return -EINVAL; +} + +static struct v4l2_ctrl_ops vicodec_ctrl_ops = { + .s_ctrl = vicodec_s_ctrl, +}; + +static const struct v4l2_ctrl_config vicodec_ctrl_i_frame = { + .ops = &vicodec_ctrl_ops, + .id = VICODEC_CID_I_FRAME_QP, + .name = "FWHT I-Frame QP Value", + .type = V4L2_CTRL_TYPE_INTEGER, + .min = 1, + .max = 31, + .def = 20, + .step = 1, +}; + +static const struct v4l2_ctrl_config vicodec_ctrl_p_frame = { + .ops = &vicodec_ctrl_ops, + .id = VICODEC_CID_P_FRAME_QP, + .name = "FWHT P-Frame QP Value", + .type = V4L2_CTRL_TYPE_INTEGER, + .min = 1, + .max = 31, + .def = 20, + .step = 1, +}; + /* * File operations */ @@ -1239,9 +1162,10 @@ static int vicodec_open(struct file *file) ctx->dev = dev; hdl = &ctx->hdl; v4l2_ctrl_handler_init(hdl, 4); - ctx->ctrl_gop_size = v4l2_ctrl_new_std(hdl, NULL, - V4L2_CID_MPEG_VIDEO_GOP_SIZE, - 1, 16, 1, 10); + v4l2_ctrl_new_std(hdl, &vicodec_ctrl_ops, V4L2_CID_MPEG_VIDEO_GOP_SIZE, + 1, 16, 1, 10); + v4l2_ctrl_new_custom(hdl, &vicodec_ctrl_i_frame, NULL); + v4l2_ctrl_new_custom(hdl, &vicodec_ctrl_p_frame, NULL); if (hdl->error) { rc = hdl->error; v4l2_ctrl_handler_free(hdl); @@ -1251,25 +1175,34 @@ static int vicodec_open(struct file *file) ctx->fh.ctrl_handler = hdl; v4l2_ctrl_handler_setup(hdl); - ctx->q_data[V4L2_M2M_SRC].fourcc = - ctx->is_enc ? V4L2_PIX_FMT_YUV420 : V4L2_PIX_FMT_FWHT; + ctx->q_data[V4L2_M2M_SRC].info = + ctx->is_enc ? v4l2_fwht_get_pixfmt(0) : &pixfmt_fwht; ctx->q_data[V4L2_M2M_SRC].width = 1280; ctx->q_data[V4L2_M2M_SRC].height = 720; - size = 1280 * 720 * 3 / 2; - ctx->q_data[V4L2_M2M_SRC].sizeimage = size; + size = 1280 * 720 * ctx->q_data[V4L2_M2M_SRC].info->sizeimage_mult / + ctx->q_data[V4L2_M2M_SRC].info->sizeimage_div; + if (ctx->is_enc) + ctx->q_data[V4L2_M2M_SRC].sizeimage = size; + else + ctx->q_data[V4L2_M2M_SRC].sizeimage = + size + sizeof(struct fwht_cframe_hdr); ctx->q_data[V4L2_M2M_DST] = ctx->q_data[V4L2_M2M_SRC]; - ctx->q_data[V4L2_M2M_DST].fourcc = - ctx->is_enc ? V4L2_PIX_FMT_FWHT : V4L2_PIX_FMT_YUV420; - ctx->colorspace = V4L2_COLORSPACE_REC709; + ctx->q_data[V4L2_M2M_DST].info = + ctx->is_enc ? &pixfmt_fwht : v4l2_fwht_get_pixfmt(0); + size = 1280 * 720 * ctx->q_data[V4L2_M2M_DST].info->sizeimage_mult / + ctx->q_data[V4L2_M2M_DST].info->sizeimage_div; + if (ctx->is_enc) + ctx->q_data[V4L2_M2M_DST].sizeimage = + size + sizeof(struct fwht_cframe_hdr); + else + ctx->q_data[V4L2_M2M_DST].sizeimage = size; + ctx->state.colorspace = V4L2_COLORSPACE_REC709; - size += sizeof(struct cframe_hdr); if (ctx->is_enc) { - ctx->q_data[V4L2_M2M_DST].sizeimage = size; ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->enc_dev, ctx, &queue_init); ctx->lock = &dev->enc_lock; } else { - ctx->q_data[V4L2_M2M_SRC].sizeimage = size; ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->dec_dev, ctx, &queue_init); ctx->lock = &dev->dec_lock; @@ -1327,7 +1260,6 @@ static const struct video_device vicodec_videodev = { static const struct v4l2_m2m_ops m2m_ops = { .device_run = device_run, - .job_abort = job_abort, .job_ready = job_ready, }; @@ -1350,7 +1282,7 @@ static int vicodec_probe(struct platform_device *pdev) #ifdef CONFIG_MEDIA_CONTROLLER dev->mdev.dev = &pdev->dev; - strlcpy(dev->mdev.model, "vicodec", sizeof(dev->mdev.model)); + strscpy(dev->mdev.model, "vicodec", sizeof(dev->mdev.model)); media_device_init(&dev->mdev); dev->v4l2_dev.mdev = &dev->mdev; #endif @@ -1378,7 +1310,7 @@ static int vicodec_probe(struct platform_device *pdev) vfd = &dev->enc_vfd; vfd->lock = &dev->enc_mutex; vfd->v4l2_dev = &dev->v4l2_dev; - strlcpy(vfd->name, "vicodec-enc", sizeof(vfd->name)); + strscpy(vfd->name, "vicodec-enc", sizeof(vfd->name)); v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD); v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD); video_set_drvdata(vfd, dev); @@ -1395,7 +1327,7 @@ static int vicodec_probe(struct platform_device *pdev) vfd = &dev->dec_vfd; vfd->lock = &dev->dec_mutex; vfd->v4l2_dev = &dev->v4l2_dev; - strlcpy(vfd->name, "vicodec-dec", sizeof(vfd->name)); + strscpy(vfd->name, "vicodec-dec", sizeof(vfd->name)); v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD); v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD); video_set_drvdata(vfd, dev); diff --git a/drivers/media/platform/video-mux.c b/drivers/media/platform/video-mux.c index c01e1592ad0a..c33900e3c23e 100644 --- a/drivers/media/platform/video-mux.c +++ b/drivers/media/platform/video-mux.c @@ -21,8 +21,10 @@ #include <linux/of.h> #include <linux/of_graph.h> #include <linux/platform_device.h> +#include <linux/slab.h> #include <media/v4l2-async.h> #include <media/v4l2-device.h> +#include <media/v4l2-fwnode.h> #include <media/v4l2-subdev.h> struct video_mux { @@ -316,6 +318,38 @@ static const struct v4l2_subdev_ops video_mux_subdev_ops = { .video = &video_mux_subdev_video_ops, }; +static int video_mux_parse_endpoint(struct device *dev, + struct v4l2_fwnode_endpoint *vep, + struct v4l2_async_subdev *asd) +{ + /* + * it's not an error if remote is missing on a video-mux + * input port, return -ENOTCONN to skip this endpoint with + * no error. + */ + return fwnode_device_is_available(asd->match.fwnode) ? 0 : -ENOTCONN; +} + +static int video_mux_async_register(struct video_mux *vmux, + unsigned int num_input_pads) +{ + unsigned int i, *ports; + int ret; + + ports = kcalloc(num_input_pads, sizeof(*ports), GFP_KERNEL); + if (!ports) + return -ENOMEM; + for (i = 0; i < num_input_pads; i++) + ports[i] = i; + + ret = v4l2_async_register_fwnode_subdev( + &vmux->subdev, sizeof(struct v4l2_async_subdev), + ports, num_input_pads, video_mux_parse_endpoint); + + kfree(ports); + return ret; +} + static int video_mux_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -333,7 +367,7 @@ static int video_mux_probe(struct platform_device *pdev) platform_set_drvdata(pdev, vmux); v4l2_subdev_init(&vmux->subdev, &video_mux_subdev_ops); - snprintf(vmux->subdev.name, sizeof(vmux->subdev.name), "%s", np->name); + snprintf(vmux->subdev.name, sizeof(vmux->subdev.name), "%pOFn", np); vmux->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; vmux->subdev.dev = dev; @@ -383,7 +417,7 @@ static int video_mux_probe(struct platform_device *pdev) vmux->subdev.entity.ops = &video_mux_ops; - return v4l2_async_register_subdev(&vmux->subdev); + return video_mux_async_register(vmux, num_pads - 1); } static int video_mux_remove(struct platform_device *pdev) diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c index 462099a141e4..60c522ee2e03 100644 --- a/drivers/media/platform/vim2m.c +++ b/drivers/media/platform/vim2m.c @@ -1038,7 +1038,7 @@ static int vim2m_probe(struct platform_device *pdev) #ifdef CONFIG_MEDIA_CONTROLLER dev->mdev.dev = &pdev->dev; - strlcpy(dev->mdev.model, "vim2m", sizeof(dev->mdev.model)); + strscpy(dev->mdev.model, "vim2m", sizeof(dev->mdev.model)); media_device_init(&dev->mdev); dev->v4l2_dev.mdev = &dev->mdev; diff --git a/drivers/media/platform/vimc/vimc-capture.c b/drivers/media/platform/vimc/vimc-capture.c index ec68feaac378..3f7e9ed56633 100644 --- a/drivers/media/platform/vimc/vimc-capture.c +++ b/drivers/media/platform/vimc/vimc-capture.c @@ -71,8 +71,8 @@ static int vimc_cap_querycap(struct file *file, void *priv, { struct vimc_cap_device *vcap = video_drvdata(file); - strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver)); - strlcpy(cap->card, KBUILD_MODNAME, sizeof(cap->card)); + strscpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver)); + strscpy(cap->card, KBUILD_MODNAME, sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", vcap->vdev.v4l2_dev->name); @@ -476,7 +476,7 @@ static int vimc_cap_comp_bind(struct device *comp, struct device *master, vdev->queue = q; vdev->v4l2_dev = v4l2_dev; vdev->vfl_dir = VFL_DIR_RX; - strlcpy(vdev->name, pdata->entity_name, sizeof(vdev->name)); + strscpy(vdev->name, pdata->entity_name, sizeof(vdev->name)); video_set_drvdata(vdev, &vcap->ved); /* Register the video_device with the v4l2 and the media framework */ diff --git a/drivers/media/platform/vimc/vimc-common.c b/drivers/media/platform/vimc/vimc-common.c index 617415c224fe..dee1b9dfc4f6 100644 --- a/drivers/media/platform/vimc/vimc-common.c +++ b/drivers/media/platform/vimc/vimc-common.c @@ -430,7 +430,7 @@ int vimc_ent_sd_register(struct vimc_ent_device *ved, sd->entity.function = function; sd->entity.ops = &vimc_ent_sd_mops; sd->owner = THIS_MODULE; - strlcpy(sd->name, name, sizeof(sd->name)); + strscpy(sd->name, name, sizeof(sd->name)); v4l2_set_subdevdata(sd, ved); /* Expose this subdev to user space */ diff --git a/drivers/media/platform/vimc/vimc-core.c b/drivers/media/platform/vimc/vimc-core.c index 9246f265de31..ce809d2e3d53 100644 --- a/drivers/media/platform/vimc/vimc-core.c +++ b/drivers/media/platform/vimc/vimc-core.c @@ -259,7 +259,7 @@ static struct component_match *vimc_add_subdevs(struct vimc_device *vimc) dev_dbg(&vimc->pdev.dev, "new pdev for %s\n", vimc->pipe_cfg->ents[i].drv); - strlcpy(pdata.entity_name, vimc->pipe_cfg->ents[i].name, + strscpy(pdata.entity_name, vimc->pipe_cfg->ents[i].name, sizeof(pdata.entity_name)); vimc->subdevs[i] = platform_device_register_data(&vimc->pdev.dev, @@ -317,7 +317,7 @@ static int vimc_probe(struct platform_device *pdev) vimc->v4l2_dev.mdev = &vimc->mdev; /* Initialize media device */ - strlcpy(vimc->mdev.model, VIMC_MDEV_MODEL_NAME, + strscpy(vimc->mdev.model, VIMC_MDEV_MODEL_NAME, sizeof(vimc->mdev.model)); vimc->mdev.dev = &pdev->dev; media_device_init(&vimc->mdev); diff --git a/drivers/media/platform/vimc/vimc-sensor.c b/drivers/media/platform/vimc/vimc-sensor.c index b2b89315e7ba..edf4c85ae63d 100644 --- a/drivers/media/platform/vimc/vimc-sensor.c +++ b/drivers/media/platform/vimc/vimc-sensor.c @@ -317,6 +317,18 @@ static int vimc_sen_s_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_VFLIP: tpg_s_vflip(&vsen->tpg, ctrl->val); break; + case V4L2_CID_BRIGHTNESS: + tpg_s_brightness(&vsen->tpg, ctrl->val); + break; + case V4L2_CID_CONTRAST: + tpg_s_contrast(&vsen->tpg, ctrl->val); + break; + case V4L2_CID_HUE: + tpg_s_hue(&vsen->tpg, ctrl->val); + break; + case V4L2_CID_SATURATION: + tpg_s_saturation(&vsen->tpg, ctrl->val); + break; default: return -EINVAL; } @@ -378,6 +390,14 @@ static int vimc_sen_comp_bind(struct device *comp, struct device *master, V4L2_CID_VFLIP, 0, 1, 1, 0); v4l2_ctrl_new_std(&vsen->hdl, &vimc_sen_ctrl_ops, V4L2_CID_HFLIP, 0, 1, 1, 0); + v4l2_ctrl_new_std(&vsen->hdl, &vimc_sen_ctrl_ops, + V4L2_CID_BRIGHTNESS, 0, 255, 1, 128); + v4l2_ctrl_new_std(&vsen->hdl, &vimc_sen_ctrl_ops, + V4L2_CID_CONTRAST, 0, 255, 1, 128); + v4l2_ctrl_new_std(&vsen->hdl, &vimc_sen_ctrl_ops, + V4L2_CID_HUE, -128, 127, 1, 0); + v4l2_ctrl_new_std(&vsen->hdl, &vimc_sen_ctrl_ops, + V4L2_CID_SATURATION, 0, 255, 1, 128); vsen->sd.ctrl_handler = &vsen->hdl; if (vsen->hdl.error) { ret = vsen->hdl.error; diff --git a/drivers/media/platform/vivid/vivid-cec.c b/drivers/media/platform/vivid/vivid-cec.c index 71105fa4c5f9..4d822dbed972 100644 --- a/drivers/media/platform/vivid/vivid-cec.c +++ b/drivers/media/platform/vivid/vivid-cec.c @@ -241,11 +241,11 @@ static int vivid_received(struct cec_adapter *adap, struct cec_msg *msg) cec_ops_set_osd_string(msg, &disp_ctl, osd); switch (disp_ctl) { case CEC_OP_DISP_CTL_DEFAULT: - strcpy(dev->osd, osd); + strscpy(dev->osd, osd, sizeof(dev->osd)); dev->osd_jiffies = jiffies; break; case CEC_OP_DISP_CTL_UNTIL_CLEARED: - strcpy(dev->osd, osd); + strscpy(dev->osd, osd, sizeof(dev->osd)); dev->osd_jiffies = 0; break; case CEC_OP_DISP_CTL_CLEAR: diff --git a/drivers/media/platform/vivid/vivid-core.c b/drivers/media/platform/vivid/vivid-core.c index 31db363602e5..06961e7d8036 100644 --- a/drivers/media/platform/vivid/vivid-core.c +++ b/drivers/media/platform/vivid/vivid-core.c @@ -197,8 +197,8 @@ static int vidioc_querycap(struct file *file, void *priv, { struct vivid_dev *dev = video_drvdata(file); - strcpy(cap->driver, "vivid"); - strcpy(cap->card, "vivid"); + strscpy(cap->driver, "vivid", sizeof(cap->driver)); + strscpy(cap->card, "vivid", sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", dev->v4l2_dev.name); diff --git a/drivers/media/platform/vivid/vivid-core.h b/drivers/media/platform/vivid/vivid-core.h index 477c80a4d44c..cd4c8230563c 100644 --- a/drivers/media/platform/vivid/vivid-core.h +++ b/drivers/media/platform/vivid/vivid-core.h @@ -111,7 +111,7 @@ enum vivid_colorspace { VIVID_CS_170M, VIVID_CS_709, VIVID_CS_SRGB, - VIVID_CS_ADOBERGB, + VIVID_CS_OPRGB, VIVID_CS_2020, VIVID_CS_DCI_P3, VIVID_CS_240M, diff --git a/drivers/media/platform/vivid/vivid-ctrls.c b/drivers/media/platform/vivid/vivid-ctrls.c index 5429193fbb91..999aa101b150 100644 --- a/drivers/media/platform/vivid/vivid-ctrls.c +++ b/drivers/media/platform/vivid/vivid-ctrls.c @@ -348,7 +348,7 @@ static int vivid_vid_cap_s_ctrl(struct v4l2_ctrl *ctrl) V4L2_COLORSPACE_SMPTE170M, V4L2_COLORSPACE_REC709, V4L2_COLORSPACE_SRGB, - V4L2_COLORSPACE_ADOBERGB, + V4L2_COLORSPACE_OPRGB, V4L2_COLORSPACE_BT2020, V4L2_COLORSPACE_DCI_P3, V4L2_COLORSPACE_SMPTE240M, @@ -729,7 +729,7 @@ static const char * const vivid_ctrl_colorspace_strings[] = { "SMPTE 170M", "Rec. 709", "sRGB", - "AdobeRGB", + "opRGB", "BT.2020", "DCI-P3", "SMPTE 240M", @@ -752,7 +752,7 @@ static const char * const vivid_ctrl_xfer_func_strings[] = { "Default", "Rec. 709", "sRGB", - "AdobeRGB", + "opRGB", "SMPTE 240M", "None", "DCI-P3", diff --git a/drivers/media/platform/vivid/vivid-osd.c b/drivers/media/platform/vivid/vivid-osd.c index bbbc1b6938a5..1a89593b0c86 100644 --- a/drivers/media/platform/vivid/vivid-osd.c +++ b/drivers/media/platform/vivid/vivid-osd.c @@ -110,7 +110,7 @@ static int vivid_fb_get_fix(struct vivid_dev *dev, struct fb_fix_screeninfo *fix { dprintk(dev, 1, "vivid_fb_get_fix\n"); memset(fix, 0, sizeof(struct fb_fix_screeninfo)); - strlcpy(fix->id, "vioverlay fb", sizeof(fix->id)); + strscpy(fix->id, "vioverlay fb", sizeof(fix->id)); fix->smem_start = dev->video_pbase; fix->smem_len = dev->video_buffer_size; fix->type = FB_TYPE_PACKED_PIXELS; diff --git a/drivers/media/platform/vivid/vivid-radio-common.c b/drivers/media/platform/vivid/vivid-radio-common.c index 7c8efe38ff5b..138c7bce68b1 100644 --- a/drivers/media/platform/vivid/vivid-radio-common.c +++ b/drivers/media/platform/vivid/vivid-radio-common.c @@ -76,10 +76,10 @@ void vivid_radio_rds_init(struct vivid_dev *dev) rds->ta = dev->radio_tx_rds_ta->cur.val; rds->tp = dev->radio_tx_rds_tp->cur.val; rds->ms = dev->radio_tx_rds_ms->cur.val; - strlcpy(rds->psname, + strscpy(rds->psname, dev->radio_tx_rds_psname->p_cur.p_char, sizeof(rds->psname)); - strlcpy(rds->radiotext, + strscpy(rds->radiotext, dev->radio_tx_rds_radiotext->p_cur.p_char + alt * 64, sizeof(rds->radiotext)); v4l2_ctrl_unlock(dev->radio_tx_rds_pi); diff --git a/drivers/media/platform/vivid/vivid-radio-rx.c b/drivers/media/platform/vivid/vivid-radio-rx.c index 1f86d7d4f72f..232cab508f48 100644 --- a/drivers/media/platform/vivid/vivid-radio-rx.c +++ b/drivers/media/platform/vivid/vivid-radio-rx.c @@ -223,7 +223,7 @@ int vivid_radio_rx_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) if (vt->index > 0) return -EINVAL; - strlcpy(vt->name, "AM/FM/SW Receiver", sizeof(vt->name)); + strscpy(vt->name, "AM/FM/SW Receiver", sizeof(vt->name)); vt->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_FREQ_BANDS | V4L2_TUNER_CAP_RDS | (dev->radio_rx_rds_controls ? diff --git a/drivers/media/platform/vivid/vivid-radio-tx.c b/drivers/media/platform/vivid/vivid-radio-tx.c index 1a3749ba5e7e..049d40b948bb 100644 --- a/drivers/media/platform/vivid/vivid-radio-tx.c +++ b/drivers/media/platform/vivid/vivid-radio-tx.c @@ -103,7 +103,7 @@ int vidioc_g_modulator(struct file *file, void *fh, struct v4l2_modulator *a) if (a->index > 0) return -EINVAL; - strlcpy(a->name, "AM/FM/SW Transmitter", sizeof(a->name)); + strscpy(a->name, "AM/FM/SW Transmitter", sizeof(a->name)); a->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_FREQ_BANDS | V4L2_TUNER_CAP_RDS | (dev->radio_tx_rds_controls ? diff --git a/drivers/media/platform/vivid/vivid-rds-gen.c b/drivers/media/platform/vivid/vivid-rds-gen.c index 39ca9a56448c..b5b104ee64c9 100644 --- a/drivers/media/platform/vivid/vivid-rds-gen.c +++ b/drivers/media/platform/vivid/vivid-rds-gen.c @@ -147,11 +147,11 @@ void vivid_rds_gen_fill(struct vivid_rds_gen *rds, unsigned freq, snprintf(rds->psname, sizeof(rds->psname), "%6d.%1d", freq / 16, ((freq & 0xf) * 10) / 16); if (alt) - strlcpy(rds->radiotext, + strscpy(rds->radiotext, " The Radio Data System can switch between different Radio Texts ", sizeof(rds->radiotext)); else - strlcpy(rds->radiotext, + strscpy(rds->radiotext, "An example of Radio Text as transmitted by the Radio Data System", sizeof(rds->radiotext)); } diff --git a/drivers/media/platform/vivid/vivid-sdr-cap.c b/drivers/media/platform/vivid/vivid-sdr-cap.c index cfb7cb4d37a8..200b789a3f21 100644 --- a/drivers/media/platform/vivid/vivid-sdr-cap.c +++ b/drivers/media/platform/vivid/vivid-sdr-cap.c @@ -396,7 +396,7 @@ int vivid_sdr_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) { switch (vt->index) { case 0: - strlcpy(vt->name, "ADC", sizeof(vt->name)); + strscpy(vt->name, "ADC", sizeof(vt->name)); vt->type = V4L2_TUNER_ADC; vt->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS; @@ -404,7 +404,7 @@ int vivid_sdr_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) vt->rangehigh = bands_adc[2].rangehigh; return 0; case 1: - strlcpy(vt->name, "RF", sizeof(vt->name)); + strscpy(vt->name, "RF", sizeof(vt->name)); vt->type = V4L2_TUNER_RF; vt->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS; diff --git a/drivers/media/platform/vivid/vivid-vid-cap.c b/drivers/media/platform/vivid/vivid-vid-cap.c index 1599159f2574..6cf910a60ecf 100644 --- a/drivers/media/platform/vivid/vivid-vid-cap.c +++ b/drivers/media/platform/vivid/vivid-vid-cap.c @@ -51,7 +51,7 @@ static const struct vivid_fmt formats_ovl[] = { }; /* The number of discrete webcam framesizes */ -#define VIVID_WEBCAM_SIZES 5 +#define VIVID_WEBCAM_SIZES 6 /* The number of discrete webcam frameintervals */ #define VIVID_WEBCAM_IVALS (VIVID_WEBCAM_SIZES * 2) @@ -59,6 +59,7 @@ static const struct vivid_fmt formats_ovl[] = { static const struct v4l2_frmsize_discrete webcam_sizes[VIVID_WEBCAM_SIZES] = { { 320, 180 }, { 640, 360 }, + { 640, 480 }, { 1280, 720 }, { 1920, 1080 }, { 3840, 2160 }, @@ -74,9 +75,11 @@ static const struct v4l2_fract webcam_intervals[VIVID_WEBCAM_IVALS] = { { 1, 4 }, { 1, 5 }, { 1, 10 }, + { 2, 25 }, { 1, 15 }, { 1, 25 }, { 1, 30 }, + { 1, 40 }, { 1, 50 }, { 1, 60 }, }; @@ -1505,7 +1508,7 @@ int vivid_video_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) break; } } - strlcpy(vt->name, "TV Tuner", sizeof(vt->name)); + strscpy(vt->name, "TV Tuner", sizeof(vt->name)); return 0; } @@ -1722,7 +1725,7 @@ int vidioc_s_edid(struct file *file, void *_fh, return -E2BIG; } phys_addr = cec_get_edid_phys_addr(edid->edid, edid->blocks * 128, NULL); - ret = cec_phys_addr_validate(phys_addr, &phys_addr, NULL); + ret = v4l2_phys_addr_validate(phys_addr, &phys_addr, NULL); if (ret) return ret; @@ -1738,7 +1741,7 @@ set_phys_addr: for (i = 0; i < MAX_OUTPUTS && dev->cec_tx_adap[i]; i++) cec_s_phys_addr(dev->cec_tx_adap[i], - cec_phys_addr_for_input(phys_addr, i + 1), + v4l2_phys_addr_for_input(phys_addr, i + 1), false); return 0; } diff --git a/drivers/media/platform/vivid/vivid-vid-common.c b/drivers/media/platform/vivid/vivid-vid-common.c index be531caa2cdf..9645a91b8782 100644 --- a/drivers/media/platform/vivid/vivid-vid-common.c +++ b/drivers/media/platform/vivid/vivid-vid-common.c @@ -450,6 +450,34 @@ struct vivid_fmt vivid_formats[] = { .buffers = 1, }, { + .fourcc = V4L2_PIX_FMT_SBGGR16, /* Bayer BG/GR */ + .vdownsampling = { 1 }, + .bit_depth = { 16 }, + .planes = 1, + .buffers = 1, + }, + { + .fourcc = V4L2_PIX_FMT_SGBRG16, /* Bayer GB/RG */ + .vdownsampling = { 1 }, + .bit_depth = { 16 }, + .planes = 1, + .buffers = 1, + }, + { + .fourcc = V4L2_PIX_FMT_SGRBG16, /* Bayer GR/BG */ + .vdownsampling = { 1 }, + .bit_depth = { 16 }, + .planes = 1, + .buffers = 1, + }, + { + .fourcc = V4L2_PIX_FMT_SRGGB16, /* Bayer RG/GB */ + .vdownsampling = { 1 }, + .bit_depth = { 16 }, + .planes = 1, + .buffers = 1, + }, + { .fourcc = V4L2_PIX_FMT_HSV24, /* HSV 24bits */ .color_enc = TGP_COLOR_ENC_HSV, .vdownsampling = { 1 }, @@ -863,7 +891,7 @@ int vidioc_g_edid(struct file *file, void *_fh, if (edid->blocks > dev->edid_blocks - edid->start_block) edid->blocks = dev->edid_blocks - edid->start_block; if (adap) - cec_set_edid_phys_addr(dev->edid, dev->edid_blocks * 128, adap->phys_addr); + v4l2_set_edid_phys_addr(dev->edid, dev->edid_blocks * 128, adap->phys_addr); memcpy(edid->edid, dev->edid + edid->start_block * 128, edid->blocks * 128); return 0; } diff --git a/drivers/media/platform/vivid/vivid-vid-out.c b/drivers/media/platform/vivid/vivid-vid-out.c index 51fec66d8d45..50248e2176a0 100644 --- a/drivers/media/platform/vivid/vivid-vid-out.c +++ b/drivers/media/platform/vivid/vivid-vid-out.c @@ -413,7 +413,7 @@ int vivid_try_fmt_vid_out(struct file *file, void *priv, mp->colorspace = V4L2_COLORSPACE_SMPTE170M; } else if (mp->colorspace != V4L2_COLORSPACE_SMPTE170M && mp->colorspace != V4L2_COLORSPACE_REC709 && - mp->colorspace != V4L2_COLORSPACE_ADOBERGB && + mp->colorspace != V4L2_COLORSPACE_OPRGB && mp->colorspace != V4L2_COLORSPACE_BT2020 && mp->colorspace != V4L2_COLORSPACE_SRGB) { mp->colorspace = V4L2_COLORSPACE_REC709; diff --git a/drivers/media/platform/vsp1/vsp1_brx.c b/drivers/media/platform/vsp1/vsp1_brx.c index 359917b5d842..5e50178b057d 100644 --- a/drivers/media/platform/vsp1/vsp1_brx.c +++ b/drivers/media/platform/vsp1/vsp1_brx.c @@ -153,7 +153,7 @@ static int brx_set_format(struct v4l2_subdev *subdev, format = vsp1_entity_get_pad_format(&brx->entity, config, fmt->pad); *format = fmt->format; - /* Reset the compose rectangle */ + /* Reset the compose rectangle. */ if (fmt->pad != brx->entity.source_pad) { struct v4l2_rect *compose; @@ -164,7 +164,7 @@ static int brx_set_format(struct v4l2_subdev *subdev, compose->height = format->height; } - /* Propagate the format code to all pads */ + /* Propagate the format code to all pads. */ if (fmt->pad == BRX_PAD_SINK(0)) { unsigned int i; diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index b9c0f695d002..8d86f618ec77 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -770,6 +770,7 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int pipe_index, struct vsp1_device *vsp1 = dev_get_drvdata(dev); struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[pipe_index]; const struct vsp1_format_info *fmtinfo; + unsigned int chroma_hsub; struct vsp1_rwpf *rpf; if (rpf_index >= vsp1->info->rpf_count) @@ -810,10 +811,18 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int pipe_index, return -EINVAL; } + /* + * Only formats with three planes can affect the chroma planes pitch. + * All formats with two planes have a horizontal subsampling value of 2, + * but combine U and V in a single chroma plane, which thus results in + * the luma plane and chroma plane having the same pitch. + */ + chroma_hsub = (fmtinfo->planes == 3) ? fmtinfo->hsub : 1; + rpf->fmtinfo = fmtinfo; rpf->format.num_planes = fmtinfo->planes; rpf->format.plane_fmt[0].bytesperline = cfg->pitch; - rpf->format.plane_fmt[1].bytesperline = cfg->pitch; + rpf->format.plane_fmt[1].bytesperline = cfg->pitch / chroma_hsub; rpf->alpha = cfg->alpha; rpf->mem.addr[0] = cfg->mem[0]; diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index b6619c9c18bb..c650e45bb0ad 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -242,7 +242,7 @@ static int vsp1_create_entities(struct vsp1_device *vsp1) mdev->dev = vsp1->dev; mdev->hw_revision = vsp1->version; - strlcpy(mdev->model, vsp1->info->model, sizeof(mdev->model)); + strscpy(mdev->model, vsp1->info->model, sizeof(mdev->model)); snprintf(mdev->bus_info, sizeof(mdev->bus_info), "platform:%s", dev_name(mdev->dev)); media_device_init(mdev); @@ -802,7 +802,7 @@ static int vsp1_probe(struct platform_device *pdev) platform_set_drvdata(pdev, vsp1); - /* I/O and IRQ resources (clock managed by the clock PM domain) */ + /* I/O and IRQ resources (clock managed by the clock PM domain). */ io = platform_get_resource(pdev, IORESOURCE_MEM, 0); vsp1->mmio = devm_ioremap_resource(&pdev->dev, io); if (IS_ERR(vsp1->mmio)) @@ -821,7 +821,7 @@ static int vsp1_probe(struct platform_device *pdev) return ret; } - /* FCP (optional) */ + /* FCP (optional). */ fcp_node = of_parse_phandle(pdev->dev.of_node, "renesas,fcp", 0); if (fcp_node) { vsp1->fcp = rcar_fcp_get(fcp_node); @@ -869,7 +869,7 @@ static int vsp1_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "IP version 0x%08x\n", vsp1->version); - /* Instanciate entities */ + /* Instantiate entities. */ ret = vsp1_create_entities(vsp1); if (ret < 0) { dev_err(&pdev->dev, "failed to create entities\n"); diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c index 36a29e13109e..a54ab528b060 100644 --- a/drivers/media/platform/vsp1/vsp1_entity.c +++ b/drivers/media/platform/vsp1/vsp1_entity.c @@ -404,7 +404,7 @@ int vsp1_subdev_set_pad_format(struct v4l2_subdev *subdev, format = vsp1_entity_get_pad_format(entity, config, entity->source_pad); *format = fmt->format; - /* Reset the crop and compose rectangles */ + /* Reset the crop and compose rectangles. */ selection = vsp1_entity_get_pad_selection(entity, config, fmt->pad, V4L2_SEL_TGT_CROP); selection->left = 0; diff --git a/drivers/media/platform/vsp1/vsp1_histo.c b/drivers/media/platform/vsp1/vsp1_histo.c index 5e15c8ff88d9..8b01e99acd20 100644 --- a/drivers/media/platform/vsp1/vsp1_histo.c +++ b/drivers/media/platform/vsp1/vsp1_histo.c @@ -429,8 +429,8 @@ static int histo_v4l2_querycap(struct file *file, void *fh, cap->device_caps = V4L2_CAP_META_CAPTURE | V4L2_CAP_STREAMING; - strlcpy(cap->driver, "vsp1", sizeof(cap->driver)); - strlcpy(cap->card, histo->video.name, sizeof(cap->card)); + strscpy(cap->driver, "vsp1", sizeof(cap->driver)); + strscpy(cap->card, histo->video.name, sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", dev_name(histo->entity.vsp1->dev)); diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c index 0cb63244b21a..0b18f0bd7419 100644 --- a/drivers/media/platform/vsp1/vsp1_lif.c +++ b/drivers/media/platform/vsp1/vsp1_lif.c @@ -88,14 +88,35 @@ static void lif_configure_stream(struct vsp1_entity *entity, { const struct v4l2_mbus_framefmt *format; struct vsp1_lif *lif = to_lif(&entity->subdev); - unsigned int hbth = 1300; - unsigned int obth = 400; - unsigned int lbth = 200; + unsigned int hbth; + unsigned int obth; + unsigned int lbth; format = vsp1_entity_get_pad_format(&lif->entity, lif->entity.config, LIF_PAD_SOURCE); - obth = min(obth, (format->width + 1) / 2 * format->height - 4); + switch (entity->vsp1->version & VI6_IP_VERSION_SOC_MASK) { + case VI6_IP_VERSION_MODEL_VSPD_GEN2: + case VI6_IP_VERSION_MODEL_VSPD_V2H: + hbth = 1536; + obth = min(128U, (format->width + 1) / 2 * format->height - 4); + lbth = 1520; + break; + + case VI6_IP_VERSION_MODEL_VSPDL_GEN3: + case VI6_IP_VERSION_MODEL_VSPD_V3: + hbth = 0; + obth = 1500; + lbth = 0; + break; + + case VI6_IP_VERSION_MODEL_VSPD_GEN3: + default: + hbth = 0; + obth = 3000; + lbth = 0; + break; + } vsp1_lif_write(lif, dlb, VI6_LIF_CSBTH, (hbth << VI6_LIF_CSBTH_HBTH_SHIFT) | diff --git a/drivers/media/platform/vsp1/vsp1_regs.h b/drivers/media/platform/vsp1/vsp1_regs.h index 3738ff2f7b85..f6e4157095cc 100644 --- a/drivers/media/platform/vsp1/vsp1_regs.h +++ b/drivers/media/platform/vsp1/vsp1_regs.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * vsp1_regs.h -- R-Car VSP1 Registers Definitions * diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index f8005b60b9d2..616afa7e165f 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -108,7 +108,7 @@ static void rpf_configure_stream(struct vsp1_entity *entity, vsp1_rpf_write(rpf, dlb, VI6_RPF_INFMT, infmt); vsp1_rpf_write(rpf, dlb, VI6_RPF_DSWAP, fmtinfo->swap); - /* Output location */ + /* Output location. */ if (pipe->brx) { const struct v4l2_rect *compose; @@ -309,7 +309,7 @@ static void rpf_configure_partition(struct vsp1_entity *entity, /* * Interlaced pipelines will use the extended pre-cmd to process - * SRCM_ADDR_{Y,C0,C1} + * SRCM_ADDR_{Y,C0,C1}. */ if (pipe->interlaced) { vsp1_rpf_configure_autofld(rpf, dl); diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c index 04e4e05af6ae..b1617cb1f2b9 100644 --- a/drivers/media/platform/vsp1/vsp1_sru.c +++ b/drivers/media/platform/vsp1/vsp1_sru.c @@ -312,6 +312,11 @@ static unsigned int sru_max_width(struct vsp1_entity *entity, output = vsp1_entity_get_pad_format(&sru->entity, sru->entity.config, SRU_PAD_SOURCE); + /* + * The maximum input width of the SRU is 288 input pixels, but 32 + * pixels are reserved to support overlapping partition windows when + * scaling. + */ if (input->width != output->width) return 512; else @@ -333,7 +338,7 @@ static void sru_partition(struct vsp1_entity *entity, output = vsp1_entity_get_pad_format(&sru->entity, sru->entity.config, SRU_PAD_SOURCE); - /* Adapt if SRUx2 is enabled */ + /* Adapt if SRUx2 is enabled. */ if (input->width != output->width) { window->width /= 2; window->left /= 2; diff --git a/drivers/media/platform/vsp1/vsp1_uds.c b/drivers/media/platform/vsp1/vsp1_uds.c index c20c84b54936..27012af973b2 100644 --- a/drivers/media/platform/vsp1/vsp1_uds.c +++ b/drivers/media/platform/vsp1/vsp1_uds.c @@ -314,13 +314,13 @@ static void uds_configure_partition(struct vsp1_entity *entity, output = vsp1_entity_get_pad_format(&uds->entity, uds->entity.config, UDS_PAD_SOURCE); - /* Input size clipping */ + /* Input size clipping. */ vsp1_uds_write(uds, dlb, VI6_UDS_HSZCLIP, VI6_UDS_HSZCLIP_HCEN | (0 << VI6_UDS_HSZCLIP_HCL_OFST_SHIFT) | (partition->uds_sink.width << VI6_UDS_HSZCLIP_HCL_SIZE_SHIFT)); - /* Output size clipping */ + /* Output size clipping. */ vsp1_uds_write(uds, dlb, VI6_UDS_CLIP_SIZE, (partition->uds_source.width << VI6_UDS_CLIP_SIZE_HSIZE_SHIFT) | @@ -342,6 +342,14 @@ static unsigned int uds_max_width(struct vsp1_entity *entity, UDS_PAD_SOURCE); hscale = output->width / input->width; + /* + * The maximum width of the UDS is 304 pixels. These are input pixels + * in the event of up-scaling, and output pixels in the event of + * downscaling. + * + * To support overlapping partition windows we clamp at units of 256 and + * the remaining pixels are reserved. + */ if (hscale <= 2) return 256; else if (hscale <= 4) @@ -366,7 +374,7 @@ static void uds_partition(struct vsp1_entity *entity, const struct v4l2_mbus_framefmt *output; const struct v4l2_mbus_framefmt *input; - /* Initialise the partition state */ + /* Initialise the partition state. */ partition->uds_sink = *window; partition->uds_source = *window; diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index 81d47a09d7bc..771dfe1f7c20 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -38,9 +38,7 @@ #define VSP1_VIDEO_DEF_WIDTH 1024 #define VSP1_VIDEO_DEF_HEIGHT 768 -#define VSP1_VIDEO_MIN_WIDTH 2U #define VSP1_VIDEO_MAX_WIDTH 8190U -#define VSP1_VIDEO_MIN_HEIGHT 2U #define VSP1_VIDEO_MAX_HEIGHT 8190U /* ----------------------------------------------------------------------------- @@ -136,9 +134,8 @@ static int __vsp1_video_try_format(struct vsp1_video *video, height = round_down(height, info->vsub); /* Clamp the width and height. */ - pix->width = clamp(width, VSP1_VIDEO_MIN_WIDTH, VSP1_VIDEO_MAX_WIDTH); - pix->height = clamp(height, VSP1_VIDEO_MIN_HEIGHT, - VSP1_VIDEO_MAX_HEIGHT); + pix->width = clamp(width, info->hsub, VSP1_VIDEO_MAX_WIDTH); + pix->height = clamp(height, info->vsub, VSP1_VIDEO_MAX_HEIGHT); /* * Compute and clamp the stride and image size. While not documented in @@ -867,7 +864,7 @@ static void vsp1_video_cleanup_pipeline(struct vsp1_pipeline *pipe) pipe->stream_config = NULL; pipe->configured = false; - /* Release our partition table allocation */ + /* Release our partition table allocation. */ kfree(pipe->part_table); pipe->part_table = NULL; } @@ -976,8 +973,8 @@ vsp1_video_querycap(struct file *file, void *fh, struct v4l2_capability *cap) cap->device_caps = V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING; - strlcpy(cap->driver, "vsp1", sizeof(cap->driver)); - strlcpy(cap->card, video->video.name, sizeof(cap->card)); + strscpy(cap->driver, "vsp1", sizeof(cap->driver)); + strscpy(cap->card, video->video.name, sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", dev_name(video->vsp1->dev)); diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index c2a1a7f97e26..32bb207b2007 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -317,7 +317,7 @@ static void wpf_configure_stream(struct vsp1_entity *entity, vsp1_wpf_write(wpf, dlb, VI6_WPF_SRCRPF, srcrpf); - /* Enable interrupts */ + /* Enable interrupts. */ vsp1_dl_body_write(dlb, VI6_WPF_IRQ_STA(wpf->entity.index), 0); vsp1_dl_body_write(dlb, VI6_WPF_IRQ_ENB(wpf->entity.index), VI6_WFP_IRQ_ENB_DFEE); diff --git a/drivers/media/platform/xilinx/xilinx-dma.c b/drivers/media/platform/xilinx/xilinx-dma.c index d041f94be832..4ae9d38c9433 100644 --- a/drivers/media/platform/xilinx/xilinx-dma.c +++ b/drivers/media/platform/xilinx/xilinx-dma.c @@ -504,10 +504,10 @@ xvip_dma_querycap(struct file *file, void *fh, struct v4l2_capability *cap) cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS | dma->xdev->v4l2_caps; - strlcpy(cap->driver, "xilinx-vipp", sizeof(cap->driver)); - strlcpy(cap->card, dma->video.name, sizeof(cap->card)); - snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s:%u", - dma->xdev->dev->of_node->name, dma->port); + strscpy(cap->driver, "xilinx-vipp", sizeof(cap->driver)); + strscpy(cap->card, dma->video.name, sizeof(cap->card)); + snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%pOFn:%u", + dma->xdev->dev->of_node, dma->port); return 0; } @@ -527,7 +527,7 @@ xvip_dma_enum_format(struct file *file, void *fh, struct v4l2_fmtdesc *f) return -EINVAL; f->pixelformat = dma->format.pixelformat; - strlcpy(f->description, dma->fmtinfo->description, + strscpy(f->description, dma->fmtinfo->description, sizeof(f->description)); return 0; @@ -693,8 +693,8 @@ int xvip_dma_init(struct xvip_composite_device *xdev, struct xvip_dma *dma, dma->video.fops = &xvip_dma_fops; dma->video.v4l2_dev = &xdev->v4l2_dev; dma->video.queue = &dma->queue; - snprintf(dma->video.name, sizeof(dma->video.name), "%s %s %u", - xdev->dev->of_node->name, + snprintf(dma->video.name, sizeof(dma->video.name), "%pOFn %s %u", + xdev->dev->of_node, type == V4L2_BUF_TYPE_VIDEO_CAPTURE ? "output" : "input", port); dma->video.vfl_type = VFL_TYPE_GRABBER; diff --git a/drivers/media/platform/xilinx/xilinx-tpg.c b/drivers/media/platform/xilinx/xilinx-tpg.c index 9c49d1d10bee..851d20dcd550 100644 --- a/drivers/media/platform/xilinx/xilinx-tpg.c +++ b/drivers/media/platform/xilinx/xilinx-tpg.c @@ -833,7 +833,7 @@ static int xtpg_probe(struct platform_device *pdev) v4l2_subdev_init(subdev, &xtpg_ops); subdev->dev = &pdev->dev; subdev->internal_ops = &xtpg_internal_ops; - strlcpy(subdev->name, dev_name(&pdev->dev), sizeof(subdev->name)); + strscpy(subdev->name, dev_name(&pdev->dev), sizeof(subdev->name)); v4l2_set_subdevdata(subdev, xtpg); subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; subdev->entity.ops = &xtpg_media_ops; diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c index 6d95ec1e9a6b..99e016d35d91 100644 --- a/drivers/media/platform/xilinx/xilinx-vipp.c +++ b/drivers/media/platform/xilinx/xilinx-vipp.c @@ -32,33 +32,36 @@ /** * struct xvip_graph_entity - Entity in the video graph - * @list: list entry in a graph entities list - * @node: the entity's DT node - * @entity: media entity, from the corresponding V4L2 subdev * @asd: subdev asynchronous registration information + * @entity: media entity, from the corresponding V4L2 subdev * @subdev: V4L2 subdev */ struct xvip_graph_entity { - struct list_head list; - struct device_node *node; + struct v4l2_async_subdev asd; /* must be first */ struct media_entity *entity; - - struct v4l2_async_subdev asd; struct v4l2_subdev *subdev; }; +static inline struct xvip_graph_entity * +to_xvip_entity(struct v4l2_async_subdev *asd) +{ + return container_of(asd, struct xvip_graph_entity, asd); +} + /* ----------------------------------------------------------------------------- * Graph Management */ static struct xvip_graph_entity * xvip_graph_find_entity(struct xvip_composite_device *xdev, - const struct device_node *node) + const struct fwnode_handle *fwnode) { struct xvip_graph_entity *entity; + struct v4l2_async_subdev *asd; - list_for_each_entry(entity, &xdev->entities, list) { - if (entity->node == node) + list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) { + entity = to_xvip_entity(asd); + if (entity->asd.match.fwnode == fwnode) return entity; } @@ -75,22 +78,23 @@ static int xvip_graph_build_one(struct xvip_composite_device *xdev, struct media_pad *remote_pad; struct xvip_graph_entity *ent; struct v4l2_fwnode_link link; - struct device_node *ep = NULL; + struct fwnode_handle *ep = NULL; int ret = 0; dev_dbg(xdev->dev, "creating links for entity %s\n", local->name); while (1) { /* Get the next endpoint and parse its link. */ - ep = of_graph_get_next_endpoint(entity->node, ep); + ep = fwnode_graph_get_next_endpoint(entity->asd.match.fwnode, + ep); if (ep == NULL) break; - dev_dbg(xdev->dev, "processing endpoint %pOF\n", ep); + dev_dbg(xdev->dev, "processing endpoint %p\n", ep); - ret = v4l2_fwnode_parse_link(of_fwnode_handle(ep), &link); + ret = v4l2_fwnode_parse_link(ep, &link); if (ret < 0) { - dev_err(xdev->dev, "failed to parse link for %pOF\n", + dev_err(xdev->dev, "failed to parse link for %p\n", ep); continue; } @@ -99,9 +103,8 @@ static int xvip_graph_build_one(struct xvip_composite_device *xdev, * the link. */ if (link.local_port >= local->num_pads) { - dev_err(xdev->dev, "invalid port number %u for %pOF\n", - link.local_port, - to_of_node(link.local_node)); + dev_err(xdev->dev, "invalid port number %u for %p\n", + link.local_port, link.local_node); v4l2_fwnode_put_link(&link); ret = -EINVAL; break; @@ -110,28 +113,25 @@ static int xvip_graph_build_one(struct xvip_composite_device *xdev, local_pad = &local->pads[link.local_port]; if (local_pad->flags & MEDIA_PAD_FL_SINK) { - dev_dbg(xdev->dev, "skipping sink port %pOF:%u\n", - to_of_node(link.local_node), - link.local_port); + dev_dbg(xdev->dev, "skipping sink port %p:%u\n", + link.local_node, link.local_port); v4l2_fwnode_put_link(&link); continue; } /* Skip DMA engines, they will be processed separately. */ if (link.remote_node == of_fwnode_handle(xdev->dev->of_node)) { - dev_dbg(xdev->dev, "skipping DMA port %pOF:%u\n", - to_of_node(link.local_node), - link.local_port); + dev_dbg(xdev->dev, "skipping DMA port %p:%u\n", + link.local_node, link.local_port); v4l2_fwnode_put_link(&link); continue; } /* Find the remote entity. */ - ent = xvip_graph_find_entity(xdev, - to_of_node(link.remote_node)); + ent = xvip_graph_find_entity(xdev, link.remote_node); if (ent == NULL) { - dev_err(xdev->dev, "no entity found for %pOF\n", - to_of_node(link.remote_node)); + dev_err(xdev->dev, "no entity found for %p\n", + link.remote_node); v4l2_fwnode_put_link(&link); ret = -ENODEV; break; @@ -140,8 +140,8 @@ static int xvip_graph_build_one(struct xvip_composite_device *xdev, remote = ent->entity; if (link.remote_port >= remote->num_pads) { - dev_err(xdev->dev, "invalid port number %u on %pOF\n", - link.remote_port, to_of_node(link.remote_node)); + dev_err(xdev->dev, "invalid port number %u on %p\n", + link.remote_port, link.remote_node); v4l2_fwnode_put_link(&link); ret = -EINVAL; break; @@ -168,7 +168,7 @@ static int xvip_graph_build_one(struct xvip_composite_device *xdev, } } - of_node_put(ep); + fwnode_handle_put(ep); return ret; } @@ -230,8 +230,7 @@ static int xvip_graph_build_dma(struct xvip_composite_device *xdev) dma->video.name); /* Find the remote entity. */ - ent = xvip_graph_find_entity(xdev, - to_of_node(link.remote_node)); + ent = xvip_graph_find_entity(xdev, link.remote_node); if (ent == NULL) { dev_err(xdev->dev, "no entity found for %pOF\n", to_of_node(link.remote_node)); @@ -289,12 +288,14 @@ static int xvip_graph_notify_complete(struct v4l2_async_notifier *notifier) struct xvip_composite_device *xdev = container_of(notifier, struct xvip_composite_device, notifier); struct xvip_graph_entity *entity; + struct v4l2_async_subdev *asd; int ret; dev_dbg(xdev->dev, "notify complete, all subdevs registered\n"); /* Create links for every entity. */ - list_for_each_entry(entity, &xdev->entities, list) { + list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) { + entity = to_xvip_entity(asd); ret = xvip_graph_build_one(xdev, entity); if (ret < 0) return ret; @@ -314,22 +315,25 @@ static int xvip_graph_notify_complete(struct v4l2_async_notifier *notifier) static int xvip_graph_notify_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd) + struct v4l2_async_subdev *unused) { struct xvip_composite_device *xdev = container_of(notifier, struct xvip_composite_device, notifier); struct xvip_graph_entity *entity; + struct v4l2_async_subdev *asd; /* Locate the entity corresponding to the bound subdev and store the * subdev pointer. */ - list_for_each_entry(entity, &xdev->entities, list) { - if (entity->node != subdev->dev->of_node) + list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) { + entity = to_xvip_entity(asd); + + if (entity->asd.match.fwnode != subdev->fwnode) continue; if (entity->subdev) { - dev_err(xdev->dev, "duplicate subdev for node %pOF\n", - entity->node); + dev_err(xdev->dev, "duplicate subdev for node %p\n", + entity->asd.match.fwnode); return -EINVAL; } @@ -349,56 +353,60 @@ static const struct v4l2_async_notifier_operations xvip_graph_notify_ops = { }; static int xvip_graph_parse_one(struct xvip_composite_device *xdev, - struct device_node *node) + struct fwnode_handle *fwnode) { - struct xvip_graph_entity *entity; - struct device_node *remote; - struct device_node *ep = NULL; + struct fwnode_handle *remote; + struct fwnode_handle *ep = NULL; int ret = 0; - dev_dbg(xdev->dev, "parsing node %pOF\n", node); + dev_dbg(xdev->dev, "parsing node %p\n", fwnode); while (1) { - ep = of_graph_get_next_endpoint(node, ep); + struct v4l2_async_subdev *asd; + + ep = fwnode_graph_get_next_endpoint(fwnode, ep); if (ep == NULL) break; - dev_dbg(xdev->dev, "handling endpoint %pOF\n", ep); + dev_dbg(xdev->dev, "handling endpoint %p\n", ep); - remote = of_graph_get_remote_port_parent(ep); + remote = fwnode_graph_get_remote_port_parent(ep); if (remote == NULL) { ret = -EINVAL; - break; + goto err_notifier_cleanup; } + fwnode_handle_put(ep); + /* Skip entities that we have already processed. */ - if (remote == xdev->dev->of_node || + if (remote == of_fwnode_handle(xdev->dev->of_node) || xvip_graph_find_entity(xdev, remote)) { - of_node_put(remote); + fwnode_handle_put(remote); continue; } - entity = devm_kzalloc(xdev->dev, sizeof(*entity), GFP_KERNEL); - if (entity == NULL) { - of_node_put(remote); - ret = -ENOMEM; - break; + asd = v4l2_async_notifier_add_fwnode_subdev( + &xdev->notifier, remote, + sizeof(struct xvip_graph_entity)); + if (IS_ERR(asd)) { + ret = PTR_ERR(asd); + fwnode_handle_put(remote); + goto err_notifier_cleanup; } - - entity->node = remote; - entity->asd.match_type = V4L2_ASYNC_MATCH_FWNODE; - entity->asd.match.fwnode = of_fwnode_handle(remote); - list_add_tail(&entity->list, &xdev->entities); - xdev->num_subdevs++; } - of_node_put(ep); + return 0; + +err_notifier_cleanup: + v4l2_async_notifier_cleanup(&xdev->notifier); + fwnode_handle_put(ep); return ret; } static int xvip_graph_parse(struct xvip_composite_device *xdev) { struct xvip_graph_entity *entity; + struct v4l2_async_subdev *asd; int ret; /* @@ -407,14 +415,17 @@ static int xvip_graph_parse(struct xvip_composite_device *xdev) * loop will handle entities added at the end of the list while walking * the links. */ - ret = xvip_graph_parse_one(xdev, xdev->dev->of_node); + ret = xvip_graph_parse_one(xdev, of_fwnode_handle(xdev->dev->of_node)); if (ret < 0) return 0; - list_for_each_entry(entity, &xdev->entities, list) { - ret = xvip_graph_parse_one(xdev, entity->node); - if (ret < 0) + list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) { + entity = to_xvip_entity(asd); + ret = xvip_graph_parse_one(xdev, entity->asd.match.fwnode); + if (ret < 0) { + v4l2_async_notifier_cleanup(&xdev->notifier); break; + } } return ret; @@ -485,17 +496,11 @@ static int xvip_graph_dma_init(struct xvip_composite_device *xdev) static void xvip_graph_cleanup(struct xvip_composite_device *xdev) { - struct xvip_graph_entity *entityp; - struct xvip_graph_entity *entity; struct xvip_dma *dmap; struct xvip_dma *dma; v4l2_async_notifier_unregister(&xdev->notifier); - - list_for_each_entry_safe(entity, entityp, &xdev->entities, list) { - of_node_put(entity->node); - list_del(&entity->list); - } + v4l2_async_notifier_cleanup(&xdev->notifier); list_for_each_entry_safe(dma, dmap, &xdev->dmas, list) { xvip_dma_cleanup(dma); @@ -505,10 +510,6 @@ static void xvip_graph_cleanup(struct xvip_composite_device *xdev) static int xvip_graph_init(struct xvip_composite_device *xdev) { - struct xvip_graph_entity *entity; - struct v4l2_async_subdev **subdevs = NULL; - unsigned int num_subdevs; - unsigned int i; int ret; /* Init the DMA channels. */ @@ -525,26 +526,12 @@ static int xvip_graph_init(struct xvip_composite_device *xdev) goto done; } - if (!xdev->num_subdevs) { + if (list_empty(&xdev->notifier.asd_list)) { dev_err(xdev->dev, "no subdev found in graph\n"); goto done; } /* Register the subdevices notifier. */ - num_subdevs = xdev->num_subdevs; - subdevs = devm_kcalloc(xdev->dev, num_subdevs, sizeof(*subdevs), - GFP_KERNEL); - if (subdevs == NULL) { - ret = -ENOMEM; - goto done; - } - - i = 0; - list_for_each_entry(entity, &xdev->entities, list) - subdevs[i++] = &entity->asd; - - xdev->notifier.subdevs = subdevs; - xdev->notifier.num_subdevs = num_subdevs; xdev->notifier.ops = &xvip_graph_notify_ops; ret = v4l2_async_notifier_register(&xdev->v4l2_dev, &xdev->notifier); @@ -578,7 +565,7 @@ static int xvip_composite_v4l2_init(struct xvip_composite_device *xdev) int ret; xdev->media_dev.dev = xdev->dev; - strlcpy(xdev->media_dev.model, "Xilinx Video Composite Device", + strscpy(xdev->media_dev.model, "Xilinx Video Composite Device", sizeof(xdev->media_dev.model)); xdev->media_dev.hw_revision = 0; @@ -610,8 +597,8 @@ static int xvip_composite_probe(struct platform_device *pdev) return -ENOMEM; xdev->dev = &pdev->dev; - INIT_LIST_HEAD(&xdev->entities); INIT_LIST_HEAD(&xdev->dmas); + v4l2_async_notifier_init(&xdev->notifier); ret = xvip_composite_v4l2_init(xdev); if (ret < 0) diff --git a/drivers/media/platform/xilinx/xilinx-vipp.h b/drivers/media/platform/xilinx/xilinx-vipp.h index faf6b6e80b3b..7e9c4cff33b4 100644 --- a/drivers/media/platform/xilinx/xilinx-vipp.h +++ b/drivers/media/platform/xilinx/xilinx-vipp.h @@ -28,8 +28,6 @@ * @media_dev: media device * @dev: (OF) device * @notifier: V4L2 asynchronous subdevs notifier - * @entities: entities in the graph as a list of xvip_graph_entity - * @num_subdevs: number of subdevs in the pipeline * @dmas: list of DMA channels at the pipeline output and input * @v4l2_caps: V4L2 capabilities of the whole device (see VIDIOC_QUERYCAP) */ @@ -39,8 +37,6 @@ struct xvip_composite_device { struct device *dev; struct v4l2_async_notifier notifier; - struct list_head entities; - unsigned int num_subdevs; struct list_head dmas; u32 v4l2_caps; diff --git a/drivers/media/radio/dsbr100.c b/drivers/media/radio/dsbr100.c index 8521bb2825e8..c9d51a5f2838 100644 --- a/drivers/media/radio/dsbr100.c +++ b/drivers/media/radio/dsbr100.c @@ -174,8 +174,8 @@ static int vidioc_querycap(struct file *file, void *priv, { struct dsbr100_device *radio = video_drvdata(file); - strlcpy(v->driver, "dsbr100", sizeof(v->driver)); - strlcpy(v->card, "D-Link R-100 USB FM Radio", sizeof(v->card)); + strscpy(v->driver, "dsbr100", sizeof(v->driver)); + strscpy(v->card, "D-Link R-100 USB FM Radio", sizeof(v->card)); usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info)); v->device_caps = V4L2_CAP_RADIO | V4L2_CAP_TUNER; v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS; @@ -191,7 +191,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, return -EINVAL; dsbr100_getstat(radio); - strcpy(v->name, "FM"); + strscpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; v->rangelow = FREQ_MIN * FREQ_MUL; v->rangehigh = FREQ_MAX * FREQ_MUL; @@ -379,7 +379,8 @@ static int usb_dsbr100_probe(struct usb_interface *intf, goto err_reg_ctrl; } mutex_init(&radio->v4l2_lock); - strlcpy(radio->videodev.name, v4l2_dev->name, sizeof(radio->videodev.name)); + strscpy(radio->videodev.name, v4l2_dev->name, + sizeof(radio->videodev.name)); radio->videodev.v4l2_dev = v4l2_dev; radio->videodev.fops = &usb_dsbr100_fops; radio->videodev.ioctl_ops = &usb_dsbr100_ioctl_ops; diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c index 5b82e63885cd..d12e07e32546 100644 --- a/drivers/media/radio/radio-cadet.c +++ b/drivers/media/radio/radio-cadet.c @@ -353,9 +353,9 @@ static ssize_t cadet_read(struct file *file, char __user *data, size_t count, lo static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *v) { - strlcpy(v->driver, "ADS Cadet", sizeof(v->driver)); - strlcpy(v->card, "ADS Cadet", sizeof(v->card)); - strlcpy(v->bus_info, "ISA:radio-cadet", sizeof(v->bus_info)); + strscpy(v->driver, "ADS Cadet", sizeof(v->driver)); + strscpy(v->card, "ADS Cadet", sizeof(v->card)); + strscpy(v->bus_info, "ISA:radio-cadet", sizeof(v->bus_info)); v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_READWRITE | V4L2_CAP_RDS_CAPTURE; v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS; @@ -370,7 +370,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, if (v->index) return -EINVAL; v->type = V4L2_TUNER_RADIO; - strlcpy(v->name, "Radio", sizeof(v->name)); + strscpy(v->name, "Radio", sizeof(v->name)); v->capability = bands[0].capability | bands[1].capability; v->rangelow = bands[0].rangelow; /* 520 kHz (start of AM band) */ v->rangehigh = bands[1].rangehigh; /* 108.0 MHz (end of FM band) */ @@ -595,7 +595,7 @@ static int __init cadet_init(void) struct v4l2_ctrl_handler *hdl; int res = -ENODEV; - strlcpy(v4l2_dev->name, "cadet", sizeof(v4l2_dev->name)); + strscpy(v4l2_dev->name, "cadet", sizeof(v4l2_dev->name)); mutex_init(&dev->lock); /* If a probe was requested then probe ISAPnP first (safest) */ @@ -639,7 +639,7 @@ static int __init cadet_init(void) dev->is_fm_band = true; dev->curfreq = bands[dev->is_fm_band].rangelow; cadet_setfreq(dev, dev->curfreq); - strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); + strscpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); dev->vdev.v4l2_dev = v4l2_dev; dev->vdev.fops = &cadet_fops; dev->vdev.ioctl_ops = &cadet_ioctl_ops; diff --git a/drivers/media/radio/radio-isa.c b/drivers/media/radio/radio-isa.c index 7312e469e850..551de8a45b95 100644 --- a/drivers/media/radio/radio-isa.c +++ b/drivers/media/radio/radio-isa.c @@ -42,8 +42,8 @@ static int radio_isa_querycap(struct file *file, void *priv, { struct radio_isa_card *isa = video_drvdata(file); - strlcpy(v->driver, isa->drv->driver.driver.name, sizeof(v->driver)); - strlcpy(v->card, isa->drv->card, sizeof(v->card)); + strscpy(v->driver, isa->drv->driver.driver.name, sizeof(v->driver)); + strscpy(v->card, isa->drv->card, sizeof(v->card)); snprintf(v->bus_info, sizeof(v->bus_info), "ISA:%s", isa->v4l2_dev.name); v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO; @@ -60,7 +60,7 @@ static int radio_isa_g_tuner(struct file *file, void *priv, if (v->index > 0) return -EINVAL; - strlcpy(v->name, "FM", sizeof(v->name)); + strscpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; v->rangelow = FREQ_LOW; v->rangehigh = FREQ_HIGH; @@ -198,7 +198,7 @@ static struct radio_isa_card *radio_isa_alloc(struct radio_isa_driver *drv, dev_set_drvdata(pdev, isa); isa->drv = drv; v4l2_dev = &isa->v4l2_dev; - strlcpy(v4l2_dev->name, dev_name(pdev), sizeof(v4l2_dev->name)); + strscpy(v4l2_dev->name, dev_name(pdev), sizeof(v4l2_dev->name)); return isa; } @@ -243,7 +243,7 @@ static int radio_isa_common_probe(struct radio_isa_card *isa, mutex_init(&isa->lock); isa->vdev.lock = &isa->lock; - strlcpy(isa->vdev.name, v4l2_dev->name, sizeof(isa->vdev.name)); + strscpy(isa->vdev.name, v4l2_dev->name, sizeof(isa->vdev.name)); isa->vdev.v4l2_dev = v4l2_dev; isa->vdev.fops = &radio_isa_fops; isa->vdev.ioctl_ops = &radio_isa_ioctl_ops; diff --git a/drivers/media/radio/radio-keene.c b/drivers/media/radio/radio-keene.c index f2ea8bc5f5ee..e9484b013073 100644 --- a/drivers/media/radio/radio-keene.c +++ b/drivers/media/radio/radio-keene.c @@ -174,8 +174,8 @@ static int vidioc_querycap(struct file *file, void *priv, { struct keene_device *radio = video_drvdata(file); - strlcpy(v->driver, "radio-keene", sizeof(v->driver)); - strlcpy(v->card, "Keene FM Transmitter", sizeof(v->card)); + strscpy(v->driver, "radio-keene", sizeof(v->driver)); + strscpy(v->card, "Keene FM Transmitter", sizeof(v->card)); usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info)); v->device_caps = V4L2_CAP_RADIO | V4L2_CAP_MODULATOR; v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS; @@ -190,7 +190,7 @@ static int vidioc_g_modulator(struct file *file, void *priv, if (v->index > 0) return -EINVAL; - strlcpy(v->name, "FM", sizeof(v->name)); + strscpy(v->name, "FM", sizeof(v->name)); v->rangelow = FREQ_MIN * FREQ_MUL; v->rangehigh = FREQ_MAX * FREQ_MUL; v->txsubchans = radio->stereo ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; @@ -362,7 +362,7 @@ static int usb_keene_probe(struct usb_interface *intf, radio->v4l2_dev.ctrl_handler = hdl; radio->v4l2_dev.release = usb_keene_video_device_release; - strlcpy(radio->vdev.name, radio->v4l2_dev.name, + strscpy(radio->vdev.name, radio->v4l2_dev.name, sizeof(radio->vdev.name)); radio->vdev.v4l2_dev = &radio->v4l2_dev; radio->vdev.fops = &usb_keene_fops; diff --git a/drivers/media/radio/radio-ma901.c b/drivers/media/radio/radio-ma901.c index fdc481257efd..5cb153727841 100644 --- a/drivers/media/radio/radio-ma901.c +++ b/drivers/media/radio/radio-ma901.c @@ -197,8 +197,8 @@ static int vidioc_querycap(struct file *file, void *priv, { struct ma901radio_device *radio = video_drvdata(file); - strlcpy(v->driver, "radio-ma901", sizeof(v->driver)); - strlcpy(v->card, "Masterkit MA901 USB FM Radio", sizeof(v->card)); + strscpy(v->driver, "radio-ma901", sizeof(v->driver)); + strscpy(v->card, "Masterkit MA901 USB FM Radio", sizeof(v->card)); usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info)); v->device_caps = V4L2_CAP_RADIO | V4L2_CAP_TUNER; v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS; @@ -222,7 +222,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, * retval = ma901radio_get_stat(radio, &is_stereo, &v->signal); */ - strcpy(v->name, "FM"); + strscpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; v->rangelow = FREQ_MIN * FREQ_MUL; v->rangehigh = FREQ_MAX * FREQ_MUL; @@ -400,7 +400,7 @@ static int usb_ma901radio_probe(struct usb_interface *intf, radio->v4l2_dev.ctrl_handler = &radio->hdl; radio->v4l2_dev.release = usb_ma901radio_release; - strlcpy(radio->vdev.name, radio->v4l2_dev.name, + strscpy(radio->vdev.name, radio->v4l2_dev.name, sizeof(radio->vdev.name)); radio->vdev.v4l2_dev = &radio->v4l2_dev; radio->vdev.fops = &usb_ma901radio_fops; diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c index e4e758739246..1b97ad2ce7d0 100644 --- a/drivers/media/radio/radio-maxiradio.c +++ b/drivers/media/radio/radio-maxiradio.c @@ -142,7 +142,7 @@ static int maxiradio_probe(struct pci_dev *pdev, dev->tea.cannot_read_data = true; dev->tea.v4l2_dev = v4l2_dev; dev->tea.radio_nr = radio_nr; - strlcpy(dev->tea.card, "Maxi Radio FM2000", sizeof(dev->tea.card)); + strscpy(dev->tea.card, "Maxi Radio FM2000", sizeof(dev->tea.card)); snprintf(dev->tea.bus_info, sizeof(dev->tea.bus_info), "PCI:%s", pci_name(pdev)); diff --git a/drivers/media/radio/radio-miropcm20.c b/drivers/media/radio/radio-miropcm20.c index 7b35e633118d..b626567b75c5 100644 --- a/drivers/media/radio/radio-miropcm20.c +++ b/drivers/media/radio/radio-miropcm20.c @@ -200,8 +200,8 @@ static int vidioc_querycap(struct file *file, void *priv, { struct pcm20 *dev = video_drvdata(file); - strlcpy(v->driver, "Miro PCM20", sizeof(v->driver)); - strlcpy(v->card, "Miro PCM20", sizeof(v->card)); + strscpy(v->driver, "Miro PCM20", sizeof(v->driver)); + strscpy(v->card, "Miro PCM20", sizeof(v->card)); snprintf(v->bus_info, sizeof(v->bus_info), "ISA:%s", dev->v4l2_dev.name); v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_RDS_CAPTURE; v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS; @@ -231,7 +231,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, if (v->index) return -EINVAL; - strlcpy(v->name, "FM", sizeof(v->name)); + strscpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; v->rangelow = 87*16000; v->rangehigh = 108*16000; @@ -443,7 +443,7 @@ static int __init pcm20_init(void) "you must load the snd-miro driver first!\n"); return -ENODEV; } - strlcpy(v4l2_dev->name, "radio-miropcm20", sizeof(v4l2_dev->name)); + strscpy(v4l2_dev->name, "radio-miropcm20", sizeof(v4l2_dev->name)); mutex_init(&dev->lock); res = v4l2_device_register(NULL, v4l2_dev); @@ -474,7 +474,7 @@ static int __init pcm20_init(void) v4l2_err(v4l2_dev, "Could not register control\n"); goto err_hdl; } - strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); + strscpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name)); dev->vdev.v4l2_dev = v4l2_dev; dev->vdev.fops = &pcm20_fops; dev->vdev.ioctl_ops = &pcm20_ioctl_ops; diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index 0f292c6ba338..ab1324f68199 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c @@ -266,8 +266,8 @@ static int vidioc_querycap(struct file *file, void *priv, { struct amradio_device *radio = video_drvdata(file); - strlcpy(v->driver, "radio-mr800", sizeof(v->driver)); - strlcpy(v->card, "AverMedia MR 800 USB FM Radio", sizeof(v->card)); + strscpy(v->driver, "radio-mr800", sizeof(v->driver)); + strscpy(v->card, "AverMedia MR 800 USB FM Radio", sizeof(v->card)); usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info)); v->device_caps = V4L2_CAP_RADIO | V4L2_CAP_TUNER | V4L2_CAP_HW_FREQ_SEEK; @@ -291,7 +291,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, if (retval) return retval; - strcpy(v->name, "FM"); + strscpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; v->rangelow = FREQ_MIN * FREQ_MUL; v->rangehigh = FREQ_MAX * FREQ_MUL; @@ -547,7 +547,7 @@ static int usb_amradio_probe(struct usb_interface *intf, radio->v4l2_dev.ctrl_handler = &radio->hdl; radio->v4l2_dev.release = usb_amradio_release; - strlcpy(radio->vdev.name, radio->v4l2_dev.name, + strscpy(radio->vdev.name, radio->v4l2_dev.name, sizeof(radio->vdev.name)); radio->vdev.v4l2_dev = &radio->v4l2_dev; radio->vdev.fops = &usb_amradio_fops; diff --git a/drivers/media/radio/radio-raremono.c b/drivers/media/radio/radio-raremono.c index 9a5079d64c4a..5e782b3c2fa9 100644 --- a/drivers/media/radio/radio-raremono.c +++ b/drivers/media/radio/radio-raremono.c @@ -181,8 +181,8 @@ static int vidioc_querycap(struct file *file, void *priv, { struct raremono_device *radio = video_drvdata(file); - strlcpy(v->driver, "radio-raremono", sizeof(v->driver)); - strlcpy(v->card, "Thanko's Raremono", sizeof(v->card)); + strscpy(v->driver, "radio-raremono", sizeof(v->driver)); + strscpy(v->card, "Thanko's Raremono", sizeof(v->card)); usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info)); v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO; v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS; @@ -212,7 +212,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, if (v->index > 0) return -EINVAL; - strlcpy(v->name, "AM/FM/SW", sizeof(v->name)); + strscpy(v->name, "AM/FM/SW", sizeof(v->name)); v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_FREQ_BANDS; v->rangelow = AM_FREQ_RANGE_LOW * 16; @@ -338,7 +338,7 @@ static int usb_raremono_probe(struct usb_interface *intf, mutex_init(&radio->lock); - strlcpy(radio->vdev.name, radio->v4l2_dev.name, + strscpy(radio->vdev.name, radio->v4l2_dev.name, sizeof(radio->vdev.name)); radio->vdev.v4l2_dev = &radio->v4l2_dev; radio->vdev.fops = &usb_raremono_fops; diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c index 4f9b97edd9eb..a8fedc963614 100644 --- a/drivers/media/radio/radio-sf16fmi.c +++ b/drivers/media/radio/radio-sf16fmi.c @@ -129,9 +129,9 @@ static void fmi_set_freq(struct fmi *fmi) static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *v) { - strlcpy(v->driver, "radio-sf16fmi", sizeof(v->driver)); - strlcpy(v->card, "SF16-FMI/FMP/FMD radio", sizeof(v->card)); - strlcpy(v->bus_info, "ISA:radio-sf16fmi", sizeof(v->bus_info)); + strscpy(v->driver, "radio-sf16fmi", sizeof(v->driver)); + strscpy(v->card, "SF16-FMI/FMP/FMD radio", sizeof(v->card)); + strscpy(v->bus_info, "ISA:radio-sf16fmi", sizeof(v->bus_info)); v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO; v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; @@ -145,7 +145,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, if (v->index > 0) return -EINVAL; - strlcpy(v->name, "FM", sizeof(v->name)); + strscpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; v->rangelow = RSF16_MINFREQ; v->rangehigh = RSF16_MAXFREQ; @@ -315,7 +315,7 @@ static int __init fmi_init(void) return -ENODEV; } - strlcpy(v4l2_dev->name, "sf16fmi", sizeof(v4l2_dev->name)); + strscpy(v4l2_dev->name, "sf16fmi", sizeof(v4l2_dev->name)); fmi->io = io; res = v4l2_device_register(NULL, v4l2_dev); @@ -339,7 +339,7 @@ static int __init fmi_init(void) return res; } - strlcpy(fmi->vdev.name, v4l2_dev->name, sizeof(fmi->vdev.name)); + strscpy(fmi->vdev.name, v4l2_dev->name, sizeof(fmi->vdev.name)); fmi->vdev.v4l2_dev = v4l2_dev; fmi->vdev.fops = &fmi_fops; fmi->vdev.ioctl_ops = &fmi_ioctl_ops; diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c index 7b07d42a9909..ca8a1c263eac 100644 --- a/drivers/media/radio/radio-sf16fmr2.c +++ b/drivers/media/radio/radio-sf16fmr2.c @@ -213,8 +213,8 @@ static int fmr2_probe(struct fmr2 *fmr2, struct device *pdev, int io) if (io == fmr2_cards[i]->io) return -EBUSY; - strlcpy(fmr2->v4l2_dev.name, "radio-sf16fmr2", - sizeof(fmr2->v4l2_dev.name)), + strscpy(fmr2->v4l2_dev.name, "radio-sf16fmr2", + sizeof(fmr2->v4l2_dev.name)), fmr2->io = io; if (!request_region(fmr2->io, 2, fmr2->v4l2_dev.name)) { @@ -234,7 +234,7 @@ static int fmr2_probe(struct fmr2 *fmr2, struct device *pdev, int io) fmr2->tea.radio_nr = radio_nr[num_fmr2_cards]; fmr2->tea.ops = &fmr2_tea_ops; fmr2->tea.ext_init = fmr2_tea_ext_init; - strlcpy(fmr2->tea.card, card_name, sizeof(fmr2->tea.card)); + strscpy(fmr2->tea.card, card_name, sizeof(fmr2->tea.card)); snprintf(fmr2->tea.bus_info, sizeof(fmr2->tea.bus_info), "%s:%s", fmr2->is_fmd2 ? "PnP" : "ISA", dev_name(pdev)); diff --git a/drivers/media/radio/radio-shark.c b/drivers/media/radio/radio-shark.c index 22f3466af2b1..8230da828d0e 100644 --- a/drivers/media/radio/radio-shark.c +++ b/drivers/media/radio/radio-shark.c @@ -345,7 +345,7 @@ static int usb_shark_probe(struct usb_interface *intf, shark->tea.ops = &shark_tea_ops; shark->tea.cannot_mute = true; shark->tea.has_am = true; - strlcpy(shark->tea.card, "Griffin radioSHARK", + strscpy(shark->tea.card, "Griffin radioSHARK", sizeof(shark->tea.card)); usb_make_path(shark->usbdev, shark->tea.bus_info, sizeof(shark->tea.bus_info)); diff --git a/drivers/media/radio/radio-shark2.c b/drivers/media/radio/radio-shark2.c index 4d1a4b3d669c..d150f12382c6 100644 --- a/drivers/media/radio/radio-shark2.c +++ b/drivers/media/radio/radio-shark2.c @@ -310,7 +310,7 @@ static int usb_shark_probe(struct usb_interface *intf, shark->tea.ops = &shark_tea_ops; shark->tea.has_am = true; shark->tea.write_before_read = true; - strlcpy(shark->tea.card, "Griffin radioSHARK2", + strscpy(shark->tea.card, "Griffin radioSHARK2", sizeof(shark->tea.card)); usb_make_path(shark->usbdev, shark->tea.bus_info, sizeof(shark->tea.bus_info)); diff --git a/drivers/media/radio/radio-si476x.c b/drivers/media/radio/radio-si476x.c index b52e678c6901..269971145f88 100644 --- a/drivers/media/radio/radio-si476x.c +++ b/drivers/media/radio/radio-si476x.c @@ -340,9 +340,9 @@ static int si476x_radio_querycap(struct file *file, void *priv, { struct si476x_radio *radio = video_drvdata(file); - strlcpy(capability->driver, radio->v4l2dev.name, + strscpy(capability->driver, radio->v4l2dev.name, sizeof(capability->driver)); - strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card)); + strscpy(capability->card, DRIVER_CARD, sizeof(capability->card)); snprintf(capability->bus_info, sizeof(capability->bus_info), "platform:%s", radio->v4l2dev.name); @@ -428,15 +428,15 @@ static int si476x_radio_g_tuner(struct file *file, void *priv, si476x_core_lock(radio->core); if (si476x_core_is_a_secondary_tuner(radio->core)) { - strlcpy(tuner->name, "FM (secondary)", sizeof(tuner->name)); + strscpy(tuner->name, "FM (secondary)", sizeof(tuner->name)); tuner->rxsubchans = 0; tuner->rangelow = si476x_bands[SI476X_BAND_FM].rangelow; } else if (si476x_core_has_am(radio->core)) { if (si476x_core_is_a_primary_tuner(radio->core)) - strlcpy(tuner->name, "AM/FM (primary)", + strscpy(tuner->name, "AM/FM (primary)", sizeof(tuner->name)); else - strlcpy(tuner->name, "AM/FM", sizeof(tuner->name)); + strscpy(tuner->name, "AM/FM", sizeof(tuner->name)); tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_RDS; @@ -446,7 +446,7 @@ static int si476x_radio_g_tuner(struct file *file, void *priv, tuner->rangelow = si476x_bands[SI476X_BAND_AM].rangelow; } else { - strlcpy(tuner->name, "FM", sizeof(tuner->name)); + strscpy(tuner->name, "FM", sizeof(tuner->name)); tuner->rxsubchans = V4L2_TUNER_SUB_RDS; tuner->capability |= V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c index afb763256fd6..6632be648cea 100644 --- a/drivers/media/radio/radio-tea5764.c +++ b/drivers/media/radio/radio-tea5764.c @@ -287,8 +287,8 @@ static int vidioc_querycap(struct file *file, void *priv, struct tea5764_device *radio = video_drvdata(file); struct video_device *dev = &radio->vdev; - strlcpy(v->driver, dev->dev.driver->name, sizeof(v->driver)); - strlcpy(v->card, dev->name, sizeof(v->card)); + strscpy(v->driver, dev->dev.driver->name, sizeof(v->driver)); + strscpy(v->card, dev->name, sizeof(v->card)); snprintf(v->bus_info, sizeof(v->bus_info), "I2C:%s", dev_name(&dev->dev)); v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO; @@ -305,7 +305,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, if (v->index > 0) return -EINVAL; - strlcpy(v->name, "FM", sizeof(v->name)); + strscpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; tea5764_i2c_read(radio); v->rangelow = FREQ_MIN * FREQ_MUL; diff --git a/drivers/media/radio/radio-tea5777.c b/drivers/media/radio/radio-tea5777.c index 04ed1a5d1177..61f751cf1aa4 100644 --- a/drivers/media/radio/radio-tea5777.c +++ b/drivers/media/radio/radio-tea5777.c @@ -266,10 +266,10 @@ static int vidioc_querycap(struct file *file, void *priv, { struct radio_tea5777 *tea = video_drvdata(file); - strlcpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver)); - strlcpy(v->card, tea->card, sizeof(v->card)); + strscpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver)); + strscpy(v->card, tea->card, sizeof(v->card)); strlcat(v->card, " TEA5777", sizeof(v->card)); - strlcpy(v->bus_info, tea->bus_info, sizeof(v->bus_info)); + strscpy(v->bus_info, tea->bus_info, sizeof(v->bus_info)); v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO; v->device_caps |= V4L2_CAP_HW_FREQ_SEEK; v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS; @@ -304,9 +304,9 @@ static int vidioc_g_tuner(struct file *file, void *priv, memset(v, 0, sizeof(*v)); if (tea->has_am) - strlcpy(v->name, "AM/FM", sizeof(v->name)); + strscpy(v->name, "AM/FM", sizeof(v->name)); else - strlcpy(v->name, "FM", sizeof(v->name)); + strscpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_FREQ_BANDS | @@ -560,7 +560,7 @@ int radio_tea5777_init(struct radio_tea5777 *tea, struct module *owner) tea->vd = tea575x_radio; video_set_drvdata(&tea->vd, tea); mutex_init(&tea->mutex); - strlcpy(tea->vd.name, tea->v4l2_dev->name, sizeof(tea->vd.name)); + strscpy(tea->vd.name, tea->v4l2_dev->name, sizeof(tea->vd.name)); tea->vd.lock = &tea->mutex; tea->vd.v4l2_dev = tea->v4l2_dev; tea->fops = tea575x_fops; diff --git a/drivers/media/radio/radio-timb.c b/drivers/media/radio/radio-timb.c index fc4d9a73ab17..0eda863124e9 100644 --- a/drivers/media/radio/radio-timb.c +++ b/drivers/media/radio/radio-timb.c @@ -39,8 +39,8 @@ struct timbradio { static int timbradio_vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *v) { - strlcpy(v->driver, DRIVER_NAME, sizeof(v->driver)); - strlcpy(v->card, "Timberdale Radio", sizeof(v->card)); + strscpy(v->driver, DRIVER_NAME, sizeof(v->driver)); + strscpy(v->card, "Timberdale Radio", sizeof(v->card)); snprintf(v->bus_info, sizeof(v->bus_info), "platform:"DRIVER_NAME); v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO; v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS; @@ -115,7 +115,7 @@ static int timbradio_probe(struct platform_device *pdev) tr->pdata = *pdata; mutex_init(&tr->lock); - strlcpy(tr->video_dev.name, "Timberdale Radio", + strscpy(tr->video_dev.name, "Timberdale Radio", sizeof(tr->video_dev.name)); tr->video_dev.fops = &timbradio_fops; tr->video_dev.ioctl_ops = &timbradio_ioctl_ops; @@ -123,7 +123,7 @@ static int timbradio_probe(struct platform_device *pdev) tr->video_dev.minor = -1; tr->video_dev.lock = &tr->lock; - strlcpy(tr->v4l2_dev.name, DRIVER_NAME, sizeof(tr->v4l2_dev.name)); + strscpy(tr->v4l2_dev.name, DRIVER_NAME, sizeof(tr->v4l2_dev.name)); err = v4l2_device_register(NULL, &tr->v4l2_dev); if (err) goto err; diff --git a/drivers/media/radio/radio-wl1273.c b/drivers/media/radio/radio-wl1273.c index 11aa94f189cb..b95704f3cb8b 100644 --- a/drivers/media/radio/radio-wl1273.c +++ b/drivers/media/radio/radio-wl1273.c @@ -1286,11 +1286,11 @@ static int wl1273_fm_vidioc_querycap(struct file *file, void *priv, dev_dbg(radio->dev, "%s\n", __func__); - strlcpy(capability->driver, WL1273_FM_DRIVER_NAME, + strscpy(capability->driver, WL1273_FM_DRIVER_NAME, sizeof(capability->driver)); - strlcpy(capability->card, "Texas Instruments Wl1273 FM Radio", + strscpy(capability->card, "Texas Instruments Wl1273 FM Radio", sizeof(capability->card)); - strlcpy(capability->bus_info, radio->bus_type, + strscpy(capability->bus_info, radio->bus_type, sizeof(capability->bus_info)); capability->device_caps = V4L2_CAP_HW_FREQ_SEEK | @@ -1488,7 +1488,7 @@ static int wl1273_fm_vidioc_g_audio(struct file *file, void *priv, if (audio->index > 1) return -EINVAL; - strlcpy(audio->name, "Radio", sizeof(audio->name)); + strscpy(audio->name, "Radio", sizeof(audio->name)); audio->capability = V4L2_AUDCAP_STEREO; return 0; @@ -1523,7 +1523,7 @@ static int wl1273_fm_vidioc_g_tuner(struct file *file, void *priv, if (tuner->index > 0) return -EINVAL; - strlcpy(tuner->name, WL1273_FM_DRIVER_NAME, sizeof(tuner->name)); + strscpy(tuner->name, WL1273_FM_DRIVER_NAME, sizeof(tuner->name)); tuner->type = V4L2_TUNER_RADIO; tuner->rangelow = WL1273_FREQ(WL1273_BAND_JAPAN_LOW); @@ -1781,7 +1781,7 @@ static int wl1273_fm_vidioc_g_modulator(struct file *file, void *priv, dev_dbg(radio->dev, "%s\n", __func__); - strlcpy(modulator->name, WL1273_FM_DRIVER_NAME, + strscpy(modulator->name, WL1273_FM_DRIVER_NAME, sizeof(modulator->name)); modulator->rangelow = WL1273_FREQ(WL1273_BAND_JAPAN_LOW); diff --git a/drivers/media/radio/si470x/radio-si470x-common.c b/drivers/media/radio/si470x/radio-si470x-common.c index c40e1753f34b..1d7ab5462c77 100644 --- a/drivers/media/radio/si470x/radio-si470x-common.c +++ b/drivers/media/radio/si470x/radio-si470x-common.c @@ -622,7 +622,7 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv, } /* driver constants */ - strcpy(tuner->name, "FM"); + strscpy(tuner->name, "FM", sizeof(tuner->name)); tuner->type = V4L2_TUNER_RADIO; tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO | diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c index e3b3ecd14a4d..9751ea1d80be 100644 --- a/drivers/media/radio/si470x/radio-si470x-i2c.c +++ b/drivers/media/radio/si470x/radio-si470x-i2c.c @@ -229,8 +229,8 @@ static int si470x_fops_release(struct file *file) static int si470x_vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *capability) { - strlcpy(capability->driver, DRIVER_NAME, sizeof(capability->driver)); - strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card)); + strscpy(capability->driver, DRIVER_NAME, sizeof(capability->driver)); + strscpy(capability->card, DRIVER_CARD, sizeof(capability->card)); capability->device_caps = V4L2_CAP_HW_FREQ_SEEK | V4L2_CAP_READWRITE | V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_RDS_CAPTURE; capability->capabilities = capability->device_caps | V4L2_CAP_DEVICE_CAPS; diff --git a/drivers/media/radio/si470x/radio-si470x-usb.c b/drivers/media/radio/si470x/radio-si470x-usb.c index 313a95f195a2..91d6ef5579f7 100644 --- a/drivers/media/radio/si470x/radio-si470x-usb.c +++ b/drivers/media/radio/si470x/radio-si470x-usb.c @@ -519,8 +519,8 @@ static int si470x_vidioc_querycap(struct file *file, void *priv, { struct si470x_device *radio = video_drvdata(file); - strlcpy(capability->driver, DRIVER_NAME, sizeof(capability->driver)); - strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card)); + strscpy(capability->driver, DRIVER_NAME, sizeof(capability->driver)); + strscpy(capability->card, DRIVER_CARD, sizeof(capability->card)); usb_make_path(radio->usbdev, capability->bus_info, sizeof(capability->bus_info)); capability->device_caps = V4L2_CAP_HW_FREQ_SEEK | V4L2_CAP_READWRITE | diff --git a/drivers/media/radio/si4713/radio-platform-si4713.c b/drivers/media/radio/si4713/radio-platform-si4713.c index 27339ec495f6..733fcf3933e4 100644 --- a/drivers/media/radio/si4713/radio-platform-si4713.c +++ b/drivers/media/radio/si4713/radio-platform-si4713.c @@ -67,10 +67,10 @@ static const struct v4l2_file_operations radio_si4713_fops = { static int radio_si4713_querycap(struct file *file, void *priv, struct v4l2_capability *capability) { - strlcpy(capability->driver, "radio-si4713", sizeof(capability->driver)); - strlcpy(capability->card, "Silicon Labs Si4713 Modulator", + strscpy(capability->driver, "radio-si4713", sizeof(capability->driver)); + strscpy(capability->card, "Silicon Labs Si4713 Modulator", sizeof(capability->card)); - strlcpy(capability->bus_info, "platform:radio-si4713", + strscpy(capability->bus_info, "platform:radio-si4713", sizeof(capability->bus_info)); capability->device_caps = V4L2_CAP_MODULATOR | V4L2_CAP_RDS_OUTPUT; capability->capabilities = capability->device_caps | V4L2_CAP_DEVICE_CAPS; diff --git a/drivers/media/radio/si4713/radio-usb-si4713.c b/drivers/media/radio/si4713/radio-usb-si4713.c index 1ebbf0217142..23065ecce979 100644 --- a/drivers/media/radio/si4713/radio-usb-si4713.c +++ b/drivers/media/radio/si4713/radio-usb-si4713.c @@ -67,8 +67,8 @@ static int vidioc_querycap(struct file *file, void *priv, { struct si4713_usb_device *radio = video_drvdata(file); - strlcpy(v->driver, "radio-usb-si4713", sizeof(v->driver)); - strlcpy(v->card, "Si4713 FM Transmitter", sizeof(v->card)); + strscpy(v->driver, "radio-usb-si4713", sizeof(v->driver)); + strscpy(v->card, "Si4713 FM Transmitter", sizeof(v->card)); usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info)); v->device_caps = V4L2_CAP_MODULATOR | V4L2_CAP_RDS_OUTPUT; v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS; @@ -467,7 +467,7 @@ static int usb_si4713_probe(struct usb_interface *intf, radio->vdev.ctrl_handler = sd->ctrl_handler; radio->v4l2_dev.release = usb_si4713_video_device_release; - strlcpy(radio->vdev.name, radio->v4l2_dev.name, + strscpy(radio->vdev.name, radio->v4l2_dev.name, sizeof(radio->vdev.name)); radio->vdev.v4l2_dev = &radio->v4l2_dev; radio->vdev.fops = &usb_si4713_fops; diff --git a/drivers/media/radio/tea575x.c b/drivers/media/radio/tea575x.c index 7412fe1b10c6..f89f83e04741 100644 --- a/drivers/media/radio/tea575x.c +++ b/drivers/media/radio/tea575x.c @@ -233,10 +233,10 @@ static int vidioc_querycap(struct file *file, void *priv, { struct snd_tea575x *tea = video_drvdata(file); - strlcpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver)); - strlcpy(v->card, tea->card, sizeof(v->card)); + strscpy(v->driver, tea->v4l2_dev->name, sizeof(v->driver)); + strscpy(v->card, tea->card, sizeof(v->card)); strlcat(v->card, tea->tea5759 ? " TEA5759" : " TEA5757", sizeof(v->card)); - strlcpy(v->bus_info, tea->bus_info, sizeof(v->bus_info)); + strscpy(v->bus_info, tea->bus_info, sizeof(v->bus_info)); v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO; if (!tea->cannot_read_data) v->device_caps |= V4L2_CAP_HW_FREQ_SEEK; @@ -296,7 +296,7 @@ int snd_tea575x_g_tuner(struct snd_tea575x *tea, struct v4l2_tuner *v) snd_tea575x_enum_freq_bands(tea, &band_fm); memset(v, 0, sizeof(*v)); - strlcpy(v->name, tea->has_am ? "FM/AM" : "FM", sizeof(v->name)); + strscpy(v->name, tea->has_am ? "FM/AM" : "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; v->capability = band_fm.capability; v->rangelow = tea->has_am ? bands[BAND_AM].rangelow : band_fm.rangelow; @@ -537,7 +537,7 @@ int snd_tea575x_init(struct snd_tea575x *tea, struct module *owner) tea->vd = tea575x_radio; video_set_drvdata(&tea->vd, tea); mutex_init(&tea->mutex); - strlcpy(tea->vd.name, tea->v4l2_dev->name, sizeof(tea->vd.name)); + strscpy(tea->vd.name, tea->v4l2_dev->name, sizeof(tea->vd.name)); tea->vd.lock = &tea->mutex; tea->vd.v4l2_dev = tea->v4l2_dev; tea->fops = tea575x_fops; diff --git a/drivers/media/radio/tef6862.c b/drivers/media/radio/tef6862.c index ed210f4c476a..a76ff2978dfb 100644 --- a/drivers/media/radio/tef6862.c +++ b/drivers/media/radio/tef6862.c @@ -79,7 +79,7 @@ static int tef6862_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *v) return -EINVAL; /* only support FM for now */ - strlcpy(v->name, "FM", sizeof(v->name)); + strscpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; v->rangelow = TEF6862_LO_FREQ; v->rangehigh = TEF6862_HI_FREQ; diff --git a/drivers/media/radio/wl128x/fmdrv_v4l2.c b/drivers/media/radio/wl128x/fmdrv_v4l2.c index dccdf6558e6a..e25fd4d4d280 100644 --- a/drivers/media/radio/wl128x/fmdrv_v4l2.c +++ b/drivers/media/radio/wl128x/fmdrv_v4l2.c @@ -190,9 +190,9 @@ release_unlock: static int fm_v4l2_vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *capability) { - strlcpy(capability->driver, FM_DRV_NAME, sizeof(capability->driver)); - strlcpy(capability->card, FM_DRV_CARD_SHORT_NAME, - sizeof(capability->card)); + strscpy(capability->driver, FM_DRV_NAME, sizeof(capability->driver)); + strscpy(capability->card, FM_DRV_CARD_SHORT_NAME, + sizeof(capability->card)); sprintf(capability->bus_info, "UART"); capability->device_caps = V4L2_CAP_HW_FREQ_SEEK | V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_MODULATOR | @@ -249,7 +249,7 @@ static int fm_v4l2_vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *audio) { memset(audio, 0, sizeof(*audio)); - strcpy(audio->name, "Radio"); + strscpy(audio->name, "Radio", sizeof(audio->name)); audio->capability = V4L2_AUDCAP_STEREO; return 0; @@ -293,7 +293,7 @@ static int fm_v4l2_vidioc_g_tuner(struct file *file, void *priv, if (ret != 0) return ret; - strcpy(tuner->name, "FM"); + strscpy(tuner->name, "FM", sizeof(tuner->name)); tuner->type = V4L2_TUNER_RADIO; /* Store rangelow and rangehigh freq in unit of 62.5 Hz */ tuner->rangelow = bottom_freq * 16; @@ -531,7 +531,8 @@ int fm_v4l2_init_video_device(struct fmdev *fmdev, int radio_nr) struct v4l2_ctrl *ctrl; int ret; - strlcpy(fmdev->v4l2_dev.name, FM_DRV_NAME, sizeof(fmdev->v4l2_dev.name)); + strscpy(fmdev->v4l2_dev.name, FM_DRV_NAME, + sizeof(fmdev->v4l2_dev.name)); ret = v4l2_device_register(NULL, &fmdev->v4l2_dev); if (ret < 0) return ret; diff --git a/drivers/media/rc/ati_remote.c b/drivers/media/rc/ati_remote.c index 8e82610ffaad..265e91a2a70d 100644 --- a/drivers/media/rc/ati_remote.c +++ b/drivers/media/rc/ati_remote.c @@ -862,7 +862,7 @@ static int ati_remote_probe(struct usb_interface *interface, ati_remote->interface = interface; usb_make_path(udev, ati_remote->rc_phys, sizeof(ati_remote->rc_phys)); - strlcpy(ati_remote->mouse_phys, ati_remote->rc_phys, + strscpy(ati_remote->mouse_phys, ati_remote->rc_phys, sizeof(ati_remote->mouse_phys)); strlcat(ati_remote->rc_phys, "/input0", sizeof(ati_remote->rc_phys)); diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c index 71b8c9bbf6c4..dd2fd307ef85 100644 --- a/drivers/media/rc/ene_ir.c +++ b/drivers/media/rc/ene_ir.c @@ -326,8 +326,6 @@ static int ene_rx_get_sample_reg(struct ene_device *dev) /* Sense current received carrier */ static void ene_rx_sense_carrier(struct ene_device *dev) { - DEFINE_IR_RAW_EVENT(ev); - int carrier, duty_cycle; int period = ene_read_reg(dev, ENE_CIRCAR_PRD); int hperiod = ene_read_reg(dev, ENE_CIRCAR_HPRD); @@ -348,9 +346,11 @@ static void ene_rx_sense_carrier(struct ene_device *dev) dbg("RX: sensed carrier = %d Hz, duty cycle %d%%", carrier, duty_cycle); if (dev->carrier_detect_enabled) { - ev.carrier_report = true; - ev.carrier = carrier; - ev.duty_cycle = duty_cycle; + struct ir_raw_event ev = { + .carrier_report = true, + .carrier = carrier, + .duty_cycle = duty_cycle + }; ir_raw_event_store(dev->rdev, &ev); } } @@ -733,7 +733,7 @@ static irqreturn_t ene_isr(int irq, void *data) unsigned long flags; irqreturn_t retval = IRQ_NONE; struct ene_device *dev = (struct ene_device *)data; - DEFINE_IR_RAW_EVENT(ev); + struct ir_raw_event ev = {}; spin_lock_irqsave(&dev->hw_lock, flags); diff --git a/drivers/media/rc/fintek-cir.c b/drivers/media/rc/fintek-cir.c index f2639d0c2fca..601944666b71 100644 --- a/drivers/media/rc/fintek-cir.c +++ b/drivers/media/rc/fintek-cir.c @@ -282,7 +282,7 @@ static int fintek_cmdsize(u8 cmd, u8 subcmd) /* process ir data stored in driver buffer */ static void fintek_process_rx_ir_data(struct fintek_dev *fintek) { - DEFINE_IR_RAW_EVENT(rawir); + struct ir_raw_event rawir = {}; u8 sample; bool event = false; int i; @@ -314,7 +314,6 @@ static void fintek_process_rx_ir_data(struct fintek_dev *fintek) break; case PARSE_IRDATA: fintek->rem--; - init_ir_raw_event(&rawir); rawir.pulse = ((sample & BUF_PULSE_BIT) != 0); rawir.duration = US_TO_NS((sample & BUF_SAMPLE_MASK) * CIR_SAMPLE_PERIOD); diff --git a/drivers/media/rc/igorplugusb.c b/drivers/media/rc/igorplugusb.c index f563ddd7f739..ba3f95a97f14 100644 --- a/drivers/media/rc/igorplugusb.c +++ b/drivers/media/rc/igorplugusb.c @@ -56,7 +56,7 @@ static void igorplugusb_cmd(struct igorplugusb *ir, int cmd); static void igorplugusb_irdata(struct igorplugusb *ir, unsigned len) { - DEFINE_IR_RAW_EVENT(rawir); + struct ir_raw_event rawir = {}; unsigned i, start, overflow; dev_dbg(ir->dev, "irdata: %*ph (len=%u)", len, ir->buf_in, len); diff --git a/drivers/media/rc/iguanair.c b/drivers/media/rc/iguanair.c index 7daac8bab83b..fbacb13b614b 100644 --- a/drivers/media/rc/iguanair.c +++ b/drivers/media/rc/iguanair.c @@ -129,12 +129,10 @@ static void process_ir_data(struct iguanair *ir, unsigned len) break; } } else if (len >= 7) { - DEFINE_IR_RAW_EVENT(rawir); + struct ir_raw_event rawir = {}; unsigned i; bool event = false; - init_ir_raw_event(&rawir); - for (i = 0; i < 7; i++) { if (ir->buf_in[i] == 0x80) { rawir.pulse = false; diff --git a/drivers/media/rc/imon_raw.c b/drivers/media/rc/imon_raw.c index 32709f96de14..7796098d9c30 100644 --- a/drivers/media/rc/imon_raw.c +++ b/drivers/media/rc/imon_raw.c @@ -28,7 +28,7 @@ static inline int is_bit_set(const u8 *buf, int bit) static void imon_ir_data(struct imon *imon) { - DEFINE_IR_RAW_EVENT(rawir); + struct ir_raw_event rawir = {}; int offset = 0, size = 5 * 8; int bit; diff --git a/drivers/media/rc/ir-hix5hd2.c b/drivers/media/rc/ir-hix5hd2.c index 700ab4c563d0..abc4d6c1b323 100644 --- a/drivers/media/rc/ir-hix5hd2.c +++ b/drivers/media/rc/ir-hix5hd2.c @@ -175,7 +175,7 @@ static irqreturn_t hix5hd2_ir_rx_interrupt(int irq, void *data) } if ((irq_sr & INTMS_SYMBRCV) || (irq_sr & INTMS_TIMEOUT)) { - DEFINE_IR_RAW_EVENT(ev); + struct ir_raw_event ev = {}; symb_num = readl_relaxed(priv->base + IR_DATAH); for (i = 0; i < symb_num; i++) { diff --git a/drivers/media/rc/ir-imon-decoder.c b/drivers/media/rc/ir-imon-decoder.c index 67c1b0c15aae..a0efe2605393 100644 --- a/drivers/media/rc/ir-imon-decoder.c +++ b/drivers/media/rc/ir-imon-decoder.c @@ -70,24 +70,13 @@ static void ir_imon_decode_scancode(struct rc_dev *dev) } if (!imon->stick_keyboard) { - struct lirc_scancode lsc = { - .scancode = imon->bits, - .rc_proto = RC_PROTO_IMON, - }; + input_report_rel(dev->input_dev, REL_X, rel_x); + input_report_rel(dev->input_dev, REL_Y, rel_y); - ir_lirc_scancode_event(dev, &lsc); - - input_event(imon->idev, EV_MSC, MSC_SCAN, imon->bits); - - input_report_rel(imon->idev, REL_X, rel_x); - input_report_rel(imon->idev, REL_Y, rel_y); - - input_report_key(imon->idev, BTN_LEFT, + input_report_key(dev->input_dev, BTN_LEFT, (imon->bits & 0x00010000) != 0); - input_report_key(imon->idev, BTN_RIGHT, + input_report_key(dev->input_dev, BTN_RIGHT, (imon->bits & 0x00040000) != 0); - input_sync(imon->idev); - return; } } @@ -243,62 +232,19 @@ static int ir_imon_encode(enum rc_proto protocol, u32 scancode, static int ir_imon_register(struct rc_dev *dev) { - struct input_dev *idev; struct imon_dec *imon = &dev->raw->imon; - int ret; - - idev = input_allocate_device(); - if (!idev) - return -ENOMEM; - - snprintf(imon->name, sizeof(imon->name), - "iMON PAD Stick (%s)", dev->device_name); - idev->name = imon->name; - idev->phys = dev->input_phys; - - /* Mouse bits */ - set_bit(EV_REL, idev->evbit); - set_bit(EV_KEY, idev->evbit); - set_bit(REL_X, idev->relbit); - set_bit(REL_Y, idev->relbit); - set_bit(BTN_LEFT, idev->keybit); - set_bit(BTN_RIGHT, idev->keybit); - - /* Report scancodes too */ - set_bit(EV_MSC, idev->evbit); - set_bit(MSC_SCAN, idev->mscbit); - - input_set_drvdata(idev, imon); - - ret = input_register_device(idev); - if (ret < 0) { - input_free_device(idev); - return -EIO; - } - imon->idev = idev; imon->stick_keyboard = false; return 0; } -static int ir_imon_unregister(struct rc_dev *dev) -{ - struct imon_dec *imon = &dev->raw->imon; - - input_unregister_device(imon->idev); - imon->idev = NULL; - - return 0; -} - static struct ir_raw_handler imon_handler = { .protocols = RC_PROTO_BIT_IMON, .decode = ir_imon_decode, .encode = ir_imon_encode, .carrier = 38000, .raw_register = ir_imon_register, - .raw_unregister = ir_imon_unregister, .min_timeout = IMON_UNIT * IMON_BITS * 2, }; diff --git a/drivers/media/rc/ir-mce_kbd-decoder.c b/drivers/media/rc/ir-mce_kbd-decoder.c index 64ea42927669..67f1c179c713 100644 --- a/drivers/media/rc/ir-mce_kbd-decoder.c +++ b/drivers/media/rc/ir-mce_kbd-decoder.c @@ -129,13 +129,14 @@ static void mce_kbd_rx_timeout(struct timer_list *t) if (time_is_before_eq_jiffies(raw->mce_kbd.rx_timeout.expires)) { for (i = 0; i < 7; i++) { maskcode = kbd_keycodes[MCIR2_MASK_KEYS_START + i]; - input_report_key(raw->mce_kbd.idev, maskcode, 0); + input_report_key(raw->dev->input_dev, maskcode, 0); } for (i = 0; i < MCIR2_MASK_KEYS_START; i++) - input_report_key(raw->mce_kbd.idev, kbd_keycodes[i], 0); + input_report_key(raw->dev->input_dev, kbd_keycodes[i], + 0); - input_sync(raw->mce_kbd.idev); + input_sync(raw->dev->input_dev); } spin_unlock_irqrestore(&raw->mce_kbd.keylock, flags); } @@ -154,7 +155,6 @@ static enum mce_kbd_mode mce_kbd_mode(struct mce_kbd_dec *data) static void ir_mce_kbd_process_keyboard_data(struct rc_dev *dev, u32 scancode) { - struct mce_kbd_dec *data = &dev->raw->mce_kbd; u8 keydata1 = (scancode >> 8) & 0xff; u8 keydata2 = (scancode >> 16) & 0xff; u8 shiftmask = scancode & 0xff; @@ -170,23 +170,22 @@ static void ir_mce_kbd_process_keyboard_data(struct rc_dev *dev, u32 scancode) keystate = 1; else keystate = 0; - input_report_key(data->idev, maskcode, keystate); + input_report_key(dev->input_dev, maskcode, keystate); } if (keydata1) - input_report_key(data->idev, kbd_keycodes[keydata1], 1); + input_report_key(dev->input_dev, kbd_keycodes[keydata1], 1); if (keydata2) - input_report_key(data->idev, kbd_keycodes[keydata2], 1); + input_report_key(dev->input_dev, kbd_keycodes[keydata2], 1); if (!keydata1 && !keydata2) { for (i = 0; i < MCIR2_MASK_KEYS_START; i++) - input_report_key(data->idev, kbd_keycodes[i], 0); + input_report_key(dev->input_dev, kbd_keycodes[i], 0); } } static void ir_mce_kbd_process_mouse_data(struct rc_dev *dev, u32 scancode) { - struct mce_kbd_dec *data = &dev->raw->mce_kbd; /* raw mouse coordinates */ u8 xdata = (scancode >> 7) & 0x7f; u8 ydata = (scancode >> 14) & 0x7f; @@ -208,11 +207,11 @@ static void ir_mce_kbd_process_mouse_data(struct rc_dev *dev, u32 scancode) dev_dbg(&dev->dev, "mouse: x = %d, y = %d, btns = %s%s\n", x, y, left ? "L" : "", right ? "R" : ""); - input_report_rel(data->idev, REL_X, x); - input_report_rel(data->idev, REL_Y, y); + input_report_rel(dev->input_dev, REL_X, x); + input_report_rel(dev->input_dev, REL_Y, y); - input_report_key(data->idev, BTN_LEFT, left); - input_report_key(data->idev, BTN_RIGHT, right); + input_report_key(dev->input_dev, BTN_LEFT, left); + input_report_key(dev->input_dev, BTN_RIGHT, right); } /** @@ -355,8 +354,8 @@ again: lsc.scancode = scancode; ir_lirc_scancode_event(dev, &lsc); data->state = STATE_INACTIVE; - input_event(data->idev, EV_MSC, MSC_SCAN, scancode); - input_sync(data->idev); + input_event(dev->input_dev, EV_MSC, MSC_SCAN, scancode); + input_sync(dev->input_dev); return 0; } @@ -370,66 +369,18 @@ out: static int ir_mce_kbd_register(struct rc_dev *dev) { struct mce_kbd_dec *mce_kbd = &dev->raw->mce_kbd; - struct input_dev *idev; - int i, ret; - - idev = input_allocate_device(); - if (!idev) - return -ENOMEM; - - snprintf(mce_kbd->name, sizeof(mce_kbd->name), - "MCE IR Keyboard/Mouse (%s)", dev->driver_name); - strlcat(mce_kbd->phys, "/input0", sizeof(mce_kbd->phys)); - - idev->name = mce_kbd->name; - idev->phys = mce_kbd->phys; - - /* Keyboard bits */ - set_bit(EV_KEY, idev->evbit); - set_bit(EV_REP, idev->evbit); - for (i = 0; i < sizeof(kbd_keycodes); i++) - set_bit(kbd_keycodes[i], idev->keybit); - - /* Mouse bits */ - set_bit(EV_REL, idev->evbit); - set_bit(REL_X, idev->relbit); - set_bit(REL_Y, idev->relbit); - set_bit(BTN_LEFT, idev->keybit); - set_bit(BTN_RIGHT, idev->keybit); - - /* Report scancodes too */ - set_bit(EV_MSC, idev->evbit); - set_bit(MSC_SCAN, idev->mscbit); timer_setup(&mce_kbd->rx_timeout, mce_kbd_rx_timeout, 0); spin_lock_init(&mce_kbd->keylock); - input_set_drvdata(idev, mce_kbd); - -#if 0 - /* Adding this reference means two input devices are associated with - * this rc-core device, which ir-keytable doesn't cope with yet */ - idev->dev.parent = &dev->dev; -#endif - - ret = input_register_device(idev); - if (ret < 0) { - input_free_device(idev); - return -EIO; - } - - mce_kbd->idev = idev; - return 0; } static int ir_mce_kbd_unregister(struct rc_dev *dev) { struct mce_kbd_dec *mce_kbd = &dev->raw->mce_kbd; - struct input_dev *idev = mce_kbd->idev; del_timer_sync(&mce_kbd->rx_timeout); - input_unregister_device(idev); return 0; } diff --git a/drivers/media/rc/ir-rc6-decoder.c b/drivers/media/rc/ir-rc6-decoder.c index 68487ce9f79b..d96aed1343e4 100644 --- a/drivers/media/rc/ir-rc6-decoder.c +++ b/drivers/media/rc/ir-rc6-decoder.c @@ -40,6 +40,7 @@ #define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */ #define RC6_6A_LCC_MASK 0xffff0000 /* RC6-6A-32 long customer code mask */ #define RC6_6A_MCE_CC 0x800f0000 /* MCE customer code */ +#define RC6_6A_KATHREIN_CC 0x80460000 /* Kathrein RCU-676 customer code */ #ifndef CHAR_BIT #define CHAR_BIT 8 /* Normally in <limits.h> */ #endif @@ -242,13 +243,17 @@ again: toggle = 0; break; case 32: - if ((scancode & RC6_6A_LCC_MASK) == RC6_6A_MCE_CC) { + switch (scancode & RC6_6A_LCC_MASK) { + case RC6_6A_MCE_CC: + case RC6_6A_KATHREIN_CC: protocol = RC_PROTO_RC6_MCE; toggle = !!(scancode & RC6_6A_MCE_TOGGLE_MASK); scancode &= ~RC6_6A_MCE_TOGGLE_MASK; - } else { + break; + default: protocol = RC_PROTO_RC6_6A_32; toggle = 0; + break; } break; default: diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c index de77d22c30a7..cd3c60ba8519 100644 --- a/drivers/media/rc/ite-cir.c +++ b/drivers/media/rc/ite-cir.c @@ -173,7 +173,7 @@ static void ite_decode_bytes(struct ite_dev *dev, const u8 * data, int u32 sample_period; unsigned long *ldata; unsigned int next_one, next_zero, size; - DEFINE_IR_RAW_EVENT(ev); + struct ir_raw_event ev = {}; if (length == 0) return; @@ -1507,9 +1507,6 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id /* initialize spinlocks */ spin_lock_init(&itdev->lock); - /* initialize raw event */ - init_ir_raw_event(&itdev->rawir); - /* set driver data into the pnp device */ pnp_set_drvdata(pdev, itdev); itdev->pdev = pdev; diff --git a/drivers/media/rc/keymaps/rc-behold.c b/drivers/media/rc/keymaps/rc-behold.c index 9b1b57e3c875..e1b2c8e26883 100644 --- a/drivers/media/rc/keymaps/rc-behold.c +++ b/drivers/media/rc/keymaps/rc-behold.c @@ -115,7 +115,7 @@ static struct rc_map_list behold_map = { .map = { .scan = behold, .size = ARRAY_SIZE(behold), - .rc_proto = RC_PROTO_NEC, + .rc_proto = RC_PROTO_NECX, .name = RC_MAP_BEHOLD, } }; diff --git a/drivers/media/rc/keymaps/rc-delock-61959.c b/drivers/media/rc/keymaps/rc-delock-61959.c index 62de69d78d92..da21d6d6d79f 100644 --- a/drivers/media/rc/keymaps/rc-delock-61959.c +++ b/drivers/media/rc/keymaps/rc-delock-61959.c @@ -60,7 +60,7 @@ static struct rc_map_list delock_61959_map = { .map = { .scan = delock_61959, .size = ARRAY_SIZE(delock_61959), - .rc_proto = RC_PROTO_NEC, + .rc_proto = RC_PROTO_NECX, .name = RC_MAP_DELOCK_61959, } }; diff --git a/drivers/media/rc/keymaps/rc-imon-rsc.c b/drivers/media/rc/keymaps/rc-imon-rsc.c index 83e4564aaa22..6f7ee4859682 100644 --- a/drivers/media/rc/keymaps/rc-imon-rsc.c +++ b/drivers/media/rc/keymaps/rc-imon-rsc.c @@ -59,7 +59,7 @@ static struct rc_map_list imon_rsc_map = { .map = { .scan = imon_rsc, .size = ARRAY_SIZE(imon_rsc), - .rc_proto = RC_PROTO_NEC, + .rc_proto = RC_PROTO_NECX, .name = RC_MAP_IMON_RSC, } }; diff --git a/drivers/media/rc/keymaps/rc-it913x-v1.c b/drivers/media/rc/keymaps/rc-it913x-v1.c index 908d14848ae8..f1b5c52953ad 100644 --- a/drivers/media/rc/keymaps/rc-it913x-v1.c +++ b/drivers/media/rc/keymaps/rc-it913x-v1.c @@ -73,7 +73,7 @@ static struct rc_map_list it913x_v1_map = { .map = { .scan = it913x_v1_rc, .size = ARRAY_SIZE(it913x_v1_rc), - .rc_proto = RC_PROTO_NEC, + .rc_proto = RC_PROTO_NECX, .name = RC_MAP_IT913X_V1, } }; diff --git a/drivers/media/rc/keymaps/rc-it913x-v2.c b/drivers/media/rc/keymaps/rc-it913x-v2.c index 05ab7fa4f90b..be5dfb4fae46 100644 --- a/drivers/media/rc/keymaps/rc-it913x-v2.c +++ b/drivers/media/rc/keymaps/rc-it913x-v2.c @@ -72,7 +72,7 @@ static struct rc_map_list it913x_v2_map = { .map = { .scan = it913x_v2_rc, .size = ARRAY_SIZE(it913x_v2_rc), - .rc_proto = RC_PROTO_NEC, + .rc_proto = RC_PROTO_NECX, .name = RC_MAP_IT913X_V2, } }; diff --git a/drivers/media/rc/keymaps/rc-msi-digivox-iii.c b/drivers/media/rc/keymaps/rc-msi-digivox-iii.c index 8fec0c1dcb12..d50e741c73b7 100644 --- a/drivers/media/rc/keymaps/rc-msi-digivox-iii.c +++ b/drivers/media/rc/keymaps/rc-msi-digivox-iii.c @@ -64,7 +64,7 @@ static struct rc_map_list msi_digivox_iii_map = { .map = { .scan = msi_digivox_iii, .size = ARRAY_SIZE(msi_digivox_iii), - .rc_proto = RC_PROTO_NEC, + .rc_proto = RC_PROTO_NECX, .name = RC_MAP_MSI_DIGIVOX_III, } }; diff --git a/drivers/media/rc/keymaps/rc-pixelview-002t.c b/drivers/media/rc/keymaps/rc-pixelview-002t.c index 4ed85f61d0ee..c0550e09f255 100644 --- a/drivers/media/rc/keymaps/rc-pixelview-002t.c +++ b/drivers/media/rc/keymaps/rc-pixelview-002t.c @@ -51,7 +51,7 @@ static struct rc_map_list pixelview_map = { .map = { .scan = pixelview_002t, .size = ARRAY_SIZE(pixelview_002t), - .rc_proto = RC_PROTO_NEC, + .rc_proto = RC_PROTO_NECX, .name = RC_MAP_PIXELVIEW_002T, } }; diff --git a/drivers/media/rc/keymaps/rc-pixelview-mk12.c b/drivers/media/rc/keymaps/rc-pixelview-mk12.c index 6ded64b732a5..864c8ea5d8e3 100644 --- a/drivers/media/rc/keymaps/rc-pixelview-mk12.c +++ b/drivers/media/rc/keymaps/rc-pixelview-mk12.c @@ -57,7 +57,7 @@ static struct rc_map_list pixelview_map = { .map = { .scan = pixelview_mk12, .size = ARRAY_SIZE(pixelview_mk12), - .rc_proto = RC_PROTO_NEC, + .rc_proto = RC_PROTO_NECX, .name = RC_MAP_PIXELVIEW_MK12, } }; diff --git a/drivers/media/rc/keymaps/rc-reddo.c b/drivers/media/rc/keymaps/rc-reddo.c index 3b37acc7b144..b73223e8c238 100644 --- a/drivers/media/rc/keymaps/rc-reddo.c +++ b/drivers/media/rc/keymaps/rc-reddo.c @@ -64,7 +64,7 @@ static struct rc_map_list reddo_map = { .map = { .scan = reddo, .size = ARRAY_SIZE(reddo), - .rc_proto = RC_PROTO_NEC, + .rc_proto = RC_PROTO_NECX, .name = RC_MAP_REDDO, } }; diff --git a/drivers/media/rc/keymaps/rc-terratec-slim.c b/drivers/media/rc/keymaps/rc-terratec-slim.c index 628272c58d65..58a209811d12 100644 --- a/drivers/media/rc/keymaps/rc-terratec-slim.c +++ b/drivers/media/rc/keymaps/rc-terratec-slim.c @@ -58,7 +58,7 @@ static struct rc_map_list terratec_slim_map = { .map = { .scan = terratec_slim, .size = ARRAY_SIZE(terratec_slim), - .rc_proto = RC_PROTO_NEC, + .rc_proto = RC_PROTO_NECX, .name = RC_MAP_TERRATEC_SLIM, } }; diff --git a/drivers/media/rc/keymaps/rc-tivo.c b/drivers/media/rc/keymaps/rc-tivo.c index 1962e33c8f4e..20268f8b18fd 100644 --- a/drivers/media/rc/keymaps/rc-tivo.c +++ b/drivers/media/rc/keymaps/rc-tivo.c @@ -77,7 +77,7 @@ static struct rc_map_list tivo_map = { .map = { .scan = tivo, .size = ARRAY_SIZE(tivo), - .rc_proto = RC_PROTO_NEC, + .rc_proto = RC_PROTO_NEC32, .name = RC_MAP_TIVO, } }; diff --git a/drivers/media/rc/keymaps/rc-total-media-in-hand.c b/drivers/media/rc/keymaps/rc-total-media-in-hand.c index bc73bee309d8..c34e8f5a88b6 100644 --- a/drivers/media/rc/keymaps/rc-total-media-in-hand.c +++ b/drivers/media/rc/keymaps/rc-total-media-in-hand.c @@ -64,7 +64,7 @@ static struct rc_map_list total_media_in_hand_map = { .map = { .scan = total_media_in_hand, .size = ARRAY_SIZE(total_media_in_hand), - .rc_proto = RC_PROTO_NEC, + .rc_proto = RC_PROTO_NECX, .name = RC_MAP_TOTAL_MEDIA_IN_HAND, } }; diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c index 4c0c8008872a..c9293696dc2d 100644 --- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c @@ -1078,7 +1078,7 @@ static int mceusb_set_rx_carrier_report(struct rc_dev *dev, int enable) */ static void mceusb_handle_command(struct mceusb_dev *ir, int index) { - DEFINE_IR_RAW_EVENT(rawir); + struct ir_raw_event rawir = {}; u8 hi = ir->buf_in[index + 1] & 0xff; u8 lo = ir->buf_in[index + 2] & 0xff; u32 carrier_cycles; @@ -1152,7 +1152,7 @@ static void mceusb_handle_command(struct mceusb_dev *ir, int index) static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len) { - DEFINE_IR_RAW_EVENT(rawir); + struct ir_raw_event rawir = {}; bool event = false; int i = 0; @@ -1175,7 +1175,6 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len) break; case PARSE_IRDATA: ir->rem--; - init_ir_raw_event(&rawir); rawir.pulse = ((ir->buf_in[i] & MCE_PULSE_BIT) != 0); rawir.duration = (ir->buf_in[i] & MCE_PULSE_MASK); if (unlikely(!rawir.duration)) { @@ -1215,11 +1214,13 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len) if (ir->rem) { ir->parser_state = PARSE_IRDATA; } else { - init_ir_raw_event(&rawir); - rawir.timeout = 1; - rawir.duration = ir->rc->timeout; + struct ir_raw_event ev = { + .timeout = 1, + .duration = ir->rc->timeout + }; + if (ir_raw_event_store_with_filter(ir->rc, - &rawir)) + &ev)) event = true; ir->pulse_tunit = 0; ir->pulse_count = 0; @@ -1603,7 +1604,7 @@ static int mceusb_dev_probe(struct usb_interface *intf, if (dev->descriptor.iManufacturer && usb_string(dev, dev->descriptor.iManufacturer, buf, sizeof(buf)) > 0) - strlcpy(name, buf, sizeof(name)); + strscpy(name, buf, sizeof(name)); if (dev->descriptor.iProduct && usb_string(dev, dev->descriptor.iProduct, buf, sizeof(buf)) > 0) diff --git a/drivers/media/rc/meson-ir.c b/drivers/media/rc/meson-ir.c index f449b35d25e7..9914c83fecb9 100644 --- a/drivers/media/rc/meson-ir.c +++ b/drivers/media/rc/meson-ir.c @@ -86,7 +86,7 @@ static irqreturn_t meson_ir_irq(int irqno, void *dev_id) { struct meson_ir *ir = dev_id; u32 duration, status; - DEFINE_IR_RAW_EVENT(rawir); + struct ir_raw_event rawir = {}; spin_lock(&ir->lock); diff --git a/drivers/media/rc/mtk-cir.c b/drivers/media/rc/mtk-cir.c index e42efd9d382e..31b7bb431497 100644 --- a/drivers/media/rc/mtk-cir.c +++ b/drivers/media/rc/mtk-cir.c @@ -212,7 +212,7 @@ static irqreturn_t mtk_ir_irq(int irqno, void *dev_id) struct mtk_ir *ir = dev_id; u8 wid = 0; u32 i, j, val; - DEFINE_IR_RAW_EVENT(rawir); + struct ir_raw_event rawir = {}; /* * Reset decoder state machine explicitly is required diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index b8299c9a9744..5c2cd8d2d155 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -737,7 +737,7 @@ static void nvt_dump_rx_buf(struct nvt_dev *nvt) */ static void nvt_process_rx_ir_data(struct nvt_dev *nvt) { - DEFINE_IR_RAW_EVENT(rawir); + struct ir_raw_event rawir = {}; u8 sample; int i; diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h index e847bdad5c51..c2cbe7f6266c 100644 --- a/drivers/media/rc/rc-core-priv.h +++ b/drivers/media/rc/rc-core-priv.h @@ -110,12 +110,9 @@ struct ir_raw_event_ctrl { unsigned int pulse_len; } sharp; struct mce_kbd_dec { - struct input_dev *idev; /* locks key up timer */ spinlock_t keylock; struct timer_list rx_timeout; - char name[64]; - char phys[64]; int state; u8 header; u32 body; @@ -133,8 +130,6 @@ struct ir_raw_event_ctrl { int last_chk; unsigned int bits; bool stick_keyboard; - struct input_dev *idev; - char name[64]; } imon; }; @@ -181,9 +176,10 @@ static inline void init_ir_raw_event_duration(struct ir_raw_event *ev, unsigned int pulse, u32 duration) { - init_ir_raw_event(ev); - ev->duration = duration; - ev->pulse = pulse; + *ev = (struct ir_raw_event) { + .duration = duration, + .pulse = pulse + }; } /** diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c index e7948908e78c..e10b4644a442 100644 --- a/drivers/media/rc/rc-ir-raw.c +++ b/drivers/media/rc/rc-ir-raw.c @@ -102,7 +102,7 @@ EXPORT_SYMBOL_GPL(ir_raw_event_store); int ir_raw_event_store_edge(struct rc_dev *dev, bool pulse) { ktime_t now; - DEFINE_IR_RAW_EVENT(ev); + struct ir_raw_event ev = {}; if (!dev->raw) return -EINVAL; @@ -210,7 +210,7 @@ void ir_raw_event_set_idle(struct rc_dev *dev, bool idle) if (idle) { dev->raw->this_ev.timeout = true; ir_raw_event_store(dev, &dev->raw->this_ev); - init_ir_raw_event(&dev->raw->this_ev); + dev->raw->this_ev = (struct ir_raw_event) {}; } if (dev->s_idle) @@ -562,10 +562,10 @@ static void ir_raw_edge_handle(struct timer_list *t) spin_lock_irqsave(&dev->raw->edge_spinlock, flags); interval = ktime_sub(ktime_get(), dev->raw->last_event); if (ktime_to_ns(interval) >= dev->timeout) { - DEFINE_IR_RAW_EVENT(ev); - - ev.timeout = true; - ev.duration = ktime_to_ns(interval); + struct ir_raw_event ev = { + .timeout = true, + .duration = ktime_to_ns(interval) + }; ir_raw_event_store(dev, &ev); } else { diff --git a/drivers/media/rc/rc-loopback.c b/drivers/media/rc/rc-loopback.c index 3822d9ebcb46..b9f9325b8db1 100644 --- a/drivers/media/rc/rc-loopback.c +++ b/drivers/media/rc/rc-loopback.c @@ -103,7 +103,7 @@ static int loop_tx_ir(struct rc_dev *dev, unsigned *txbuf, unsigned count) struct loopback_dev *lodev = dev->priv; u32 rxmask; unsigned i; - DEFINE_IR_RAW_EVENT(rawir); + struct ir_raw_event rawir = {}; if (lodev->txcarrier < lodev->rxcarriermin || lodev->txcarrier > lodev->rxcarriermax) { diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index ca68e1d2b2f9..552bbe82a160 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -274,7 +274,6 @@ static unsigned int ir_update_mapping(struct rc_dev *dev, unsigned int new_keycode) { int old_keycode = rc_map->scan[index].keycode; - int i; /* Did the user wish to remove the mapping? */ if (new_keycode == KEY_RESERVED || new_keycode == KEY_UNKNOWN) { @@ -289,20 +288,9 @@ static unsigned int ir_update_mapping(struct rc_dev *dev, old_keycode == KEY_RESERVED ? "New" : "Replacing", rc_map->scan[index].scancode, new_keycode); rc_map->scan[index].keycode = new_keycode; - __set_bit(new_keycode, dev->input_dev->keybit); } if (old_keycode != KEY_RESERVED) { - /* A previous mapping was updated... */ - __clear_bit(old_keycode, dev->input_dev->keybit); - /* ... but another scancode might use the same keycode */ - for (i = 0; i < rc_map->len; i++) { - if (rc_map->scan[i].keycode == old_keycode) { - __set_bit(old_keycode, dev->input_dev->keybit); - break; - } - } - /* Possibly shrink the keytable, failure is not a problem */ ir_resize_table(dev, rc_map, GFP_ATOMIC); } @@ -1755,10 +1743,18 @@ static int rc_prepare_rx_device(struct rc_dev *dev) dev->enabled_protocols = rc_proto; } + /* Keyboard events */ set_bit(EV_KEY, dev->input_dev->evbit); set_bit(EV_REP, dev->input_dev->evbit); set_bit(EV_MSC, dev->input_dev->evbit); set_bit(MSC_SCAN, dev->input_dev->mscbit); + bitmap_fill(dev->input_dev->keybit, KEY_CNT); + + /* Pointer/mouse events */ + set_bit(EV_REL, dev->input_dev->evbit); + set_bit(REL_X, dev->input_dev->relbit); + set_bit(REL_Y, dev->input_dev->relbit); + if (dev->open) dev->input_dev->open = ir_open; if (dev->close) diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c index 6bfc24885b5c..08c51ffd74a0 100644 --- a/drivers/media/rc/redrat3.c +++ b/drivers/media/rc/redrat3.c @@ -348,7 +348,7 @@ static u32 redrat3_us_to_len(u32 microsec) static void redrat3_process_ir_data(struct redrat3_dev *rr3) { - DEFINE_IR_RAW_EVENT(rawir); + struct ir_raw_event rawir = {}; struct device *dev; unsigned int i, sig_size, single_len, offset, val; u32 mod_freq; @@ -358,10 +358,10 @@ static void redrat3_process_ir_data(struct redrat3_dev *rr3) mod_freq = redrat3_val_to_mod_freq(&rr3->irdata); dev_dbg(dev, "Got mod_freq of %u\n", mod_freq); if (mod_freq && rr3->wideband) { - DEFINE_IR_RAW_EVENT(ev); - - ev.carrier_report = 1; - ev.carrier = mod_freq; + struct ir_raw_event ev = { + .carrier_report = 1, + .carrier = mod_freq + }; ir_raw_event_store(rr3->rc, &ev); } diff --git a/drivers/media/rc/serial_ir.c b/drivers/media/rc/serial_ir.c index 8bf5637b3a69..ffe2c672d105 100644 --- a/drivers/media/rc/serial_ir.c +++ b/drivers/media/rc/serial_ir.c @@ -273,7 +273,7 @@ static void frbwrite(unsigned int l, bool is_pulse) { /* simple noise filter */ static unsigned int ptr, pulse, space; - DEFINE_IR_RAW_EVENT(ev); + struct ir_raw_event ev = {}; if (ptr > 0 && is_pulse) { pulse += l; @@ -472,10 +472,10 @@ static int hardware_init_port(void) static void serial_ir_timeout(struct timer_list *unused) { - DEFINE_IR_RAW_EVENT(ev); - - ev.timeout = true; - ev.duration = serial_ir.rcdev->timeout; + struct ir_raw_event ev = { + .timeout = true, + .duration = serial_ir.rcdev->timeout + }; ir_raw_event_store_with_filter(serial_ir.rcdev, &ev); ir_raw_event_handle(serial_ir.rcdev); } diff --git a/drivers/media/rc/sir_ir.c b/drivers/media/rc/sir_ir.c index 9ee2c9196b4d..c8951650a368 100644 --- a/drivers/media/rc/sir_ir.c +++ b/drivers/media/rc/sir_ir.c @@ -96,7 +96,7 @@ static int sir_tx_ir(struct rc_dev *dev, unsigned int *tx_buf, static void add_read_queue(int flag, unsigned long val) { - DEFINE_IR_RAW_EVENT(ev); + struct ir_raw_event ev = {}; pr_debug("add flag %d with val %lu\n", flag, val); diff --git a/drivers/media/rc/st_rc.c b/drivers/media/rc/st_rc.c index c855b177103c..15de3ae166a2 100644 --- a/drivers/media/rc/st_rc.c +++ b/drivers/media/rc/st_rc.c @@ -67,8 +67,7 @@ struct st_rc_device { static void st_rc_send_lirc_timeout(struct rc_dev *rdev) { - DEFINE_IR_RAW_EVENT(ev); - ev.timeout = true; + struct ir_raw_event ev = { .timeout = true, .duration = rdev->timeout }; ir_raw_event_store(rdev, &ev); } @@ -101,7 +100,7 @@ static irqreturn_t st_rc_rx_interrupt(int irq, void *data) struct st_rc_device *dev = data; int last_symbol = 0; u32 status, int_status; - DEFINE_IR_RAW_EVENT(ev); + struct ir_raw_event ev = {}; if (dev->irq_wake) pm_wakeup_event(dev->dev, 0); diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c index c9a70fda88a8..a490d26bd170 100644 --- a/drivers/media/rc/streamzap.c +++ b/drivers/media/rc/streamzap.c @@ -130,7 +130,7 @@ static void sz_push(struct streamzap_ir *sz, struct ir_raw_event rawir) static void sz_push_full_pulse(struct streamzap_ir *sz, unsigned char value) { - DEFINE_IR_RAW_EVENT(rawir); + struct ir_raw_event rawir = {}; if (sz->idle) { int delta; @@ -175,7 +175,7 @@ static void sz_push_half_pulse(struct streamzap_ir *sz, static void sz_push_full_space(struct streamzap_ir *sz, unsigned char value) { - DEFINE_IR_RAW_EVENT(rawir); + struct ir_raw_event rawir = {}; rawir.pulse = false; rawir.duration = ((int) value) * SZ_RESOLUTION; @@ -249,10 +249,10 @@ static void streamzap_callback(struct urb *urb) break; case FullSpace: if (sz->buf_in[i] == SZ_TIMEOUT) { - DEFINE_IR_RAW_EVENT(rawir); - - rawir.pulse = false; - rawir.duration = sz->rdev->timeout; + struct ir_raw_event rawir = { + .pulse = false, + .duration = sz->rdev->timeout + }; sz->idle = true; if (sz->timeout_enabled) sz_push(sz, rawir); @@ -396,7 +396,7 @@ static int streamzap_probe(struct usb_interface *intf, if (usbdev->descriptor.iManufacturer && usb_string(usbdev, usbdev->descriptor.iManufacturer, buf, sizeof(buf)) > 0) - strlcpy(name, buf, sizeof(name)); + strscpy(name, buf, sizeof(name)); if (usbdev->descriptor.iProduct && usb_string(usbdev, usbdev->descriptor.iProduct, diff --git a/drivers/media/rc/sunxi-cir.c b/drivers/media/rc/sunxi-cir.c index f500cea228a9..307e44714ea0 100644 --- a/drivers/media/rc/sunxi-cir.c +++ b/drivers/media/rc/sunxi-cir.c @@ -99,7 +99,7 @@ static irqreturn_t sunxi_ir_irq(int irqno, void *dev_id) unsigned char dt; unsigned int cnt, rc; struct sunxi_ir *ir = dev_id; - DEFINE_IR_RAW_EVENT(rawir); + struct ir_raw_event rawir = {}; spin_lock(&ir->ir_lock); diff --git a/drivers/media/rc/ttusbir.c b/drivers/media/rc/ttusbir.c index aafea3c5170b..8d4b56d057ae 100644 --- a/drivers/media/rc/ttusbir.c +++ b/drivers/media/rc/ttusbir.c @@ -117,12 +117,10 @@ static void ttusbir_bulk_complete(struct urb *urb) */ static void ttusbir_process_ir_data(struct ttusbir *tt, uint8_t *buf) { - struct ir_raw_event rawir; + struct ir_raw_event rawir = {}; unsigned i, v, b; bool event = false; - init_ir_raw_event(&rawir); - for (i = 0; i < 128; i++) { v = buf[i] & 0xfe; switch (v) { diff --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c index 851acba9b436..0f07a2c384fa 100644 --- a/drivers/media/rc/winbond-cir.c +++ b/drivers/media/rc/winbond-cir.c @@ -322,11 +322,11 @@ wbcir_carrier_report(struct wbcir_data *data) inb(data->ebase + WBCIR_REG_ECEIR_CNT_HI) << 8; if (counter > 0 && counter < 0xffff) { - DEFINE_IR_RAW_EVENT(ev); - - ev.carrier_report = 1; - ev.carrier = DIV_ROUND_CLOSEST(counter * 1000000u, - data->pulse_duration); + struct ir_raw_event ev = { + .carrier_report = 1, + .carrier = DIV_ROUND_CLOSEST(counter * 1000000u, + data->pulse_duration) + }; ir_raw_event_store(data->dev, &ev); } @@ -362,7 +362,7 @@ static void wbcir_irq_rx(struct wbcir_data *data, struct pnp_dev *device) { u8 irdata; - DEFINE_IR_RAW_EVENT(rawir); + struct ir_raw_event rawir = {}; unsigned duration; /* Since RXHDLEV is set, at least 8 bytes are in the FIFO */ diff --git a/drivers/media/tuners/e4000.c b/drivers/media/tuners/e4000.c index fbec1a13dc6a..91956fb55b75 100644 --- a/drivers/media/tuners/e4000.c +++ b/drivers/media/tuners/e4000.c @@ -312,7 +312,7 @@ static int e4000_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *v) dev_dbg(&client->dev, "index=%d\n", v->index); - strlcpy(v->name, "Elonics E4000", sizeof(v->name)); + strscpy(v->name, "Elonics E4000", sizeof(v->name)); v->type = V4L2_TUNER_RF; v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS; v->rangelow = bands[0].rangelow; diff --git a/drivers/media/tuners/fc2580.c b/drivers/media/tuners/fc2580.c index db26892aac84..dd88cf7148d0 100644 --- a/drivers/media/tuners/fc2580.c +++ b/drivers/media/tuners/fc2580.c @@ -405,7 +405,7 @@ static int fc2580_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *v) dev_dbg(&client->dev, "index=%d\n", v->index); - strlcpy(v->name, "FCI FC2580", sizeof(v->name)); + strscpy(v->name, "FCI FC2580", sizeof(v->name)); v->type = V4L2_TUNER_RF; v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS; v->rangelow = bands[0].rangelow; diff --git a/drivers/media/tuners/msi001.c b/drivers/media/tuners/msi001.c index 5de6ed728708..331c198c00bb 100644 --- a/drivers/media/tuners/msi001.c +++ b/drivers/media/tuners/msi001.c @@ -305,7 +305,7 @@ static int msi001_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *v) dev_dbg(&spi->dev, "index=%d\n", v->index); - strlcpy(v->name, "Mirics MSi001", sizeof(v->name)); + strscpy(v->name, "Mirics MSi001", sizeof(v->name)); v->type = V4L2_TUNER_RF; v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS; v->rangelow = 49000000; diff --git a/drivers/media/tuners/mt20xx.c b/drivers/media/tuners/mt20xx.c index 129bf8e1aff8..8b4ce84b6914 100644 --- a/drivers/media/tuners/mt20xx.c +++ b/drivers/media/tuners/mt20xx.c @@ -636,7 +636,7 @@ struct dvb_frontend *microtune_attach(struct dvb_frontend *fe, return NULL; } - strlcpy(fe->ops.tuner_ops.info.name, name, + strscpy(fe->ops.tuner_ops.info.name, name, sizeof(fe->ops.tuner_ops.info.name)); tuner_info("microtune %s found, OK\n",name); return fe; diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index a08d8fe2bb1b..d389f1fc237a 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -468,11 +468,14 @@ static int si2157_probe(struct i2c_client *client, dev->ent.name = KBUILD_MODNAME; dev->ent.function = MEDIA_ENT_F_TUNER; - dev->pad[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK; - dev->pad[TUNER_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; - dev->pad[TUNER_PAD_AUD_OUT].flags = MEDIA_PAD_FL_SOURCE; - - ret = media_entity_pads_init(&dev->ent, TUNER_NUM_PADS, + dev->pad[SI2157_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK; + dev->pad[SI2157_PAD_RF_INPUT].sig_type = PAD_SIGNAL_ANALOG; + dev->pad[SI2157_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE; + dev->pad[SI2157_PAD_VID_OUT].sig_type = PAD_SIGNAL_ANALOG; + dev->pad[SI2157_PAD_AUD_OUT].flags = MEDIA_PAD_FL_SOURCE; + dev->pad[SI2157_PAD_AUD_OUT].sig_type = PAD_SIGNAL_AUDIO; + + ret = media_entity_pads_init(&dev->ent, SI2157_NUM_PADS, &dev->pad[0]); if (ret) diff --git a/drivers/media/tuners/si2157_priv.h b/drivers/media/tuners/si2157_priv.h index e6436f74abaa..50f86300d965 100644 --- a/drivers/media/tuners/si2157_priv.h +++ b/drivers/media/tuners/si2157_priv.h @@ -21,6 +21,13 @@ #include <media/v4l2-mc.h> #include "si2157.h" +enum si2157_pads { + SI2157_PAD_RF_INPUT, + SI2157_PAD_VID_OUT, + SI2157_PAD_AUD_OUT, + SI2157_NUM_PADS +}; + /* state struct */ struct si2157_dev { struct mutex i2c_mutex; @@ -35,7 +42,7 @@ struct si2157_dev { #if defined(CONFIG_MEDIA_CONTROLLER) struct media_device *mdev; struct media_entity ent; - struct media_pad pad[TUNER_NUM_PADS]; + struct media_pad pad[SI2157_NUM_PADS]; #endif }; diff --git a/drivers/media/tuners/tuner-simple.c b/drivers/media/tuners/tuner-simple.c index 29c1473f2e9f..d2169bb3111a 100644 --- a/drivers/media/tuners/tuner-simple.c +++ b/drivers/media/tuners/tuner-simple.c @@ -1130,7 +1130,7 @@ struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe, priv->nr, dtv_input[priv->nr]); } - strlcpy(fe->ops.tuner_ops.info.name, priv->tun->name, + strscpy(fe->ops.tuner_ops.info.name, priv->tun->name, sizeof(fe->ops.tuner_ops.info.name)); return fe; diff --git a/drivers/media/usb/airspy/airspy.c b/drivers/media/usb/airspy/airspy.c index e70c9e2f3798..41fa0f93143d 100644 --- a/drivers/media/usb/airspy/airspy.c +++ b/drivers/media/usb/airspy/airspy.c @@ -619,8 +619,8 @@ static int airspy_querycap(struct file *file, void *fh, { struct airspy *s = video_drvdata(file); - strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver)); - strlcpy(cap->card, s->vdev.name, sizeof(cap->card)); + strscpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver)); + strscpy(cap->card, s->vdev.name, sizeof(cap->card)); usb_make_path(s->udev, cap->bus_info, sizeof(cap->bus_info)); cap->device_caps = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_STREAMING | V4L2_CAP_READWRITE | V4L2_CAP_TUNER; @@ -635,7 +635,7 @@ static int airspy_enum_fmt_sdr_cap(struct file *file, void *priv, if (f->index >= NUM_FORMATS) return -EINVAL; - strlcpy(f->description, formats[f->index].name, sizeof(f->description)); + strscpy(f->description, formats[f->index].name, sizeof(f->description)); f->pixelformat = formats[f->index].pixelformat; return 0; @@ -720,14 +720,14 @@ static int airspy_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) int ret; if (v->index == 0) { - strlcpy(v->name, "AirSpy ADC", sizeof(v->name)); + strscpy(v->name, "AirSpy ADC", sizeof(v->name)); v->type = V4L2_TUNER_ADC; v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS; v->rangelow = bands[0].rangelow; v->rangehigh = bands[0].rangehigh; ret = 0; } else if (v->index == 1) { - strlcpy(v->name, "AirSpy RF", sizeof(v->name)); + strscpy(v->name, "AirSpy RF", sizeof(v->name)); v->type = V4L2_TUNER_RF; v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS; v->rangelow = bands_rf[0].rangelow; diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c index cd363a2100d4..1fdb1601dc65 100644 --- a/drivers/media/usb/au0828/au0828-core.c +++ b/drivers/media/usb/au0828/au0828-core.c @@ -266,11 +266,13 @@ static void au0828_media_graph_notify(struct media_entity *new, create_link: if (decoder && mixer) { - ret = media_create_pad_link(decoder, - DEMOD_PAD_AUDIO_OUT, - mixer, 0, - MEDIA_LNK_FL_ENABLED); - if (ret) + ret = media_get_pad_index(decoder, false, + PAD_SIGNAL_AUDIO); + if (ret >= 0) + ret = media_create_pad_link(decoder, ret, + mixer, 0, + MEDIA_LNK_FL_ENABLED); + if (ret < 0) dev_err(&dev->usbdev->dev, "Mixer Pad Link Create Error: %d\n", ret); } @@ -626,17 +628,16 @@ static int au0828_usb_probe(struct usb_interface *interface, /* Analog TV */ retval = au0828_analog_register(dev, interface); if (retval) { - pr_err("%s() au0282_dev_register failed to register on V4L2\n", + pr_err("%s() au0828_analog_register failed to register on V4L2\n", __func__); mutex_unlock(&dev->lock); - kfree(dev); goto done; } /* Digital TV */ retval = au0828_dvb_register(dev); if (retval) - pr_err("%s() au0282_dev_register failed\n", + pr_err("%s() au0828_dvb_register failed\n", __func__); /* Remote controller */ diff --git a/drivers/media/usb/au0828/au0828-i2c.c b/drivers/media/usb/au0828/au0828-i2c.c index 1b8ec5d9e7ab..92df5b5463af 100644 --- a/drivers/media/usb/au0828/au0828-i2c.c +++ b/drivers/media/usb/au0828/au0828-i2c.c @@ -378,7 +378,7 @@ int au0828_i2c_register(struct au0828_dev *dev) dev->i2c_adap.dev.parent = &dev->usbdev->dev; - strlcpy(dev->i2c_adap.name, KBUILD_MODNAME, + strscpy(dev->i2c_adap.name, KBUILD_MODNAME, sizeof(dev->i2c_adap.name)); dev->i2c_adap.algo = &dev->i2c_algo; diff --git a/drivers/media/usb/au0828/au0828-input.c b/drivers/media/usb/au0828/au0828-input.c index 832ed9f25784..4befa920246c 100644 --- a/drivers/media/usb/au0828/au0828-input.c +++ b/drivers/media/usb/au0828/au0828-input.c @@ -113,7 +113,7 @@ static int au8522_rc_andor(struct au0828_rc *ir, u16 reg, u8 mask, u8 value) static int au0828_get_key_au8522(struct au0828_rc *ir) { unsigned char buf[40]; - DEFINE_IR_RAW_EVENT(rawir); + struct ir_raw_event rawir = {}; int i, j, rc; int prv_bit, bit, width; bool first = true; @@ -167,7 +167,6 @@ static int au0828_get_key_au8522(struct au0828_rc *ir) if (first) { first = false; - init_ir_raw_event(&rawir); rawir.pulse = true; if (width > NEC_START_SPACE - 2 && width < NEC_START_SPACE + 2) { @@ -186,7 +185,6 @@ static int au0828_get_key_au8522(struct au0828_rc *ir) ir_raw_event_store(ir->rc, &rawir); } - init_ir_raw_event(&rawir); rawir.pulse = prv_bit ? false : true; rawir.duration = AU8522_UNIT * width; dprintk(16, "Storing %s with duration %d", @@ -199,7 +197,6 @@ static int au0828_get_key_au8522(struct au0828_rc *ir) } } - init_ir_raw_event(&rawir); rawir.pulse = prv_bit ? false : true; rawir.duration = AU8522_UNIT * width; dprintk(16, "Storing end %s with duration %d", diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c index 62b45062b1e6..efbf210147c7 100644 --- a/drivers/media/usb/au0828/au0828-video.c +++ b/drivers/media/usb/au0828/au0828-video.c @@ -1191,8 +1191,8 @@ static int vidioc_querycap(struct file *file, void *priv, dprintk(1, "%s called std_set %d dev_state %ld\n", __func__, dev->std_set_in_tuner_core, dev->dev_state); - strlcpy(cap->driver, "au0828", sizeof(cap->driver)); - strlcpy(cap->card, dev->board.name, sizeof(cap->card)); + strscpy(cap->driver, "au0828", sizeof(cap->driver)); + strscpy(cap->card, dev->board.name, sizeof(cap->card)); usb_make_path(dev->usbdev, cap->bus_info, sizeof(cap->bus_info)); /* set the device capabilities */ @@ -1218,7 +1218,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, dprintk(1, "%s called\n", __func__); f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - strcpy(f->description, "Packed YUV2"); + strscpy(f->description, "Packed YUV2", sizeof(f->description)); f->flags = 0; f->pixelformat = V4L2_PIX_FMT_UYVY; @@ -1349,7 +1349,7 @@ static int vidioc_enum_input(struct file *file, void *priv, return -EINVAL; input->index = tmp; - strcpy(input->name, inames[AUVI_INPUT(tmp).type]); + strscpy(input->name, inames[AUVI_INPUT(tmp).type], sizeof(input->name)); if ((AUVI_INPUT(tmp).type == AU0828_VMUX_TELEVISION) || (AUVI_INPUT(tmp).type == AU0828_VMUX_CABLE)) { input->type |= V4L2_INPUT_TYPE_TUNER; @@ -1465,9 +1465,9 @@ static int vidioc_enumaudio(struct file *file, void *priv, struct v4l2_audio *a) dprintk(1, "%s called\n", __func__); if (a->index == 0) - strcpy(a->name, "Television"); + strscpy(a->name, "Television", sizeof(a->name)); else - strcpy(a->name, "Line in"); + strscpy(a->name, "Line in", sizeof(a->name)); a->capability = V4L2_AUDCAP_STEREO; return 0; @@ -1482,9 +1482,9 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) a->index = dev->ctrl_ainput; if (a->index == 0) - strcpy(a->name, "Television"); + strscpy(a->name, "Television", sizeof(a->name)); else - strcpy(a->name, "Line in"); + strscpy(a->name, "Line in", sizeof(a->name)); a->capability = V4L2_AUDCAP_STEREO; return 0; @@ -1518,7 +1518,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) dprintk(1, "%s called std_set %d dev_state %ld\n", __func__, dev->std_set_in_tuner_core, dev->dev_state); - strcpy(t->name, "Auvitek tuner"); + strscpy(t->name, "Auvitek tuner", sizeof(t->name)); au0828_init_tuner(dev); i2c_gate_ctrl(dev, 1); @@ -1978,7 +1978,7 @@ int au0828_analog_register(struct au0828_dev *dev, dev->vdev.lock = &dev->lock; dev->vdev.queue = &dev->vb_vidq; dev->vdev.queue->lock = &dev->vb_queue_lock; - strcpy(dev->vdev.name, "au0828a video"); + strscpy(dev->vdev.name, "au0828a video", sizeof(dev->vdev.name)); /* Setup the VBI device */ dev->vbi_dev = au0828_video_template; @@ -1986,7 +1986,7 @@ int au0828_analog_register(struct au0828_dev *dev, dev->vbi_dev.lock = &dev->lock; dev->vbi_dev.queue = &dev->vb_vbiq; dev->vbi_dev.queue->lock = &dev->vb_vbi_queue_lock; - strcpy(dev->vbi_dev.name, "au0828a vbi"); + strscpy(dev->vbi_dev.name, "au0828a vbi", sizeof(dev->vbi_dev.name)); /* Init entities at the Media Controller */ au0828_analog_create_entities(dev); diff --git a/drivers/media/usb/cpia2/cpia2_v4l.c b/drivers/media/usb/cpia2/cpia2_v4l.c index 99f106b13280..aa7f3c307b22 100644 --- a/drivers/media/usb/cpia2/cpia2_v4l.c +++ b/drivers/media/usb/cpia2/cpia2_v4l.c @@ -219,12 +219,12 @@ static int cpia2_querycap(struct file *file, void *fh, struct v4l2_capability *v { struct camera_data *cam = video_drvdata(file); - strcpy(vc->driver, "cpia2"); + strscpy(vc->driver, "cpia2", sizeof(vc->driver)); if (cam->params.pnp_id.product == 0x151) - strcpy(vc->card, "QX5 Microscope"); + strscpy(vc->card, "QX5 Microscope", sizeof(vc->card)); else - strcpy(vc->card, "CPiA2 Camera"); + strscpy(vc->card, "CPiA2 Camera", sizeof(vc->card)); switch (cam->params.pnp_id.device_type) { case DEVICE_STV_672: strcat(vc->card, " (672/"); @@ -281,7 +281,7 @@ static int cpia2_enum_input(struct file *file, void *fh, struct v4l2_input *i) { if (i->index) return -EINVAL; - strcpy(i->name, "Camera"); + strscpy(i->name, "Camera", sizeof(i->name)); i->type = V4L2_INPUT_TYPE_CAMERA; return 0; } @@ -319,11 +319,11 @@ static int cpia2_enum_fmt_vid_cap(struct file *file, void *fh, f->flags = V4L2_FMT_FLAG_COMPRESSED; switch(index) { case 0: - strcpy(f->description, "MJPEG"); + strscpy(f->description, "MJPEG", sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_MJPEG; break; case 1: - strcpy(f->description, "JPEG"); + strscpy(f->description, "JPEG", sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_JPEG; break; default: diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx231xx/cx231xx-417.c index 2f3b0564d676..f700ec35b7f3 100644 --- a/drivers/media/usb/cx231xx/cx231xx-417.c +++ b/drivers/media/usb/cx231xx/cx231xx-417.c @@ -1583,7 +1583,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, if (f->index != 0) return -EINVAL; - strlcpy(f->description, "MPEG", sizeof(f->description)); + strscpy(f->description, "MPEG", sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_MPEG; return 0; diff --git a/drivers/media/usb/cx231xx/cx231xx-audio.c b/drivers/media/usb/cx231xx/cx231xx-audio.c index 32ee7b3f21c9..77f2c65eb79a 100644 --- a/drivers/media/usb/cx231xx/cx231xx-audio.c +++ b/drivers/media/usb/cx231xx/cx231xx-audio.c @@ -679,10 +679,10 @@ static int cx231xx_audio_init(struct cx231xx *dev) &snd_cx231xx_pcm_capture); pcm->info_flags = 0; pcm->private_data = dev; - strcpy(pcm->name, "Conexant cx231xx Capture"); - strcpy(card->driver, "Cx231xx-Audio"); - strcpy(card->shortname, "Cx231xx Audio"); - strcpy(card->longname, "Conexant cx231xx Audio"); + strscpy(pcm->name, "Conexant cx231xx Capture", sizeof(pcm->name)); + strscpy(card->driver, "Cx231xx-Audio", sizeof(card->driver)); + strscpy(card->shortname, "Cx231xx Audio", sizeof(card->shortname)); + strscpy(card->longname, "Conexant cx231xx Audio", sizeof(card->longname)); INIT_WORK(&dev->wq_trigger, audio_trigger); diff --git a/drivers/media/usb/cx231xx/cx231xx-input.c b/drivers/media/usb/cx231xx/cx231xx-input.c index 3e9b73a6b7c9..9f88c640ec2b 100644 --- a/drivers/media/usb/cx231xx/cx231xx-input.c +++ b/drivers/media/usb/cx231xx/cx231xx-input.c @@ -67,7 +67,7 @@ int cx231xx_ir_init(struct cx231xx *dev) dev->init_data.name = cx231xx_boards[dev->model].name; - strlcpy(info.type, "ir_video", I2C_NAME_SIZE); + strscpy(info.type, "ir_video", I2C_NAME_SIZE); info.platform_data = &dev->init_data; /* diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c index f7fcd733a2ca..f2f034c5cd62 100644 --- a/drivers/media/usb/cx231xx/cx231xx-video.c +++ b/drivers/media/usb/cx231xx/cx231xx-video.c @@ -1169,7 +1169,7 @@ int cx231xx_enum_input(struct file *file, void *priv, i->index = n; i->type = V4L2_INPUT_TYPE_CAMERA; - strcpy(i->name, iname[INPUT(n)->type]); + strscpy(i->name, iname[INPUT(n)->type], sizeof(i->name)); if ((CX231XX_VMUX_TELEVISION == INPUT(n)->type) || (CX231XX_VMUX_CABLE == INPUT(n)->type)) @@ -1244,7 +1244,7 @@ int cx231xx_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) if (0 != t->index) return -EINVAL; - strcpy(t->name, "Tuner"); + strscpy(t->name, "Tuner", sizeof(t->name)); t->type = V4L2_TUNER_ANALOG_TV; t->capability = V4L2_TUNER_CAP_NORM; @@ -1354,22 +1354,22 @@ int cx231xx_g_chip_info(struct file *file, void *fh, case 0: /* Cx231xx - internal registers */ return 0; case 1: /* AFE - read byte */ - strlcpy(chip->name, "AFE (byte)", sizeof(chip->name)); + strscpy(chip->name, "AFE (byte)", sizeof(chip->name)); return 0; case 2: /* Video Block - read byte */ - strlcpy(chip->name, "Video (byte)", sizeof(chip->name)); + strscpy(chip->name, "Video (byte)", sizeof(chip->name)); return 0; case 3: /* I2S block - read byte */ - strlcpy(chip->name, "I2S (byte)", sizeof(chip->name)); + strscpy(chip->name, "I2S (byte)", sizeof(chip->name)); return 0; case 4: /* AFE - read dword */ - strlcpy(chip->name, "AFE (dword)", sizeof(chip->name)); + strscpy(chip->name, "AFE (dword)", sizeof(chip->name)); return 0; case 5: /* Video Block - read dword */ - strlcpy(chip->name, "Video (dword)", sizeof(chip->name)); + strscpy(chip->name, "Video (dword)", sizeof(chip->name)); return 0; case 6: /* I2S Block - read dword */ - strlcpy(chip->name, "I2S (dword)", sizeof(chip->name)); + strscpy(chip->name, "I2S (dword)", sizeof(chip->name)); return 0; } return -EINVAL; @@ -1389,7 +1389,7 @@ int cx231xx_g_register(struct file *file, void *priv, ret = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, (u16)reg->reg, value, 4); reg->val = value[0] | value[1] << 8 | - value[2] << 16 | value[3] << 24; + value[2] << 16 | (u32)value[3] << 24; reg->size = 4; break; case 1: /* AFE - read byte */ @@ -1553,8 +1553,8 @@ int cx231xx_querycap(struct file *file, void *priv, struct cx231xx_fh *fh = priv; struct cx231xx *dev = fh->dev; - strlcpy(cap->driver, "cx231xx", sizeof(cap->driver)); - strlcpy(cap->card, cx231xx_boards[dev->model].name, sizeof(cap->card)); + strscpy(cap->driver, "cx231xx", sizeof(cap->driver)); + strscpy(cap->card, cx231xx_boards[dev->model].name, sizeof(cap->card)); usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); if (vdev->vfl_type == VFL_TYPE_RADIO) @@ -1583,7 +1583,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, if (unlikely(f->index >= ARRAY_SIZE(format))) return -EINVAL; - strlcpy(f->description, format[f->index].name, sizeof(f->description)); + strscpy(f->description, format[f->index].name, sizeof(f->description)); f->pixelformat = format[f->index].fourcc; return 0; @@ -1716,7 +1716,7 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) if (t->index) return -EINVAL; - strcpy(t->name, "Radio"); + strscpy(t->name, "Radio", sizeof(t->name)); call_all(dev, tuner, g_tuner, t); @@ -2242,7 +2242,8 @@ int cx231xx_register_analog_devices(struct cx231xx *dev) /* Initialize VBI template */ cx231xx_vbi_template = cx231xx_video_template; - strcpy(cx231xx_vbi_template.name, "cx231xx-vbi"); + strscpy(cx231xx_vbi_template.name, "cx231xx-vbi", + sizeof(cx231xx_vbi_template.name)); /* Allocate and fill vbi video_device struct */ cx231xx_vdev_init(dev, &dev->vbi_dev, &cx231xx_vbi_template, "vbi"); diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c index 1f6c1eefe389..80d3bd3a0f24 100644 --- a/drivers/media/usb/dvb-usb-v2/af9035.c +++ b/drivers/media/usb/dvb-usb-v2/af9035.c @@ -204,7 +204,7 @@ static int af9035_add_i2c_dev(struct dvb_usb_device *d, const char *type, .platform_data = platform_data, }; - strlcpy(board_info.type, type, I2C_NAME_SIZE); + strscpy(board_info.type, type, I2C_NAME_SIZE); /* find first free client */ for (num = 0; num < AF9035_I2C_CLIENT_MAX; num++) { diff --git a/drivers/media/usb/dvb-usb-v2/anysee.c b/drivers/media/usb/dvb-usb-v2/anysee.c index 20ee7eea2a91..0df7ad69e6c7 100644 --- a/drivers/media/usb/dvb-usb-v2/anysee.c +++ b/drivers/media/usb/dvb-usb-v2/anysee.c @@ -638,7 +638,7 @@ static int anysee_add_i2c_dev(struct dvb_usb_device *d, const char *type, .platform_data = platform_data, }; - strlcpy(board_info.type, type, I2C_NAME_SIZE); + strscpy(board_info.type, type, I2C_NAME_SIZE); /* find first free client */ for (num = 0; num < ANYSEE_I2C_CLIENT_MAX; num++) { diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c index 955318ab7f5e..3b8f7931b730 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c @@ -74,7 +74,7 @@ static int dvb_usbv2_i2c_init(struct dvb_usb_device *d) if (!d->props->i2c_algo) return 0; - strlcpy(d->i2c_adap.name, d->name, sizeof(d->i2c_adap.name)); + strscpy(d->i2c_adap.name, d->name, sizeof(d->i2c_adap.name)); d->i2c_adap.algo = d->props->i2c_algo; d->i2c_adap.dev.parent = &d->udev->dev; i2c_set_adapdata(&d->i2c_adap, d); diff --git a/drivers/media/usb/dvb-usb-v2/dvbsky.c b/drivers/media/usb/dvb-usb-v2/dvbsky.c index 1aa88d94e57f..e28bd8836751 100644 --- a/drivers/media/usb/dvb-usb-v2/dvbsky.c +++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c @@ -31,6 +31,7 @@ MODULE_PARM_DESC(disable_rc, "Disable inbuilt IR receiver."); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); struct dvbsky_state { + struct mutex stream_mutex; u8 ibuf[DVBSKY_BUF_LEN]; u8 obuf[DVBSKY_BUF_LEN]; u8 last_lock; @@ -67,17 +68,18 @@ static int dvbsky_usb_generic_rw(struct dvb_usb_device *d, static int dvbsky_stream_ctrl(struct dvb_usb_device *d, u8 onoff) { + struct dvbsky_state *state = d_to_priv(d); int ret; - static u8 obuf_pre[3] = { 0x37, 0, 0 }; - static u8 obuf_post[3] = { 0x36, 3, 0 }; + u8 obuf_pre[3] = { 0x37, 0, 0 }; + u8 obuf_post[3] = { 0x36, 3, 0 }; - mutex_lock(&d->usb_mutex); - ret = dvb_usbv2_generic_rw_locked(d, obuf_pre, 3, NULL, 0); + mutex_lock(&state->stream_mutex); + ret = dvbsky_usb_generic_rw(d, obuf_pre, 3, NULL, 0); if (!ret && onoff) { msleep(20); - ret = dvb_usbv2_generic_rw_locked(d, obuf_post, 3, NULL, 0); + ret = dvbsky_usb_generic_rw(d, obuf_post, 3, NULL, 0); } - mutex_unlock(&d->usb_mutex); + mutex_unlock(&state->stream_mutex); return ret; } @@ -606,6 +608,8 @@ static int dvbsky_init(struct dvb_usb_device *d) if (ret) return ret; */ + mutex_init(&state->stream_mutex); + state->last_lock = 0; return 0; diff --git a/drivers/media/usb/dvb-usb-v2/gl861.c b/drivers/media/usb/dvb-usb-v2/gl861.c index 3338b21d8b25..0559417c8af4 100644 --- a/drivers/media/usb/dvb-usb-v2/gl861.c +++ b/drivers/media/usb/dvb-usb-v2/gl861.c @@ -507,7 +507,7 @@ static int friio_frontend_attach(struct dvb_usb_adapter *adap) priv->i2c_client_demod = cl; priv->tuner_adap.algo = &friio_tuner_i2c_algo; priv->tuner_adap.dev.parent = &d->udev->dev; - strlcpy(priv->tuner_adap.name, d->name, sizeof(priv->tuner_adap.name)); + strscpy(priv->tuner_adap.name, d->name, sizeof(priv->tuner_adap.name)); strlcat(priv->tuner_adap.name, "-tuner", sizeof(priv->tuner_adap.name)); priv->demod_sub_i2c = &priv->tuner_adap; i2c_set_adapdata(&priv->tuner_adap, d); diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c index 0750a975bcb8..f109c04f05ae 100644 --- a/drivers/media/usb/dvb-usb-v2/lmedm04.c +++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c @@ -1004,7 +1004,7 @@ static int lme_name(struct dvb_usb_adapter *adap) " SHARP:BS2F7HZ0194", " RS2000"}; char *name = adap->fe[0]->ops.info.name; - strlcpy(name, desc, 128); + strscpy(name, desc, 128); strlcat(name, fe_name[st->tuner_config], 128); return 0; diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c index 4713ba65e1c2..85cdf593a9ad 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c @@ -892,11 +892,13 @@ static int mxl111sf_attach_tuner(struct dvb_usb_adapter *adap) #ifdef CONFIG_MEDIA_CONTROLLER_DVB state->tuner.function = MEDIA_ENT_F_TUNER; state->tuner.name = "mxl111sf tuner"; - state->tuner_pads[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK; - state->tuner_pads[TUNER_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; + state->tuner_pads[MXL111SF_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK; + state->tuner_pads[MXL111SF_PAD_RF_INPUT].sig_type = PAD_SIGNAL_ANALOG; + state->tuner_pads[MXL111SF_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; + state->tuner_pads[MXL111SF_PAD_OUTPUT].sig_type = PAD_SIGNAL_ANALOG; ret = media_entity_pads_init(&state->tuner, - TUNER_NUM_PADS, state->tuner_pads); + MXL111SF_NUM_PADS, state->tuner_pads); if (ret) return ret; diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.h b/drivers/media/usb/dvb-usb-v2/mxl111sf.h index 22253d4908eb..ed98654ba7fd 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.h @@ -52,6 +52,12 @@ struct mxl111sf_adap_state { int (*fe_sleep)(struct dvb_frontend *); }; +enum mxl111sf_pads { + MXL111SF_PAD_RF_INPUT, + MXL111SF_PAD_OUTPUT, + MXL111SF_NUM_PADS +}; + struct mxl111sf_state { struct dvb_usb_device *d; @@ -94,7 +100,7 @@ struct mxl111sf_state { struct mutex msg_lock; #ifdef CONFIG_MEDIA_CONTROLLER_DVB struct media_entity tuner; - struct media_pad tuner_pads[2]; + struct media_pad tuner_pads[MXL111SF_NUM_PADS]; #endif }; diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index a970224a94bd..8a83b10e50e0 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -687,7 +687,7 @@ static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap) /* attach demodulator */ memset(&board_info, 0, sizeof(board_info)); - strlcpy(board_info.type, "rtl2830", I2C_NAME_SIZE); + strscpy(board_info.type, "rtl2830", I2C_NAME_SIZE); board_info.addr = 0x10; board_info.platform_data = pdata; request_module("%s", board_info.type); @@ -908,7 +908,7 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) /* attach demodulator */ memset(&board_info, 0, sizeof(board_info)); - strlcpy(board_info.type, "rtl2832", I2C_NAME_SIZE); + strscpy(board_info.type, "rtl2832", I2C_NAME_SIZE); board_info.addr = 0x10; board_info.platform_data = pdata; request_module("%s", board_info.type); @@ -947,7 +947,7 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) mn88472_config.fe = &adap->fe[1]; mn88472_config.i2c_wr_max = 22, - strlcpy(info.type, "mn88472", I2C_NAME_SIZE); + strscpy(info.type, "mn88472", I2C_NAME_SIZE); mn88472_config.xtal = 20500000; mn88472_config.ts_mode = SERIAL_TS_MODE; mn88472_config.ts_clock = VARIABLE_TS_CLOCK; @@ -972,7 +972,7 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) mn88473_config.fe = &adap->fe[1]; mn88473_config.i2c_wr_max = 22, - strlcpy(info.type, "mn88473", I2C_NAME_SIZE); + strscpy(info.type, "mn88473", I2C_NAME_SIZE); info.addr = 0x18; info.platform_data = &mn88473_config; request_module(info.type); @@ -998,7 +998,7 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) si2168_config.ts_mode = SI2168_TS_SERIAL; si2168_config.ts_clock_inv = false; si2168_config.ts_clock_gapped = true; - strlcpy(info.type, "si2168", I2C_NAME_SIZE); + strscpy(info.type, "si2168", I2C_NAME_SIZE); info.addr = 0x64; info.platform_data = &si2168_config; request_module(info.type); @@ -1189,7 +1189,7 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) .clock = 28800000, }; - strlcpy(info.type, "e4000", I2C_NAME_SIZE); + strscpy(info.type, "e4000", I2C_NAME_SIZE); info.addr = 0x64; info.platform_data = &e4000_config; @@ -1213,7 +1213,7 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) }; struct i2c_board_info board_info = {}; - strlcpy(board_info.type, "fc2580", I2C_NAME_SIZE); + strscpy(board_info.type, "fc2580", I2C_NAME_SIZE); board_info.addr = 0x56; board_info.platform_data = &fc2580_pdata; request_module("fc2580"); @@ -1244,7 +1244,7 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) if (ret) goto err; - strlcpy(board_info.type, "tua9001", I2C_NAME_SIZE); + strscpy(board_info.type, "tua9001", I2C_NAME_SIZE); board_info.addr = 0x60; board_info.platform_data = &tua9001_pdata; request_module("tua9001"); @@ -1289,7 +1289,7 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap) .inversion = false, }; - strlcpy(info.type, "si2157", I2C_NAME_SIZE); + strscpy(info.type, "si2157", I2C_NAME_SIZE); info.addr = 0x60; info.platform_data = &si2157_config; request_module(info.type); @@ -1685,7 +1685,7 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d) { int ret, i, len; struct rtl28xxu_dev *dev = d->priv; - struct ir_raw_event ev; + struct ir_raw_event ev = {}; u8 buf[128]; static const struct rtl28xxu_reg_val_mask refresh_tab[] = { {IR_RX_IF, 0x03, 0xff}, @@ -1751,8 +1751,6 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d) } /* pass data to Kernel IR decoder */ - init_ir_raw_event(&ev); - for (i = 0; i < len; i++) { ev.pulse = buf[i] >> 7; ev.duration = 50800 * (buf[i] & 0x7f); diff --git a/drivers/media/usb/dvb-usb-v2/zd1301.c b/drivers/media/usb/dvb-usb-v2/zd1301.c index d1eb4b7bc051..7a41d744ff58 100644 --- a/drivers/media/usb/dvb-usb-v2/zd1301.c +++ b/drivers/media/usb/dvb-usb-v2/zd1301.c @@ -177,7 +177,7 @@ static int zd1301_frontend_attach(struct dvb_usb_adapter *adap) dev->mt2060_pdata.i2c_write_max = 9; dev->mt2060_pdata.dvb_frontend = frontend; memset(&board_info, 0, sizeof(board_info)); - strlcpy(board_info.type, "mt2060", I2C_NAME_SIZE); + strscpy(board_info.type, "mt2060", I2C_NAME_SIZE); board_info.addr = 0x60; board_info.platform_data = &dev->mt2060_pdata; request_module("%s", "mt2060"); diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c index 5b51ed7d6243..a51a45c60233 100644 --- a/drivers/media/usb/dvb-usb/cxusb.c +++ b/drivers/media/usb/dvb-usb/cxusb.c @@ -1196,7 +1196,7 @@ static int cxusb_mygica_t230_frontend_attach(struct dvb_usb_adapter *adap) si2168_config.ts_mode = SI2168_TS_PARALLEL; si2168_config.ts_clock_inv = 1; memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2168", I2C_NAME_SIZE); + strscpy(info.type, "si2168", I2C_NAME_SIZE); info.addr = 0x64; info.platform_data = &si2168_config; request_module(info.type); @@ -1216,7 +1216,7 @@ static int cxusb_mygica_t230_frontend_attach(struct dvb_usb_adapter *adap) si2157_config.fe = adap->fe_adap[0].fe; si2157_config.if_port = 1; memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "si2157", I2C_NAME_SIZE); + strscpy(info.type, "si2157", I2C_NAME_SIZE); info.addr = 0x60; info.platform_data = &si2157_config; request_module(info.type); diff --git a/drivers/media/usb/dvb-usb/dib0700_devices.c b/drivers/media/usb/dvb-usb/dib0700_devices.c index 091389fdf89e..7551dce96f64 100644 --- a/drivers/media/usb/dvb-usb/dib0700_devices.c +++ b/drivers/media/usb/dvb-usb/dib0700_devices.c @@ -3763,7 +3763,7 @@ static int xbox_one_attach(struct dvb_usb_adapter *adap) mn88472_config.ts_mode = PARALLEL_TS_MODE; mn88472_config.ts_clock = FIXED_TS_CLOCK; memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "mn88472", I2C_NAME_SIZE); + strscpy(info.type, "mn88472", I2C_NAME_SIZE); info.addr = 0x18; info.platform_data = &mn88472_config; request_module(info.type); @@ -3790,7 +3790,7 @@ static int xbox_one_attach(struct dvb_usb_adapter *adap) tda18250_config.fe = adap->fe_adap[0].fe; memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "tda18250", I2C_NAME_SIZE); + strscpy(info.type, "tda18250", I2C_NAME_SIZE); info.addr = 0x60; info.platform_data = &tda18250_config; diff --git a/drivers/media/usb/dvb-usb/dvb-usb-i2c.c b/drivers/media/usb/dvb-usb/dvb-usb-i2c.c index ca0b734e009b..2e07106f4680 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb-i2c.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-i2c.c @@ -20,7 +20,7 @@ int dvb_usb_i2c_init(struct dvb_usb_device *d) return -EINVAL; } - strlcpy(d->i2c_adap.name, d->desc->name, sizeof(d->i2c_adap.name)); + strscpy(d->i2c_adap.name, d->desc->name, sizeof(d->i2c_adap.name)); d->i2c_adap.algo = d->props.i2c_algo; d->i2c_adap.algo_data = NULL; d->i2c_adap.dev.parent = &d->udev->dev; diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c index 9ce8b4d79d1f..eefe2867815c 100644 --- a/drivers/media/usb/dvb-usb/dw2102.c +++ b/drivers/media/usb/dvb-usb/dw2102.c @@ -1589,7 +1589,7 @@ static int tt_s2_4600_frontend_attach(struct dvb_usb_adapter *adap) m88ds3103_pdata.lnb_hv_pol = 1; m88ds3103_pdata.lnb_en_pol = 0; memset(&board_info, 0, sizeof(board_info)); - strlcpy(board_info.type, "m88ds3103", I2C_NAME_SIZE); + strscpy(board_info.type, "m88ds3103", I2C_NAME_SIZE); board_info.addr = 0x68; board_info.platform_data = &m88ds3103_pdata; request_module("m88ds3103"); @@ -1608,7 +1608,7 @@ static int tt_s2_4600_frontend_attach(struct dvb_usb_adapter *adap) /* attach tuner */ ts2020_config.fe = adap->fe_adap[0].fe; memset(&board_info, 0, sizeof(board_info)); - strlcpy(board_info.type, "ts2022", I2C_NAME_SIZE); + strscpy(board_info.type, "ts2022", I2C_NAME_SIZE); board_info.addr = 0x60; board_info.platform_data = &ts2020_config; request_module("ts2020"); diff --git a/drivers/media/usb/dvb-usb/technisat-usb2.c b/drivers/media/usb/dvb-usb/technisat-usb2.c index 18d0f8f5283f..c659e18b358b 100644 --- a/drivers/media/usb/dvb-usb/technisat-usb2.c +++ b/drivers/media/usb/dvb-usb/technisat-usb2.c @@ -566,8 +566,9 @@ static int technisat_usb2_frontend_attach(struct dvb_usb_adapter *a) a->fe_adap[0].fe->ops.set_voltage = technisat_usb2_set_voltage; /* if everything was successful assign a nice name to the frontend */ - strlcpy(a->fe_adap[0].fe->ops.info.name, a->dev->desc->name, - sizeof(a->fe_adap[0].fe->ops.info.name)); + strscpy(a->fe_adap[0].fe->ops.info.name, + a->dev->desc->name, + sizeof(a->fe_adap[0].fe->ops.info.name)); } else { dvb_frontend_detach(a->fe_adap[0].fe); a->fe_adap[0].fe = NULL; diff --git a/drivers/media/usb/em28xx/em28xx-audio.c b/drivers/media/usb/em28xx/em28xx-audio.c index 67481fc82445..49c9b70b632b 100644 --- a/drivers/media/usb/em28xx/em28xx-audio.c +++ b/drivers/media/usb/em28xx/em28xx-audio.c @@ -843,11 +843,11 @@ static int em28xx_audio_urb_init(struct em28xx *dev) dev->adev.transfer_buffer = kcalloc(num_urb, sizeof(*dev->adev.transfer_buffer), - GFP_ATOMIC); + GFP_KERNEL); if (!dev->adev.transfer_buffer) return -ENOMEM; - dev->adev.urb = kcalloc(num_urb, sizeof(*dev->adev.urb), GFP_ATOMIC); + dev->adev.urb = kcalloc(num_urb, sizeof(*dev->adev.urb), GFP_KERNEL); if (!dev->adev.urb) { kfree(dev->adev.transfer_buffer); return -ENOMEM; @@ -860,14 +860,14 @@ static int em28xx_audio_urb_init(struct em28xx *dev) int j, k; void *buf; - urb = usb_alloc_urb(npackets, GFP_ATOMIC); + urb = usb_alloc_urb(npackets, GFP_KERNEL); if (!urb) { em28xx_audio_free_urb(dev); return -ENOMEM; } dev->adev.urb[i] = urb; - buf = usb_alloc_coherent(udev, npackets * ep_size, GFP_ATOMIC, + buf = usb_alloc_coherent(udev, npackets * ep_size, GFP_KERNEL, &urb->transfer_dma); if (!buf) { dev_err(&dev->intf->dev, @@ -939,11 +939,11 @@ static int em28xx_audio_init(struct em28xx *dev) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_em28xx_pcm_capture); pcm->info_flags = 0; pcm->private_data = dev; - strcpy(pcm->name, "Empia 28xx Capture"); + strscpy(pcm->name, "Empia 28xx Capture", sizeof(pcm->name)); - strcpy(card->driver, "Em28xx-Audio"); - strcpy(card->shortname, "Em28xx Audio"); - strcpy(card->longname, "Empia Em28xx Audio"); + strscpy(card->driver, "Em28xx-Audio", sizeof(card->driver)); + strscpy(card->shortname, "Em28xx Audio", sizeof(card->shortname)); + strscpy(card->longname, "Empia Em28xx Audio", sizeof(card->longname)); INIT_WORK(&adev->wq_trigger, audio_trigger); diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index 71c829f31d3b..87b887b7604e 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -2141,13 +2141,13 @@ const struct em28xx_board em28xx_boards[] = { .input = { { .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, - .amux = EM28XX_AUDIO_SRC_LINE, + .amux = EM28XX_AMUX_LINE_IN, .gpio = terratec_av350_unmute_gpio, }, { .type = EM28XX_VMUX_SVIDEO, .vmux = TVP5150_SVIDEO, - .amux = EM28XX_AUDIO_SRC_LINE, + .amux = EM28XX_AMUX_LINE_IN, .gpio = terratec_av350_unmute_gpio, } }, }, @@ -3039,6 +3039,9 @@ static int em28xx_hint_board(struct em28xx *dev) static void em28xx_card_setup(struct em28xx *dev) { + int i, j, idx; + bool duplicate_entry; + /* * If the device can be a webcam, seek for a sensor. * If sensor is not found, then it isn't a webcam. @@ -3195,6 +3198,32 @@ static void em28xx_card_setup(struct em28xx *dev) /* Allow override tuner type by a module parameter */ if (tuner >= 0) dev->tuner_type = tuner; + + /* + * Dynamically generate a list of valid audio inputs for this + * specific board, mapping them via enum em28xx_amux. + */ + + idx = 0; + for (i = 0; i < MAX_EM28XX_INPUT; i++) { + if (!INPUT(i)->type) + continue; + + /* Skip already mapped audio inputs */ + duplicate_entry = false; + for (j = 0; j < idx; j++) { + if (INPUT(i)->amux == dev->amux_map[j]) { + duplicate_entry = true; + break; + } + } + if (duplicate_entry) + continue; + + dev->amux_map[idx++] = INPUT(i)->amux; + } + for (; idx < MAX_EM28XX_INPUT; idx++) + dev->amux_map[idx] = EM28XX_AMUX_UNUSED; } void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) diff --git a/drivers/media/usb/em28xx/em28xx-i2c.c b/drivers/media/usb/em28xx/em28xx-i2c.c index e19d6342e0d0..02c13d71e6c1 100644 --- a/drivers/media/usb/em28xx/em28xx-i2c.c +++ b/drivers/media/usb/em28xx/em28xx-i2c.c @@ -985,7 +985,8 @@ int em28xx_i2c_register(struct em28xx *dev, unsigned int bus, dev->i2c_adap[bus] = em28xx_adap_template; dev->i2c_adap[bus].dev.parent = &dev->intf->dev; - strcpy(dev->i2c_adap[bus].name, dev_name(&dev->intf->dev)); + strscpy(dev->i2c_adap[bus].name, dev_name(&dev->intf->dev), + sizeof(dev->i2c_adap[bus].name)); dev->i2c_bus[bus].bus = bus; dev->i2c_bus[bus].algo_type = algo_type; diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 68571bf36d28..f43717ea831d 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -1093,6 +1093,8 @@ int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count) em28xx_videodbg("%s\n", __func__); + dev->v4l2->field_count = 0; + /* * Make sure streaming is not already in progress for this type * of filehandle (e.g. video, vbi) @@ -1471,9 +1473,9 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, fmt = format_by_fourcc(f->fmt.pix.pixelformat); if (!fmt) { - em28xx_videodbg("Fourcc format (%08x) invalid.\n", - f->fmt.pix.pixelformat); - return -EINVAL; + fmt = &format[0]; + em28xx_videodbg("Fourcc format (%08x) invalid. Using default (%08x).\n", + f->fmt.pix.pixelformat, fmt->fourcc); } if (dev->board.is_em2800) { @@ -1666,6 +1668,7 @@ static int vidioc_enum_input(struct file *file, void *priv, { struct em28xx *dev = video_drvdata(file); unsigned int n; + int j; n = i->index; if (n >= MAX_EM28XX_INPUT) @@ -1675,7 +1678,7 @@ static int vidioc_enum_input(struct file *file, void *priv, i->type = V4L2_INPUT_TYPE_CAMERA; - strcpy(i->name, iname[INPUT(n)->type]); + strscpy(i->name, iname[INPUT(n)->type], sizeof(i->name)); if (INPUT(n)->type == EM28XX_VMUX_TELEVISION) i->type = V4L2_INPUT_TYPE_TUNER; @@ -1685,6 +1688,12 @@ static int vidioc_enum_input(struct file *file, void *priv, if (dev->is_webcam) i->capabilities = 0; + /* Dynamically generates an audioset bitmask */ + i->audioset = 0; + for (j = 0; j < MAX_EM28XX_INPUT; j++) + if (dev->amux_map[j] != EM28XX_AMUX_UNUSED) + i->audioset |= 1 << j; + return 0; } @@ -1710,61 +1719,121 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) return 0; } -static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) +static int em28xx_fill_audio_input(struct em28xx *dev, + const char *s, + struct v4l2_audio *a, + unsigned int index) { - struct em28xx *dev = video_drvdata(file); + unsigned int idx = dev->amux_map[index]; + + /* + * With msp3400, almost all mappings use the default (amux = 0). + * The only one may use a different value is WinTV USB2, where it + * can also be SCART1 input. + * As it is very doubtful that we would see new boards with msp3400, + * let's just reuse the existing switch. + */ + if (dev->has_msp34xx && idx != EM28XX_AMUX_UNUSED) + idx = EM28XX_AMUX_LINE_IN; - switch (a->index) { + switch (idx) { case EM28XX_AMUX_VIDEO: - strcpy(a->name, "Television"); + strscpy(a->name, "Television", sizeof(a->name)); break; case EM28XX_AMUX_LINE_IN: - strcpy(a->name, "Line In"); + strscpy(a->name, "Line In", sizeof(a->name)); break; case EM28XX_AMUX_VIDEO2: - strcpy(a->name, "Television alt"); + strscpy(a->name, "Television alt", sizeof(a->name)); break; case EM28XX_AMUX_PHONE: - strcpy(a->name, "Phone"); + strscpy(a->name, "Phone", sizeof(a->name)); break; case EM28XX_AMUX_MIC: - strcpy(a->name, "Mic"); + strscpy(a->name, "Mic", sizeof(a->name)); break; case EM28XX_AMUX_CD: - strcpy(a->name, "CD"); + strscpy(a->name, "CD", sizeof(a->name)); break; case EM28XX_AMUX_AUX: - strcpy(a->name, "Aux"); + strscpy(a->name, "Aux", sizeof(a->name)); break; case EM28XX_AMUX_PCM_OUT: - strcpy(a->name, "PCM"); + strscpy(a->name, "PCM", sizeof(a->name)); break; + case EM28XX_AMUX_UNUSED: default: return -EINVAL; } - - a->index = dev->ctl_ainput; + a->index = index; a->capability = V4L2_AUDCAP_STEREO; + em28xx_videodbg("%s: audio input index %d is '%s'\n", + s, a->index, a->name); + return 0; } +static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a) +{ + struct em28xx *dev = video_drvdata(file); + + if (a->index >= MAX_EM28XX_INPUT) + return -EINVAL; + + return em28xx_fill_audio_input(dev, __func__, a, a->index); +} + +static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) +{ + struct em28xx *dev = video_drvdata(file); + int i; + + for (i = 0; i < MAX_EM28XX_INPUT; i++) + if (dev->ctl_ainput == dev->amux_map[i]) + return em28xx_fill_audio_input(dev, __func__, a, i); + + /* Should never happen! */ + return -EINVAL; +} + static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *a) { struct em28xx *dev = video_drvdata(file); + int idx, i; if (a->index >= MAX_EM28XX_INPUT) return -EINVAL; - if (!INPUT(a->index)->type) + + idx = dev->amux_map[a->index]; + + if (idx == EM28XX_AMUX_UNUSED) return -EINVAL; - dev->ctl_ainput = INPUT(a->index)->amux; - dev->ctl_aoutput = INPUT(a->index)->aout; + dev->ctl_ainput = idx; + + /* + * FIXME: This is wrong, as different inputs at em28xx_cards + * may have different audio outputs. So, the right thing + * to do is to implement VIDIOC_G_AUDOUT/VIDIOC_S_AUDOUT. + * With the current board definitions, this would work fine, + * as, currently, all boards fit. + */ + for (i = 0; i < MAX_EM28XX_INPUT; i++) + if (idx == dev->amux_map[i]) + break; + if (i == MAX_EM28XX_INPUT) + return -EINVAL; + + dev->ctl_aoutput = INPUT(i)->aout; if (!dev->ctl_aoutput) dev->ctl_aoutput = EM28XX_AOUT_MASTER; + em28xx_videodbg("%s: set audio input to %d\n", __func__, + dev->ctl_ainput); + return 0; } @@ -1776,7 +1845,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, if (t->index != 0) return -EINVAL; - strcpy(t->name, "Tuner"); + strscpy(t->name, "Tuner", sizeof(t->name)); v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, g_tuner, t); return 0; @@ -1833,9 +1902,9 @@ static int vidioc_g_chip_info(struct file *file, void *priv, if (chip->match.addr > 1) return -EINVAL; if (chip->match.addr == 1) - strlcpy(chip->name, "ac97", sizeof(chip->name)); + strscpy(chip->name, "ac97", sizeof(chip->name)); else - strlcpy(chip->name, + strscpy(chip->name, dev->v4l2->v4l2_dev.name, sizeof(chip->name)); return 0; } @@ -1920,8 +1989,8 @@ static int vidioc_querycap(struct file *file, void *priv, struct em28xx_v4l2 *v4l2 = dev->v4l2; struct usb_device *udev = interface_to_usbdev(dev->intf); - strlcpy(cap->driver, "em28xx", sizeof(cap->driver)); - strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card)); + strscpy(cap->driver, "em28xx", sizeof(cap->driver)); + strscpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card)); usb_make_path(udev, cap->bus_info, sizeof(cap->bus_info)); if (vdev->vfl_type == VFL_TYPE_GRABBER) @@ -1954,7 +2023,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, if (unlikely(f->index >= ARRAY_SIZE(format))) return -EINVAL; - strlcpy(f->description, format[f->index].name, sizeof(f->description)); + strscpy(f->description, format[f->index].name, sizeof(f->description)); f->pixelformat = format[f->index].fourcc; return 0; @@ -2045,7 +2114,7 @@ static int radio_g_tuner(struct file *file, void *priv, if (unlikely(t->index > 0)) return -EINVAL; - strcpy(t->name, "Radio"); + strscpy(t->name, "Radio", sizeof(t->name)); v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, tuner, g_tuner, t); @@ -2302,6 +2371,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_try_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, .vidioc_s_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, .vidioc_enum_framesizes = vidioc_enum_framesizes, + .vidioc_enumaudio = vidioc_enumaudio, .vidioc_g_audio = vidioc_g_audio, .vidioc_s_audio = vidioc_s_audio, diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h index 953caac025f2..a551072e62ed 100644 --- a/drivers/media/usb/em28xx/em28xx.h +++ b/drivers/media/usb/em28xx/em28xx.h @@ -335,6 +335,9 @@ enum em28xx_usb_audio_type { /** * em28xx_amux - describes the type of audio input used by em28xx * + * @EM28XX_AMUX_UNUSED: + * Used only on em28xx dev->map field, in order to mark an entry + * as unused. * @EM28XX_AMUX_VIDEO: * On devices without AC97, this is the only value that it is currently * allowed. @@ -369,7 +372,8 @@ enum em28xx_usb_audio_type { * same time, via the alsa mux. */ enum em28xx_amux { - EM28XX_AMUX_VIDEO, + EM28XX_AMUX_UNUSED = -1, + EM28XX_AMUX_VIDEO = 0, EM28XX_AMUX_LINE_IN, /* Some less-common mixer setups */ @@ -692,6 +696,8 @@ struct em28xx { unsigned int ctl_input; // selected input unsigned int ctl_ainput;// selected audio input unsigned int ctl_aoutput;// selected audio output + enum em28xx_amux amux_map[MAX_EM28XX_INPUT]; + int mute; int volume; diff --git a/drivers/media/usb/go7007/go7007-driver.c b/drivers/media/usb/go7007/go7007-driver.c index 62aeebcdd7f7..59cf50355b4e 100644 --- a/drivers/media/usb/go7007/go7007-driver.c +++ b/drivers/media/usb/go7007/go7007-driver.c @@ -208,7 +208,7 @@ static int init_i2c_module(struct i2c_adapter *adapter, const struct go_i2c *con struct i2c_board_info info; memset(&info, 0, sizeof(info)); - strlcpy(info.type, i2c->type, sizeof(info.type)); + strscpy(info.type, i2c->type, sizeof(info.type)); info.addr = i2c->addr; info.flags = i2c->flags; diff --git a/drivers/media/usb/go7007/go7007-v4l2.c b/drivers/media/usb/go7007/go7007-v4l2.c index c55c82f70e54..7a2781fa83e7 100644 --- a/drivers/media/usb/go7007/go7007-v4l2.c +++ b/drivers/media/usb/go7007/go7007-v4l2.c @@ -284,9 +284,9 @@ static int vidioc_querycap(struct file *file, void *priv, { struct go7007 *go = video_drvdata(file); - strlcpy(cap->driver, "go7007", sizeof(cap->driver)); - strlcpy(cap->card, go->name, sizeof(cap->card)); - strlcpy(cap->bus_info, go->bus_info, sizeof(cap->bus_info)); + strscpy(cap->driver, "go7007", sizeof(cap->driver)); + strscpy(cap->card, go->name, sizeof(cap->card)); + strscpy(cap->bus_info, go->bus_info, sizeof(cap->bus_info)); cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; @@ -634,8 +634,8 @@ static int vidioc_enum_input(struct file *file, void *priv, if (inp->index >= go->board_info->num_inputs) return -EINVAL; - strlcpy(inp->name, go->board_info->inputs[inp->index].name, - sizeof(inp->name)); + strscpy(inp->name, go->board_info->inputs[inp->index].name, + sizeof(inp->name)); /* If this board has a tuner, it will be the first input */ if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) && @@ -673,7 +673,7 @@ static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a) if (a->index >= go->board_info->num_aud_inputs) return -EINVAL; - strlcpy(a->name, go->board_info->aud_inputs[a->index].name, + strscpy(a->name, go->board_info->aud_inputs[a->index].name, sizeof(a->name)); a->capability = V4L2_AUDCAP_STEREO; return 0; @@ -684,7 +684,7 @@ static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a) struct go7007 *go = video_drvdata(file); a->index = go->aud_input; - strlcpy(a->name, go->board_info->aud_inputs[go->aud_input].name, + strscpy(a->name, go->board_info->aud_inputs[go->aud_input].name, sizeof(a->name)); a->capability = V4L2_AUDCAP_STEREO; return 0; @@ -742,7 +742,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, if (t->index != 0) return -EINVAL; - strlcpy(t->name, "Tuner", sizeof(t->name)); + strscpy(t->name, "Tuner", sizeof(t->name)); return call_all(&go->v4l2_dev, tuner, g_tuner, t); } diff --git a/drivers/media/usb/go7007/snd-go7007.c b/drivers/media/usb/go7007/snd-go7007.c index 137fc253b122..fc84b37d5587 100644 --- a/drivers/media/usb/go7007/snd-go7007.c +++ b/drivers/media/usb/go7007/snd-go7007.c @@ -260,10 +260,10 @@ int go7007_snd_init(struct go7007 *go) kfree(gosnd); return ret; } - strlcpy(gosnd->card->driver, "go7007", sizeof(gosnd->card->driver)); - strlcpy(gosnd->card->shortname, go->name, sizeof(gosnd->card->driver)); - strlcpy(gosnd->card->longname, gosnd->card->shortname, - sizeof(gosnd->card->longname)); + strscpy(gosnd->card->driver, "go7007", sizeof(gosnd->card->driver)); + strscpy(gosnd->card->shortname, go->name, sizeof(gosnd->card->driver)); + strscpy(gosnd->card->longname, gosnd->card->shortname, + sizeof(gosnd->card->longname)); gosnd->pcm->private_data = go; snd_pcm_set_ops(gosnd->pcm, SNDRV_PCM_STREAM_CAPTURE, diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c index 57aa521e16b1..fce9d6f4b7c9 100644 --- a/drivers/media/usb/gspca/gspca.c +++ b/drivers/media/usb/gspca/gspca.c @@ -1193,11 +1193,11 @@ static int vidioc_querycap(struct file *file, void *priv, { struct gspca_dev *gspca_dev = video_drvdata(file); - strlcpy((char *) cap->driver, gspca_dev->sd_desc->name, - sizeof cap->driver); + strscpy((char *)cap->driver, gspca_dev->sd_desc->name, + sizeof(cap->driver)); if (gspca_dev->dev->product != NULL) { - strlcpy((char *) cap->card, gspca_dev->dev->product, - sizeof cap->card); + strscpy((char *)cap->card, gspca_dev->dev->product, + sizeof(cap->card)); } else { snprintf((char *) cap->card, sizeof cap->card, "USB Camera (%04x:%04x)", @@ -1222,7 +1222,7 @@ static int vidioc_enum_input(struct file *file, void *priv, return -EINVAL; input->type = V4L2_INPUT_TYPE_CAMERA; input->status = gspca_dev->cam.input_flags; - strlcpy(input->name, gspca_dev->sd_desc->name, + strscpy(input->name, gspca_dev->sd_desc->name, sizeof input->name); return 0; } diff --git a/drivers/media/usb/gspca/sn9c20x.c b/drivers/media/usb/gspca/sn9c20x.c index cfa2a04d9f3f..5984bb12bcff 100644 --- a/drivers/media/usb/gspca/sn9c20x.c +++ b/drivers/media/usb/gspca/sn9c20x.c @@ -1601,7 +1601,7 @@ static int sd_chip_info(struct gspca_dev *gspca_dev, if (chip->match.addr > 1) return -EINVAL; if (chip->match.addr == 1) - strlcpy(chip->name, "sensor", sizeof(chip->name)); + strscpy(chip->name, "sensor", sizeof(chip->name)); return 0; } #endif diff --git a/drivers/media/usb/gspca/sq930x.c b/drivers/media/usb/gspca/sq930x.c index d7cbcf2b3947..e15b45f022e1 100644 --- a/drivers/media/usb/gspca/sq930x.c +++ b/drivers/media/usb/gspca/sq930x.c @@ -1044,7 +1044,7 @@ static void sd_dq_callback(struct gspca_dev *gspca_dev) v4l2_ctrl_g_ctrl(sd->gain)); gspca_dev->cam.bulk_nurbs = 1; - ret = usb_submit_urb(gspca_dev->urb[0], GFP_ATOMIC); + ret = usb_submit_urb(gspca_dev->urb[0], GFP_KERNEL); if (ret < 0) pr_err("sd_dq_callback() err %d\n", ret); diff --git a/drivers/media/usb/hackrf/hackrf.c b/drivers/media/usb/hackrf/hackrf.c index 34085a0b15a1..d43785206622 100644 --- a/drivers/media/usb/hackrf/hackrf.c +++ b/drivers/media/usb/hackrf/hackrf.c @@ -918,8 +918,8 @@ static int hackrf_querycap(struct file *file, void *fh, cap->capabilities = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_TUNER | V4L2_CAP_SDR_OUTPUT | V4L2_CAP_MODULATOR | V4L2_CAP_DEVICE_CAPS | cap->device_caps; - strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver)); - strlcpy(cap->card, dev->rx_vdev.name, sizeof(cap->card)); + strscpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver)); + strscpy(cap->card, dev->rx_vdev.name, sizeof(cap->card)); usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); return 0; @@ -1041,14 +1041,14 @@ static int hackrf_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) dev_dbg(dev->dev, "index=%d\n", v->index); if (v->index == 0) { - strlcpy(v->name, "HackRF ADC", sizeof(v->name)); + strscpy(v->name, "HackRF ADC", sizeof(v->name)); v->type = V4L2_TUNER_SDR; v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS; v->rangelow = bands_adc_dac[0].rangelow; v->rangehigh = bands_adc_dac[0].rangehigh; ret = 0; } else if (v->index == 1) { - strlcpy(v->name, "HackRF RF", sizeof(v->name)); + strscpy(v->name, "HackRF RF", sizeof(v->name)); v->type = V4L2_TUNER_RF; v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS; v->rangelow = bands_rx_tx[0].rangelow; @@ -1080,14 +1080,14 @@ static int hackrf_g_modulator(struct file *file, void *fh, dev_dbg(dev->dev, "index=%d\n", a->index); if (a->index == 0) { - strlcpy(a->name, "HackRF DAC", sizeof(a->name)); + strscpy(a->name, "HackRF DAC", sizeof(a->name)); a->type = V4L2_TUNER_SDR; a->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS; a->rangelow = bands_adc_dac[0].rangelow; a->rangehigh = bands_adc_dac[0].rangehigh; ret = 0; } else if (a->index == 1) { - strlcpy(a->name, "HackRF RF", sizeof(a->name)); + strscpy(a->name, "HackRF RF", sizeof(a->name)); a->type = V4L2_TUNER_RF; a->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS; a->rangelow = bands_rx_tx[0].rangelow; diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c index 1b89c77bad66..e082086428a4 100644 --- a/drivers/media/usb/hdpvr/hdpvr-video.c +++ b/drivers/media/usb/hdpvr/hdpvr-video.c @@ -578,8 +578,8 @@ static int vidioc_querycap(struct file *file, void *priv, { struct hdpvr_device *dev = video_drvdata(file); - strcpy(cap->driver, "hdpvr"); - strcpy(cap->card, "Hauppauge HD PVR"); + strscpy(cap->driver, "hdpvr", sizeof(cap->driver)); + strscpy(cap->card, "Hauppauge HD PVR", sizeof(cap->card)); usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE; @@ -873,7 +873,7 @@ static int vidioc_g_audio(struct file *file, void *private_data, audio->index = dev->options.audio_input; audio->capability = V4L2_AUDCAP_STEREO; - strlcpy(audio->name, audio_iname[audio->index], sizeof(audio->name)); + strscpy(audio->name, audio_iname[audio->index], sizeof(audio->name)); audio->name[sizeof(audio->name) - 1] = '\0'; return 0; } @@ -1238,7 +1238,8 @@ int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent, /* setup and register video device */ dev->video_dev = hdpvr_video_template; - strcpy(dev->video_dev.name, "Hauppauge HD PVR"); + strscpy(dev->video_dev.name, "Hauppauge HD PVR", + sizeof(dev->video_dev.name)); dev->video_dev.v4l2_dev = &dev->v4l2_dev; video_set_drvdata(&dev->video_dev, dev); diff --git a/drivers/media/usb/msi2500/msi2500.c b/drivers/media/usb/msi2500/msi2500.c index 65ef755adfdc..0fc4076c6d16 100644 --- a/drivers/media/usb/msi2500/msi2500.c +++ b/drivers/media/usb/msi2500/msi2500.c @@ -604,8 +604,8 @@ static int msi2500_querycap(struct file *file, void *fh, dev_dbg(dev->dev, "\n"); - strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver)); - strlcpy(cap->card, dev->vdev.name, sizeof(cap->card)); + strscpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver)); + strscpy(cap->card, dev->vdev.name, sizeof(cap->card)); usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); cap->device_caps = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_STREAMING | V4L2_CAP_READWRITE | V4L2_CAP_TUNER; @@ -916,7 +916,7 @@ static int msi2500_enum_fmt_sdr_cap(struct file *file, void *priv, if (f->index >= dev->num_formats) return -EINVAL; - strlcpy(f->description, formats[f->index].name, sizeof(f->description)); + strscpy(f->description, formats[f->index].name, sizeof(f->description)); f->pixelformat = formats[f->index].pixelformat; return 0; @@ -1017,7 +1017,7 @@ static int msi2500_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) dev_dbg(dev->dev, "index=%d\n", v->index); if (v->index == 0) { - strlcpy(v->name, "Mirics MSi2500", sizeof(v->name)); + strscpy(v->name, "Mirics MSi2500", sizeof(v->name)); v->type = V4L2_TUNER_ADC; v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS; v->rangelow = 1200000; diff --git a/drivers/media/usb/pulse8-cec/pulse8-cec.c b/drivers/media/usb/pulse8-cec/pulse8-cec.c index 350635826aae..365c78b748dd 100644 --- a/drivers/media/usb/pulse8-cec/pulse8-cec.c +++ b/drivers/media/usb/pulse8-cec/pulse8-cec.c @@ -571,7 +571,8 @@ static int pulse8_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr) memset(osd_str + osd_len, ' ', 4 - osd_len); osd_len = 4; osd_str[osd_len] = '\0'; - strcpy(adap->log_addrs.osd_name, osd_str); + strscpy(adap->log_addrs.osd_name, osd_str, + sizeof(adap->log_addrs.osd_name)); } err = pulse8_send_and_wait(pulse8, cmd, 1 + osd_len, MSGCODE_COMMAND_ACCEPTED, 0); diff --git a/drivers/media/usb/pvrusb2/pvrusb2-debug.h b/drivers/media/usb/pvrusb2/pvrusb2-debug.h index 5cd16292e2fa..1323f949f454 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-debug.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-debug.h @@ -17,7 +17,7 @@ extern int pvrusb2_debug; -#define pvr2_trace(msk, fmt, arg...) do {if(msk & pvrusb2_debug) printk(KERN_INFO "pvrusb2: " fmt "\n", ##arg); } while (0) +#define pvr2_trace(msk, fmt, arg...) do {if (msk & pvrusb2_debug) pr_info("pvrusb2: " fmt "\n", ##arg); } while (0) /* These are listed in *rough* order of decreasing usefulness and increasing noise level. */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c index a8519da0020b..7702285c1519 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c @@ -3293,12 +3293,12 @@ void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw) int nr = pvr2_hdw_get_unit_number(hdw); LOCK_TAKE(hdw->big_lock); do { - printk(KERN_INFO "pvrusb2: ================= START STATUS CARD #%d =================\n", nr); + pr_info("pvrusb2: ================= START STATUS CARD #%d =================\n", nr); v4l2_device_call_all(&hdw->v4l2_dev, 0, core, log_status); pvr2_trace(PVR2_TRACE_INFO,"cx2341x config:"); cx2341x_log_status(&hdw->enc_ctl_state, "pvrusb2"); pvr2_hdw_state_log_state(hdw); - printk(KERN_INFO "pvrusb2: ================== END STATUS CARD #%d ==================\n", nr); + pr_info("pvrusb2: ================== END STATUS CARD #%d ==================\n", nr); } while (0); LOCK_GIVE(hdw->big_lock); } @@ -4851,7 +4851,7 @@ static void pvr2_hdw_state_log_state(struct pvr2_hdw *hdw) for (idx = 0; ; idx++) { ccnt = pvr2_hdw_report_unlocked(hdw,idx,buf,sizeof(buf)); if (!ccnt) break; - printk(KERN_INFO "%s %.*s\n",hdw->name,ccnt,buf); + pr_info("%s %.*s\n", hdw->name, ccnt, buf); } ccnt = pvr2_hdw_report_clients(hdw, buf, sizeof(buf)); if (ccnt >= sizeof(buf)) @@ -4863,7 +4863,7 @@ static void pvr2_hdw_state_log_state(struct pvr2_hdw *hdw) while ((lcnt + ucnt < ccnt) && (buf[lcnt + ucnt] != '\n')) { lcnt++; } - printk(KERN_INFO "%s %.*s\n", hdw->name, lcnt, buf + ucnt); + pr_info("%s %.*s\n", hdw->name, lcnt, buf + ucnt); ucnt += lcnt + 1; } } diff --git a/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c index f3003ca05f4b..8f023085c2d9 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c @@ -478,8 +478,7 @@ static int pvr2_i2c_xfer(struct i2c_adapter *i2c_adap, unsigned int idx,offs,cnt; for (idx = 0; idx < num; idx++) { cnt = msgs[idx].len; - printk(KERN_INFO - "pvrusb2 i2c xfer %u/%u: addr=0x%x len=%d %s", + pr_info("pvrusb2 i2c xfer %u/%u: addr=0x%x len=%d %s", idx+1,num, msgs[idx].addr, cnt, @@ -487,22 +486,21 @@ static int pvr2_i2c_xfer(struct i2c_adapter *i2c_adap, "read" : "write")); if ((ret > 0) || !(msgs[idx].flags & I2C_M_RD)) { if (cnt > 8) cnt = 8; - printk(KERN_CONT " ["); + pr_cont(" ["); for (offs = 0; offs < cnt; offs++) { - if (offs) printk(KERN_CONT " "); - printk(KERN_CONT "%02x",msgs[idx].buf[offs]); + if (offs) pr_cont(" "); + pr_cont("%02x", msgs[idx].buf[offs]); } - if (offs < cnt) printk(KERN_CONT " ..."); - printk(KERN_CONT "]"); + if (offs < cnt) pr_cont(" ..."); + pr_cont("]"); } if (idx+1 == num) { - printk(KERN_CONT " result=%d",ret); + pr_cont(" result=%d", ret); } - printk(KERN_CONT "\n"); + pr_cont("\n"); } if (!num) { - printk(KERN_INFO - "pvrusb2 i2c xfer null transfer result=%d\n", + pr_info("pvrusb2 i2c xfer null transfer result=%d\n", ret); } } @@ -542,14 +540,14 @@ static int do_i2c_probe(struct pvr2_hdw *hdw, int addr) static void do_i2c_scan(struct pvr2_hdw *hdw) { int i; - printk(KERN_INFO "%s: i2c scan beginning\n", hdw->name); + pr_info("%s: i2c scan beginning\n", hdw->name); for (i = 0; i < 128; i++) { if (do_i2c_probe(hdw, i)) { - printk(KERN_INFO "%s: i2c scan: found device @ 0x%x\n", + pr_info("%s: i2c scan: found device @ 0x%x\n", hdw->name, i); } } - printk(KERN_INFO "%s: i2c scan done.\n", hdw->name); + pr_info("%s: i2c scan done.\n", hdw->name); } static void pvr2_i2c_register_ir(struct pvr2_hdw *hdw) @@ -573,7 +571,7 @@ static void pvr2_i2c_register_ir(struct pvr2_hdw *hdw) /* IR Receiver */ info.addr = 0x18; info.platform_data = init_data; - strlcpy(info.type, "ir_video", I2C_NAME_SIZE); + strscpy(info.type, "ir_video", I2C_NAME_SIZE); pvr2_trace(PVR2_TRACE_INFO, "Binding %s to i2c address 0x%02x.", info.type, info.addr); i2c_new_device(&hdw->i2c_adap, &info); @@ -588,7 +586,7 @@ static void pvr2_i2c_register_ir(struct pvr2_hdw *hdw) /* IR Transceiver */ info.addr = 0x71; info.platform_data = init_data; - strlcpy(info.type, "ir_z8f0811_haup", I2C_NAME_SIZE); + strscpy(info.type, "ir_z8f0811_haup", I2C_NAME_SIZE); pvr2_trace(PVR2_TRACE_INFO, "Binding %s to i2c address 0x%02x.", info.type, info.addr); i2c_new_device(&hdw->i2c_adap, &info); @@ -612,7 +610,7 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw) /* However, deal with various special cases for 24xxx hardware. */ if (ir_mode[hdw->unit_number] == 0) { - printk(KERN_INFO "%s: IR disabled\n",hdw->name); + pr_info("%s: IR disabled\n", hdw->name); hdw->i2c_func[0x18] = i2c_black_hole; } else if (ir_mode[hdw->unit_number] == 1) { if (hdw->ir_scheme_active == PVR2_IR_SCHEME_24XXX) { @@ -631,7 +629,7 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw) // Configure the adapter and set up everything else related to it. hdw->i2c_adap = pvr2_i2c_adap_template; hdw->i2c_algo = pvr2_i2c_algo_template; - strlcpy(hdw->i2c_adap.name,hdw->name,sizeof(hdw->i2c_adap.name)); + strscpy(hdw->i2c_adap.name, hdw->name, sizeof(hdw->i2c_adap.name)); hdw->i2c_adap.dev.parent = &hdw->usb_dev->dev; hdw->i2c_adap.algo = &hdw->i2c_algo; hdw->i2c_adap.algo_data = hdw; diff --git a/drivers/media/usb/pvrusb2/pvrusb2-main.c b/drivers/media/usb/pvrusb2/pvrusb2-main.c index cbe2c3a22458..23672dd352f5 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-main.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-main.c @@ -132,10 +132,10 @@ static int __init pvr_init(void) ret = usb_register(&pvr_driver); if (ret == 0) - printk(KERN_INFO "pvrusb2: " DRIVER_VERSION ":" + pr_info("pvrusb2: " DRIVER_VERSION ":" DRIVER_DESC "\n"); if (pvrusb2_debug) - printk(KERN_INFO "pvrusb2: Debug mask is %d (0x%x)\n", + pr_info("pvrusb2: Debug mask is %d (0x%x)\n", pvrusb2_debug,pvrusb2_debug); pvr2_trace(PVR2_TRACE_INIT,"pvr_init complete"); diff --git a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c index e53a80b589a1..97a93ed4bcda 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c @@ -121,10 +121,10 @@ static int pvr2_querycap(struct file *file, void *priv, struct v4l2_capability * struct pvr2_v4l2_fh *fh = file->private_data; struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - strlcpy(cap->driver, "pvrusb2", sizeof(cap->driver)); - strlcpy(cap->bus_info, pvr2_hdw_get_bus_info(hdw), - sizeof(cap->bus_info)); - strlcpy(cap->card, pvr2_hdw_get_desc(hdw), sizeof(cap->card)); + strscpy(cap->driver, "pvrusb2", sizeof(cap->driver)); + strscpy(cap->bus_info, pvr2_hdw_get_bus_info(hdw), + sizeof(cap->bus_info)); + strscpy(cap->card, pvr2_hdw_get_desc(hdw), sizeof(cap->card)); cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO | V4L2_CAP_READWRITE | V4L2_CAP_DEVICE_CAPS; @@ -545,7 +545,7 @@ static int pvr2_queryctrl(struct file *file, void *priv, "QUERYCTRL id=0x%x mapping name=%s (%s)", vc->id, pvr2_ctrl_get_name(cptr), pvr2_ctrl_get_desc(cptr)); - strlcpy(vc->name, pvr2_ctrl_get_desc(cptr), sizeof(vc->name)); + strscpy(vc->name, pvr2_ctrl_get_desc(cptr), sizeof(vc->name)); vc->flags = pvr2_ctrl_get_v4lflags(cptr); pvr2_ctrl_get_def(cptr, &val); vc->default_value = val; @@ -869,7 +869,7 @@ static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip) are gone. */ video_unregister_device(&dip->devbase); - printk(KERN_INFO "%s\n", msg); + pr_info("%s\n", msg); } @@ -1260,7 +1260,7 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, ": Failed to register pvrusb2 v4l device\n"); } - printk(KERN_INFO "pvrusb2: registered device %s [%s]\n", + pr_info("pvrusb2: registered device %s [%s]\n", video_device_node_name(&dip->devbase), pvr2_config_get_name(dip->config)); diff --git a/drivers/media/usb/pwc/pwc-if.c b/drivers/media/usb/pwc/pwc-if.c index 54b036d39c5b..72704f4d5330 100644 --- a/drivers/media/usb/pwc/pwc-if.c +++ b/drivers/media/usb/pwc/pwc-if.c @@ -1027,7 +1027,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id /* Init video_device structure */ pdev->vdev = pwc_template; - strcpy(pdev->vdev.name, name); + strscpy(pdev->vdev.name, name, sizeof(pdev->vdev.name)); pdev->vdev.queue = &pdev->vb_queue; pdev->vdev.queue->lock = &pdev->vb_queue_lock; video_set_drvdata(&pdev->vdev, pdev); diff --git a/drivers/media/usb/pwc/pwc-v4l.c b/drivers/media/usb/pwc/pwc-v4l.c index 043b2b97cee6..bef6e4ef8a7e 100644 --- a/drivers/media/usb/pwc/pwc-v4l.c +++ b/drivers/media/usb/pwc/pwc-v4l.c @@ -492,8 +492,8 @@ static int pwc_querycap(struct file *file, void *fh, struct v4l2_capability *cap { struct pwc_device *pdev = video_drvdata(file); - strcpy(cap->driver, PWC_NAME); - strlcpy(cap->card, pdev->vdev.name, sizeof(cap->card)); + strscpy(cap->driver, PWC_NAME, sizeof(cap->driver)); + strscpy(cap->card, pdev->vdev.name, sizeof(cap->card)); usb_make_path(pdev->udev, cap->bus_info, sizeof(cap->bus_info)); cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | V4L2_CAP_READWRITE; @@ -506,7 +506,7 @@ static int pwc_enum_input(struct file *file, void *fh, struct v4l2_input *i) if (i->index) /* Only one INPUT is supported */ return -EINVAL; - strlcpy(i->name, "Camera", sizeof(i->name)); + strscpy(i->name, "Camera", sizeof(i->name)); i->type = V4L2_INPUT_TYPE_CAMERA; return 0; } @@ -889,11 +889,13 @@ static int pwc_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc /* RAW format */ f->pixelformat = pdev->type <= 646 ? V4L2_PIX_FMT_PWC1 : V4L2_PIX_FMT_PWC2; f->flags = V4L2_FMT_FLAG_COMPRESSED; - strlcpy(f->description, "Raw Philips Webcam", sizeof(f->description)); + strscpy(f->description, "Raw Philips Webcam", + sizeof(f->description)); break; case 1: f->pixelformat = V4L2_PIX_FMT_YUV420; - strlcpy(f->description, "4:2:0, planar, Y-Cb-Cr", sizeof(f->description)); + strscpy(f->description, "4:2:0, planar, Y-Cb-Cr", + sizeof(f->description)); break; default: return -EINVAL; diff --git a/drivers/media/usb/rainshadow-cec/rainshadow-cec.c b/drivers/media/usb/rainshadow-cec/rainshadow-cec.c index cecdcbcd400c..d9964da05976 100644 --- a/drivers/media/usb/rainshadow-cec/rainshadow-cec.c +++ b/drivers/media/usb/rainshadow-cec/rainshadow-cec.c @@ -141,7 +141,8 @@ static void rain_irq_work_handler(struct work_struct *work) !memcmp(rain->cmd, "STA", 3)) { rain_process_msg(rain); } else { - strcpy(rain->cmd_reply, rain->cmd); + strscpy(rain->cmd_reply, rain->cmd, + sizeof(rain->cmd_reply)); complete(&rain->cmd_done); } rain->cmd_idx = 0; diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c index 82927eb334c4..5b3e54b76e9a 100644 --- a/drivers/media/usb/s2255/s2255drv.c +++ b/drivers/media/usb/s2255/s2255drv.c @@ -730,8 +730,8 @@ static int vidioc_querycap(struct file *file, void *priv, struct s2255_vc *vc = video_drvdata(file); struct s2255_dev *dev = vc->dev; - strlcpy(cap->driver, "s2255", sizeof(cap->driver)); - strlcpy(cap->card, "s2255", sizeof(cap->card)); + strscpy(cap->driver, "s2255", sizeof(cap->driver)); + strscpy(cap->card, "s2255", sizeof(cap->card)); usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | V4L2_CAP_READWRITE; @@ -749,7 +749,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, if (!jpeg_enable && ((formats[index].fourcc == V4L2_PIX_FMT_JPEG) || (formats[index].fourcc == V4L2_PIX_FMT_MJPEG))) return -EINVAL; - strlcpy(f->description, formats[index].name, sizeof(f->description)); + strscpy(f->description, formats[index].name, sizeof(f->description)); f->pixelformat = formats[index].fourcc; return 0; } @@ -1195,10 +1195,10 @@ static int vidioc_enum_input(struct file *file, void *priv, switch (dev->pid) { case 0x2255: default: - strlcpy(inp->name, "Composite", sizeof(inp->name)); + strscpy(inp->name, "Composite", sizeof(inp->name)); break; case 0x2257: - strlcpy(inp->name, (vc->idx < 2) ? "Composite" : "S-Video", + strscpy(inp->name, (vc->idx < 2) ? "Composite" : "S-Video", sizeof(inp->name)); break; } diff --git a/drivers/media/usb/stk1160/stk1160-i2c.c b/drivers/media/usb/stk1160/stk1160-i2c.c index 62a12d5356ad..c3a15564e5cb 100644 --- a/drivers/media/usb/stk1160/stk1160-i2c.c +++ b/drivers/media/usb/stk1160/stk1160-i2c.c @@ -260,7 +260,7 @@ int stk1160_i2c_register(struct stk1160 *dev) dev->i2c_adap = adap_template; dev->i2c_adap.dev.parent = dev->dev; - strcpy(dev->i2c_adap.name, "stk1160"); + strscpy(dev->i2c_adap.name, "stk1160", sizeof(dev->i2c_adap.name)); dev->i2c_adap.algo_data = dev; i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev); diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c index 504e413edcd2..701ed3d4afe6 100644 --- a/drivers/media/usb/stk1160/stk1160-v4l.c +++ b/drivers/media/usb/stk1160/stk1160-v4l.c @@ -344,8 +344,8 @@ static int vidioc_querycap(struct file *file, { struct stk1160 *dev = video_drvdata(file); - strcpy(cap->driver, "stk1160"); - strcpy(cap->card, "stk1160"); + strscpy(cap->driver, "stk1160", sizeof(cap->driver)); + strscpy(cap->card, "stk1160", sizeof(cap->card)); usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | @@ -361,7 +361,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, if (f->index != 0) return -EINVAL; - strlcpy(f->description, format[f->index].name, sizeof(f->description)); + strscpy(f->description, format[f->index].name, sizeof(f->description)); f->pixelformat = format[f->index].fourcc; return 0; } diff --git a/drivers/media/usb/stkwebcam/stk-webcam.c b/drivers/media/usb/stkwebcam/stk-webcam.c index 5accb5241072..e11d5d5b7c26 100644 --- a/drivers/media/usb/stkwebcam/stk-webcam.c +++ b/drivers/media/usb/stkwebcam/stk-webcam.c @@ -793,8 +793,8 @@ static int stk_vidioc_querycap(struct file *filp, { struct stk_camera *dev = video_drvdata(filp); - strcpy(cap->driver, "stk"); - strcpy(cap->card, "stk"); + strscpy(cap->driver, "stk", sizeof(cap->driver)); + strscpy(cap->card, "stk", sizeof(cap->card)); usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); cap->device_caps = V4L2_CAP_VIDEO_CAPTURE @@ -809,7 +809,7 @@ static int stk_vidioc_enum_input(struct file *filp, if (input->index != 0) return -EINVAL; - strcpy(input->name, "Syntek USB Camera"); + strscpy(input->name, "Syntek USB Camera", sizeof(input->name)); input->type = V4L2_INPUT_TYPE_CAMERA; return 0; } @@ -859,23 +859,23 @@ static int stk_vidioc_enum_fmt_vid_cap(struct file *filp, switch (fmtd->index) { case 0: fmtd->pixelformat = V4L2_PIX_FMT_RGB565; - strcpy(fmtd->description, "r5g6b5"); + strscpy(fmtd->description, "r5g6b5", sizeof(fmtd->description)); break; case 1: fmtd->pixelformat = V4L2_PIX_FMT_RGB565X; - strcpy(fmtd->description, "r5g6b5BE"); + strscpy(fmtd->description, "r5g6b5BE", sizeof(fmtd->description)); break; case 2: fmtd->pixelformat = V4L2_PIX_FMT_UYVY; - strcpy(fmtd->description, "yuv4:2:2"); + strscpy(fmtd->description, "yuv4:2:2", sizeof(fmtd->description)); break; case 3: fmtd->pixelformat = V4L2_PIX_FMT_SBGGR8; - strcpy(fmtd->description, "Raw bayer"); + strscpy(fmtd->description, "Raw bayer", sizeof(fmtd->description)); break; case 4: fmtd->pixelformat = V4L2_PIX_FMT_YUYV; - strcpy(fmtd->description, "yuv4:2:2"); + strscpy(fmtd->description, "yuv4:2:2", sizeof(fmtd->description)); break; default: return -EINVAL; diff --git a/drivers/media/usb/tm6000/tm6000-alsa.c b/drivers/media/usb/tm6000/tm6000-alsa.c index f18cffae4c85..b965931793b5 100644 --- a/drivers/media/usb/tm6000/tm6000-alsa.c +++ b/drivers/media/usb/tm6000/tm6000-alsa.c @@ -429,8 +429,8 @@ static int tm6000_audio_init(struct tm6000_core *dev) snd_printk(KERN_ERR "cannot create card instance %d\n", devnr); return rc; } - strcpy(card->driver, "tm6000-alsa"); - strcpy(card->shortname, "TM5600/60x0"); + strscpy(card->driver, "tm6000-alsa", sizeof(card->driver)); + strscpy(card->shortname, "TM5600/60x0", sizeof(card->shortname)); sprintf(card->longname, "TM5600/60x0 Audio at bus %d device %d", dev->udev->bus->busnum, dev->udev->devnum); @@ -456,7 +456,7 @@ static int tm6000_audio_init(struct tm6000_core *dev) pcm->info_flags = 0; pcm->private_data = chip; - strcpy(pcm->name, "Trident TM5600/60x0"); + strscpy(pcm->name, "Trident TM5600/60x0", sizeof(pcm->name)); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_tm6000_pcm_ops); diff --git a/drivers/media/usb/tm6000/tm6000-i2c.c b/drivers/media/usb/tm6000/tm6000-i2c.c index ccd1adf862b1..8c0476dfe54f 100644 --- a/drivers/media/usb/tm6000/tm6000-i2c.c +++ b/drivers/media/usb/tm6000/tm6000-i2c.c @@ -292,7 +292,7 @@ int tm6000_i2c_register(struct tm6000_core *dev) dev->i2c_adap.owner = THIS_MODULE; dev->i2c_adap.algo = &tm6000_algo; dev->i2c_adap.dev.parent = &dev->udev->dev; - strlcpy(dev->i2c_adap.name, dev->name, sizeof(dev->i2c_adap.name)); + strscpy(dev->i2c_adap.name, dev->name, sizeof(dev->i2c_adap.name)); dev->i2c_adap.algo_data = dev; i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev); rc = i2c_add_adapter(&dev->i2c_adap); @@ -300,7 +300,7 @@ int tm6000_i2c_register(struct tm6000_core *dev) return rc; dev->i2c_client.adapter = &dev->i2c_adap; - strlcpy(dev->i2c_client.name, "tm6000 internal", I2C_NAME_SIZE); + strscpy(dev->i2c_client.name, "tm6000 internal", I2C_NAME_SIZE); tm6000_i2c_eeprom(dev); return 0; diff --git a/drivers/media/usb/tm6000/tm6000-video.c b/drivers/media/usb/tm6000/tm6000-video.c index 7d268f2404e1..6c992f197255 100644 --- a/drivers/media/usb/tm6000/tm6000-video.c +++ b/drivers/media/usb/tm6000/tm6000-video.c @@ -856,8 +856,9 @@ static int vidioc_querycap(struct file *file, void *priv, struct tm6000_core *dev = ((struct tm6000_fh *)priv)->dev; struct video_device *vdev = video_devdata(file); - strlcpy(cap->driver, "tm6000", sizeof(cap->driver)); - strlcpy(cap->card, "Trident TVMaster TM5600/6000/6010", sizeof(cap->card)); + strscpy(cap->driver, "tm6000", sizeof(cap->driver)); + strscpy(cap->card, "Trident TVMaster TM5600/6000/6010", + sizeof(cap->card)); usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); if (dev->tuner_type != TUNER_ABSENT) cap->device_caps |= V4L2_CAP_TUNER; @@ -879,7 +880,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, if (f->index >= ARRAY_SIZE(format)) return -EINVAL; - strlcpy(f->description, format[f->index].name, sizeof(f->description)); + strscpy(f->description, format[f->index].name, sizeof(f->description)); f->pixelformat = format[f->index].fourcc; return 0; } @@ -1091,7 +1092,7 @@ static int vidioc_enum_input(struct file *file, void *priv, else i->type = V4L2_INPUT_TYPE_CAMERA; - strcpy(i->name, iname[dev->vinput[n].type]); + strscpy(i->name, iname[dev->vinput[n].type], sizeof(i->name)); i->std = TM6000_STD; @@ -1188,7 +1189,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, if (0 != t->index) return -EINVAL; - strcpy(t->name, "Television"); + strscpy(t->name, "Television", sizeof(t->name)); t->type = V4L2_TUNER_ANALOG_TV; t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO; t->rangehigh = 0xffffffffUL; @@ -1268,7 +1269,7 @@ static int radio_g_tuner(struct file *file, void *priv, return -EINVAL; memset(t, 0, sizeof(*t)); - strcpy(t->name, "Radio"); + strscpy(t->name, "Radio", sizeof(t->name)); t->type = V4L2_TUNER_RADIO; t->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; t->rxsubchans = V4L2_TUNER_SUB_STEREO; diff --git a/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c index eed56895c2b9..6eb84cf007b4 100644 --- a/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c @@ -1686,7 +1686,7 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i /* i2c */ memset(&ttusb->i2c_adap, 0, sizeof(struct i2c_adapter)); - strcpy(ttusb->i2c_adap.name, "TTUSB DEC"); + strscpy(ttusb->i2c_adap.name, "TTUSB DEC", sizeof(ttusb->i2c_adap.name)); i2c_set_adapdata(&ttusb->i2c_adap, ttusb); diff --git a/drivers/media/usb/usbtv/usbtv-audio.c b/drivers/media/usb/usbtv/usbtv-audio.c index 4ce38246ed64..6f108996142d 100644 --- a/drivers/media/usb/usbtv/usbtv-audio.c +++ b/drivers/media/usb/usbtv/usbtv-audio.c @@ -358,8 +358,8 @@ int usbtv_audio_init(struct usbtv *usbtv) if (rv < 0) return rv; - strlcpy(card->driver, usbtv->dev->driver->name, sizeof(card->driver)); - strlcpy(card->shortname, "usbtv", sizeof(card->shortname)); + strscpy(card->driver, usbtv->dev->driver->name, sizeof(card->driver)); + strscpy(card->shortname, "usbtv", sizeof(card->shortname)); snprintf(card->longname, sizeof(card->longname), "USBTV Audio at bus %d device %d", usbtv->udev->bus->busnum, usbtv->udev->devnum); @@ -372,7 +372,7 @@ int usbtv_audio_init(struct usbtv *usbtv) if (rv < 0) goto err; - strlcpy(pcm->name, "USBTV Audio Input", sizeof(pcm->name)); + strscpy(pcm->name, "USBTV Audio Input", sizeof(pcm->name)); pcm->info_flags = 0; pcm->private_data = usbtv; diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c index 36a9a4017185..4a1eab711bdc 100644 --- a/drivers/media/usb/usbtv/usbtv-video.c +++ b/drivers/media/usb/usbtv/usbtv-video.c @@ -600,8 +600,8 @@ static int usbtv_querycap(struct file *file, void *priv, { struct usbtv *dev = video_drvdata(file); - strlcpy(cap->driver, "usbtv", sizeof(cap->driver)); - strlcpy(cap->card, "usbtv", sizeof(cap->card)); + strscpy(cap->driver, "usbtv", sizeof(cap->driver)); + strscpy(cap->card, "usbtv", sizeof(cap->card)); usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); cap->device_caps = V4L2_CAP_VIDEO_CAPTURE; cap->device_caps |= V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; @@ -616,10 +616,10 @@ static int usbtv_enum_input(struct file *file, void *priv, switch (i->index) { case USBTV_COMPOSITE_INPUT: - strlcpy(i->name, "Composite", sizeof(i->name)); + strscpy(i->name, "Composite", sizeof(i->name)); break; case USBTV_SVIDEO_INPUT: - strlcpy(i->name, "S-Video", sizeof(i->name)); + strscpy(i->name, "S-Video", sizeof(i->name)); break; default: return -EINVAL; @@ -636,8 +636,8 @@ static int usbtv_enum_fmt_vid_cap(struct file *file, void *priv, if (f->index > 0) return -EINVAL; - strlcpy(f->description, "16 bpp YUY2, 4:2:2, packed", - sizeof(f->description)); + strscpy(f->description, "16 bpp YUY2, 4:2:2, packed", + sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_YUYV; return 0; } @@ -934,7 +934,7 @@ int usbtv_video_init(struct usbtv *usbtv) } /* Video structure */ - strlcpy(usbtv->vdev.name, "usbtv", sizeof(usbtv->vdev.name)); + strscpy(usbtv->vdev.name, "usbtv", sizeof(usbtv->vdev.name)); usbtv->vdev.v4l2_dev = &usbtv->v4l2_dev; usbtv->vdev.release = video_device_release_empty; usbtv->vdev.fops = &usbtv_fops; diff --git a/drivers/media/usb/usbvision/usbvision-core.c b/drivers/media/usb/usbvision/usbvision-core.c index 7138c2b606cc..31e0e98d6daf 100644 --- a/drivers/media/usb/usbvision/usbvision-core.c +++ b/drivers/media/usb/usbvision/usbvision-core.c @@ -1272,7 +1272,6 @@ static void usbvision_isoc_irq(struct urb *urb) int len; struct usb_usbvision *usbvision = urb->context; int i; - unsigned long start_time = jiffies; struct usbvision_frame **f; /* We don't want to do anything if we are about to be removed! */ @@ -1324,8 +1323,6 @@ static void usbvision_isoc_irq(struct urb *urb) scratch_reset(usbvision); } - usbvision->time_in_irq += jiffies - start_time; - for (i = 0; i < USBVISION_URB_FRAMES; i++) { urb->iso_frame_desc[i].status = 0; urb->iso_frame_desc[i].actual_length = 0; diff --git a/drivers/media/usb/usbvision/usbvision-video.c b/drivers/media/usb/usbvision/usbvision-video.c index f29d1bef0293..dd2ff8ed6c6a 100644 --- a/drivers/media/usb/usbvision/usbvision-video.c +++ b/drivers/media/usb/usbvision/usbvision-video.c @@ -467,8 +467,8 @@ static int vidioc_querycap(struct file *file, void *priv, struct usb_usbvision *usbvision = video_drvdata(file); struct video_device *vdev = video_devdata(file); - strlcpy(vc->driver, "USBVision", sizeof(vc->driver)); - strlcpy(vc->card, + strscpy(vc->driver, "USBVision", sizeof(vc->driver)); + strscpy(vc->card, usbvision_device_data[usbvision->dev_model].model_string, sizeof(vc->card)); usb_make_path(usbvision->dev, vc->bus_info, sizeof(vc->bus_info)); @@ -504,9 +504,9 @@ static int vidioc_enum_input(struct file *file, void *priv, switch (chan) { case 0: if (usbvision_device_data[usbvision->dev_model].video_channels == 4) { - strcpy(vi->name, "White Video Input"); + strscpy(vi->name, "White Video Input", sizeof(vi->name)); } else { - strcpy(vi->name, "Television"); + strscpy(vi->name, "Television", sizeof(vi->name)); vi->type = V4L2_INPUT_TYPE_TUNER; vi->tuner = chan; vi->std = USBVISION_NORMS; @@ -515,22 +515,23 @@ static int vidioc_enum_input(struct file *file, void *priv, case 1: vi->type = V4L2_INPUT_TYPE_CAMERA; if (usbvision_device_data[usbvision->dev_model].video_channels == 4) - strcpy(vi->name, "Green Video Input"); + strscpy(vi->name, "Green Video Input", sizeof(vi->name)); else - strcpy(vi->name, "Composite Video Input"); + strscpy(vi->name, "Composite Video Input", + sizeof(vi->name)); vi->std = USBVISION_NORMS; break; case 2: vi->type = V4L2_INPUT_TYPE_CAMERA; if (usbvision_device_data[usbvision->dev_model].video_channels == 4) - strcpy(vi->name, "Yellow Video Input"); + strscpy(vi->name, "Yellow Video Input", sizeof(vi->name)); else - strcpy(vi->name, "S-Video Input"); + strscpy(vi->name, "S-Video Input", sizeof(vi->name)); vi->std = USBVISION_NORMS; break; case 3: vi->type = V4L2_INPUT_TYPE_CAMERA; - strcpy(vi->name, "Red Video Input"); + strscpy(vi->name, "Red Video Input", sizeof(vi->name)); vi->std = USBVISION_NORMS; break; } @@ -589,9 +590,9 @@ static int vidioc_g_tuner(struct file *file, void *priv, if (vt->index) /* Only tuner 0 */ return -EINVAL; if (vt->type == V4L2_TUNER_RADIO) - strcpy(vt->name, "Radio"); + strscpy(vt->name, "Radio", sizeof(vt->name)); else - strcpy(vt->name, "Television"); + strscpy(vt->name, "Television", sizeof(vt->name)); /* Let clients fill in the remainder of this struct */ call_all(usbvision, tuner, g_tuner, vt); @@ -814,7 +815,8 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, { if (vfd->index >= USBVISION_SUPPORTED_PALETTES - 1) return -EINVAL; - strcpy(vfd->description, usbvision_v4l2_format[vfd->index].desc); + strscpy(vfd->description, usbvision_v4l2_format[vfd->index].desc, + sizeof(vfd->description)); vfd->pixelformat = usbvision_v4l2_format[vfd->index].format; return 0; } diff --git a/drivers/media/usb/usbvision/usbvision.h b/drivers/media/usb/usbvision/usbvision.h index 6ecdcd58248f..017e7baf5747 100644 --- a/drivers/media/usb/usbvision/usbvision.h +++ b/drivers/media/usb/usbvision/usbvision.h @@ -447,7 +447,6 @@ struct usb_usbvision { unsigned long isoc_skip_count; /* How many empty ISO packets received */ unsigned long isoc_err_count; /* How many bad ISO packets received */ unsigned long isoc_packet_count; /* How many packets we totally got */ - unsigned long time_in_irq; /* How long do we need for interrupt */ int isoc_measure_bandwidth_count; int frame_num; /* How many video frames we send to user */ int max_strip_len; /* How big is the biggest strip */ diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index c2ad102bd693..d45415cbe6e7 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c @@ -38,7 +38,7 @@ * Controls */ -static struct uvc_control_info uvc_ctrls[] = { +static const struct uvc_control_info uvc_ctrls[] = { { .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_BRIGHTNESS_CONTROL, @@ -354,13 +354,13 @@ static struct uvc_control_info uvc_ctrls[] = { }, }; -static struct uvc_menu_info power_line_frequency_controls[] = { +static const struct uvc_menu_info power_line_frequency_controls[] = { { 0, "Disabled" }, { 1, "50 Hz" }, { 2, "60 Hz" }, }; -static struct uvc_menu_info exposure_auto_controls[] = { +static const struct uvc_menu_info exposure_auto_controls[] = { { 2, "Auto Mode" }, { 1, "Manual Mode" }, { 4, "Shutter Priority Mode" }, @@ -421,7 +421,7 @@ static void uvc_ctrl_set_rel_speed(struct uvc_control_mapping *mapping, data[first+1] = min_t(int, abs(value), 0xff); } -static struct uvc_control_mapping uvc_ctrl_mappings[] = { +static const struct uvc_control_mapping uvc_ctrl_mappings[] = { { .id = V4L2_CID_BRIGHTNESS, .name = "Brightness", @@ -978,7 +978,7 @@ static s32 __uvc_ctrl_get_value(struct uvc_control_mapping *mapping, s32 value = mapping->get(mapping, UVC_GET_CUR, data); if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) { - struct uvc_menu_info *menu = mapping->menu_info; + const struct uvc_menu_info *menu = mapping->menu_info; unsigned int i; for (i = 0; i < mapping->menu_count; ++i, ++menu) { @@ -1025,13 +1025,13 @@ static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, { struct uvc_control_mapping *master_map = NULL; struct uvc_control *master_ctrl = NULL; - struct uvc_menu_info *menu; + const struct uvc_menu_info *menu; unsigned int i; memset(v4l2_ctrl, 0, sizeof(*v4l2_ctrl)); v4l2_ctrl->id = mapping->id; v4l2_ctrl->type = mapping->v4l2_type; - strlcpy(v4l2_ctrl->name, mapping->name, sizeof(v4l2_ctrl->name)); + strscpy(v4l2_ctrl->name, mapping->name, sizeof(v4l2_ctrl->name)); v4l2_ctrl->flags = 0; if (!(ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR)) @@ -1145,7 +1145,7 @@ done: int uvc_query_v4l2_menu(struct uvc_video_chain *chain, struct v4l2_querymenu *query_menu) { - struct uvc_menu_info *menu_info; + const struct uvc_menu_info *menu_info; struct uvc_control_mapping *mapping; struct uvc_control *ctrl; u32 index = query_menu->index; @@ -1191,7 +1191,7 @@ int uvc_query_v4l2_menu(struct uvc_video_chain *chain, } } - strlcpy(query_menu->name, menu_info->name, sizeof(query_menu->name)); + strscpy(query_menu->name, menu_info->name, sizeof(query_menu->name)); done: mutex_unlock(&chain->ctrl_mutex); diff --git a/drivers/media/usb/uvc/uvc_debugfs.c b/drivers/media/usb/uvc/uvc_debugfs.c index 368f8f8dfcb5..77e7c2419b9b 100644 --- a/drivers/media/usb/uvc/uvc_debugfs.c +++ b/drivers/media/usb/uvc/uvc_debugfs.c @@ -106,9 +106,6 @@ void uvc_debugfs_init_stream(struct uvc_streaming *stream) void uvc_debugfs_cleanup_stream(struct uvc_streaming *stream) { - if (stream->debugfs_dir == NULL) - return; - debugfs_remove_recursive(stream->debugfs_dir); stream->debugfs_dir = NULL; } @@ -128,6 +125,5 @@ void uvc_debugfs_init(void) void uvc_debugfs_cleanup(void) { - if (uvc_debugfs_root_dir != NULL) - debugfs_remove_recursive(uvc_debugfs_root_dir); + debugfs_remove_recursive(uvc_debugfs_root_dir); } diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index d46dc432456c..bc369a0934a3 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -427,7 +427,7 @@ static int uvc_parse_format(struct uvc_device *dev, fmtdesc = uvc_format_by_guid(&buffer[5]); if (fmtdesc != NULL) { - strlcpy(format->name, fmtdesc->name, + strscpy(format->name, fmtdesc->name, sizeof(format->name)); format->fcc = fmtdesc->fcc; } else { @@ -445,7 +445,7 @@ static int uvc_parse_format(struct uvc_device *dev, */ if (dev->quirks & UVC_QUIRK_FORCE_Y8) { if (format->fcc == V4L2_PIX_FMT_YUYV) { - strlcpy(format->name, "Greyscale 8-bit (Y8 )", + strscpy(format->name, "Greyscale 8-bit (Y8 )", sizeof(format->name)); format->fcc = V4L2_PIX_FMT_GREY; format->bpp = 8; @@ -471,7 +471,7 @@ static int uvc_parse_format(struct uvc_device *dev, return -EINVAL; } - strlcpy(format->name, "MJPEG", sizeof(format->name)); + strscpy(format->name, "MJPEG", sizeof(format->name)); format->fcc = V4L2_PIX_FMT_MJPEG; format->flags = UVC_FMT_FLAG_COMPRESSED; format->bpp = 0; @@ -489,13 +489,13 @@ static int uvc_parse_format(struct uvc_device *dev, switch (buffer[8] & 0x7f) { case 0: - strlcpy(format->name, "SD-DV", sizeof(format->name)); + strscpy(format->name, "SD-DV", sizeof(format->name)); break; case 1: - strlcpy(format->name, "SDL-DV", sizeof(format->name)); + strscpy(format->name, "SDL-DV", sizeof(format->name)); break; case 2: - strlcpy(format->name, "HD-DV", sizeof(format->name)); + strscpy(format->name, "HD-DV", sizeof(format->name)); break; default: uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " @@ -914,7 +914,7 @@ static struct uvc_entity *uvc_alloc_entity(u16 type, u8 id, unsigned int size; unsigned int i; - extra_size = ALIGN(extra_size, sizeof(*entity->pads)); + extra_size = roundup(extra_size, sizeof(*entity->pads)); num_inputs = (type & UVC_TERM_OUTPUT) ? num_pads : num_pads - 1; size = sizeof(*entity) + extra_size + sizeof(*entity->pads) * num_pads + num_inputs; @@ -1932,7 +1932,7 @@ int uvc_register_video_device(struct uvc_device *dev, break; } - strlcpy(vdev->name, dev->name, sizeof(vdev->name)); + strscpy(vdev->name, dev->name, sizeof(vdev->name)); /* * Set the driver data before calling video_register_device, otherwise @@ -2027,10 +2027,9 @@ static int uvc_register_chains(struct uvc_device *dev) #ifdef CONFIG_MEDIA_CONTROLLER ret = uvc_mc_register_entities(chain); - if (ret < 0) { - uvc_printk(KERN_INFO, "Failed to register entites " - "(%d).\n", ret); - } + if (ret < 0) + uvc_printk(KERN_INFO, + "Failed to register entities (%d).\n", ret); #endif } @@ -2041,10 +2040,7 @@ static int uvc_register_chains(struct uvc_device *dev) * USB probe, disconnect, suspend and resume */ -struct uvc_device_info { - u32 quirks; - u32 meta_format; -}; +static const struct uvc_device_info uvc_quirk_none = { 0 }; static int uvc_probe(struct usb_interface *intf, const struct usb_device_id *id) @@ -2053,7 +2049,6 @@ static int uvc_probe(struct usb_interface *intf, struct uvc_device *dev; const struct uvc_device_info *info = (const struct uvc_device_info *)id->driver_info; - u32 quirks = info ? info->quirks : 0; int function; int ret; @@ -2080,13 +2075,12 @@ static int uvc_probe(struct usb_interface *intf, dev->udev = usb_get_dev(udev); dev->intf = usb_get_intf(intf); dev->intfnum = intf->cur_altsetting->desc.bInterfaceNumber; - dev->quirks = (uvc_quirks_param == -1) - ? quirks : uvc_quirks_param; - if (info) - dev->meta_format = info->meta_format; + dev->info = info ? info : &uvc_quirk_none; + dev->quirks = uvc_quirks_param == -1 + ? dev->info->quirks : uvc_quirks_param; if (udev->product != NULL) - strlcpy(dev->name, udev->product, sizeof(dev->name)); + strscpy(dev->name, udev->product, sizeof(dev->name)); else snprintf(dev->name, sizeof(dev->name), "UVC Camera (%04x:%04x)", @@ -2124,7 +2118,7 @@ static int uvc_probe(struct usb_interface *intf, le16_to_cpu(udev->descriptor.idVendor), le16_to_cpu(udev->descriptor.idProduct)); - if (dev->quirks != quirks) { + if (dev->quirks != dev->info->quirks) { uvc_printk(KERN_INFO, "Forcing device quirks to 0x%x by module " "parameter for testing purpose.\n", dev->quirks); uvc_printk(KERN_INFO, "Please report required quirks to the " @@ -2134,11 +2128,11 @@ static int uvc_probe(struct usb_interface *intf, /* Initialize the media device and register the V4L2 device. */ #ifdef CONFIG_MEDIA_CONTROLLER dev->mdev.dev = &intf->dev; - strlcpy(dev->mdev.model, dev->name, sizeof(dev->mdev.model)); + strscpy(dev->mdev.model, dev->name, sizeof(dev->mdev.model)); if (udev->serial) - strlcpy(dev->mdev.serial, udev->serial, + strscpy(dev->mdev.serial, udev->serial, sizeof(dev->mdev.serial)); - strcpy(dev->mdev.bus_info, udev->devpath); + strscpy(dev->mdev.bus_info, udev->devpath, sizeof(dev->mdev.bus_info)); dev->mdev.hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); media_device_init(&dev->mdev); @@ -2344,7 +2338,9 @@ static const struct uvc_device_info uvc_quirk_force_y8 = { .quirks = UVC_QUIRK_FORCE_Y8, }; -#define UVC_QUIRK_INFO(q) (kernel_ulong_t)&(struct uvc_device_info){.quirks = q} +#define UVC_INFO_QUIRK(q) (kernel_ulong_t)&(struct uvc_device_info){.quirks = q} +#define UVC_INFO_META(m) (kernel_ulong_t)&(struct uvc_device_info) \ + {.meta_format = m} /* * The Logitech cameras listed below have their interface class set to @@ -2453,7 +2449,7 @@ static const struct usb_device_id uvc_ids[] = { .bInterfaceClass = USB_CLASS_VIDEO, .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_INFO(UVC_QUIRK_RESTORE_CTRLS_ON_INIT) }, + .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_RESTORE_CTRLS_ON_INIT) }, /* Chicony CNF7129 (Asus EEE 100HE) */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, @@ -2462,7 +2458,7 @@ static const struct usb_device_id uvc_ids[] = { .bInterfaceClass = USB_CLASS_VIDEO, .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_INFO(UVC_QUIRK_RESTRICT_FRAME_RATE) }, + .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_RESTRICT_FRAME_RATE) }, /* Alcor Micro AU3820 (Future Boy PC USB Webcam) */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, @@ -2525,7 +2521,7 @@ static const struct usb_device_id uvc_ids[] = { .bInterfaceClass = USB_CLASS_VIDEO, .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_INFO(UVC_QUIRK_PROBE_MINMAX + .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_PROBE_MINMAX | UVC_QUIRK_BUILTIN_ISIGHT) }, /* Apple Built-In iSight via iBridge */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE @@ -2607,7 +2603,7 @@ static const struct usb_device_id uvc_ids[] = { .bInterfaceClass = USB_CLASS_VIDEO, .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_INFO(UVC_QUIRK_PROBE_MINMAX + .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_PROBE_MINMAX | UVC_QUIRK_PROBE_DEF) }, /* IMC Networks (Medion Akoya) */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE @@ -2707,7 +2703,7 @@ static const struct usb_device_id uvc_ids[] = { .bInterfaceClass = USB_CLASS_VIDEO, .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_INFO(UVC_QUIRK_PROBE_MINMAX + .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_PROBE_MINMAX | UVC_QUIRK_PROBE_EXTRAFIELDS) }, /* Aveo Technology USB 2.0 Camera (Tasco USB Microscope) */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE @@ -2725,7 +2721,7 @@ static const struct usb_device_id uvc_ids[] = { .bInterfaceClass = USB_CLASS_VIDEO, .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_INFO(UVC_QUIRK_PROBE_EXTRAFIELDS) }, + .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_PROBE_EXTRAFIELDS) }, /* Manta MM-353 Plako */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, @@ -2771,7 +2767,7 @@ static const struct usb_device_id uvc_ids[] = { .bInterfaceClass = USB_CLASS_VIDEO, .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_INFO(UVC_QUIRK_STATUS_INTERVAL) }, + .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_STATUS_INTERVAL) }, /* MSI StarCam 370i */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, @@ -2798,7 +2794,7 @@ static const struct usb_device_id uvc_ids[] = { .bInterfaceClass = USB_CLASS_VIDEO, .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_INFO(UVC_QUIRK_PROBE_MINMAX + .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_PROBE_MINMAX | UVC_QUIRK_IGNORE_SELECTOR_UNIT) }, /* Oculus VR Positional Tracker DK2 */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE @@ -2818,6 +2814,15 @@ static const struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = (kernel_ulong_t)&uvc_quirk_force_y8 }, + /* Intel RealSense D4M */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x8086, + .idProduct = 0x0b03, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) }, /* Generic USB Video Class */ { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_UNDEFINED) }, { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_15) }, diff --git a/drivers/media/usb/uvc/uvc_entity.c b/drivers/media/usb/uvc/uvc_entity.c index 554063c07d7a..06bffdf8828b 100644 --- a/drivers/media/usb/uvc/uvc_entity.c +++ b/drivers/media/usb/uvc/uvc_entity.c @@ -79,7 +79,7 @@ static int uvc_mc_init_entity(struct uvc_video_chain *chain, if (UVC_ENTITY_TYPE(entity) != UVC_TT_STREAMING) { v4l2_subdev_init(&entity->subdev, &uvc_subdev_ops); - strlcpy(entity->subdev.name, entity->name, + strscpy(entity->subdev.name, entity->name, sizeof(entity->subdev.name)); ret = media_entity_pads_init(&entity->subdev.entity, diff --git a/drivers/media/usb/uvc/uvc_metadata.c b/drivers/media/usb/uvc/uvc_metadata.c index cd1aec19cc5b..5f535b515c23 100644 --- a/drivers/media/usb/uvc/uvc_metadata.c +++ b/drivers/media/usb/uvc/uvc_metadata.c @@ -33,8 +33,8 @@ static int uvc_meta_v4l2_querycap(struct file *file, void *fh, struct uvc_streaming *stream = video_get_drvdata(vfh->vdev); struct uvc_video_chain *chain = stream->chain; - strlcpy(cap->driver, "uvcvideo", sizeof(cap->driver)); - strlcpy(cap->card, vfh->vdev->name, sizeof(cap->card)); + strscpy(cap->driver, "uvcvideo", sizeof(cap->driver)); + strscpy(cap->card, vfh->vdev->name, sizeof(cap->card)); usb_make_path(stream->dev->udev, cap->bus_info, sizeof(cap->bus_info)); cap->capabilities = V4L2_CAP_DEVICE_CAPS | V4L2_CAP_STREAMING | chain->caps; @@ -74,7 +74,8 @@ static int uvc_meta_v4l2_try_format(struct file *file, void *fh, memset(fmt, 0, sizeof(*fmt)); - fmt->dataformat = fmeta == dev->meta_format ? fmeta : V4L2_META_FMT_UVC; + fmt->dataformat = fmeta == dev->info->meta_format + ? fmeta : V4L2_META_FMT_UVC; fmt->buffersize = UVC_METATADA_BUF_SIZE; return 0; @@ -118,14 +119,14 @@ static int uvc_meta_v4l2_enum_formats(struct file *file, void *fh, u32 index = fdesc->index; if (fdesc->type != vfh->vdev->queue->type || - index > 1U || (index && !dev->meta_format)) + index > 1U || (index && !dev->info->meta_format)) return -EINVAL; memset(fdesc, 0, sizeof(*fdesc)); fdesc->type = vfh->vdev->queue->type; fdesc->index = index; - fdesc->pixelformat = index ? dev->meta_format : V4L2_META_FMT_UVC; + fdesc->pixelformat = index ? dev->info->meta_format : V4L2_META_FMT_UVC; return 0; } diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index 18a7384b50ee..b26182ce7462 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -591,8 +591,8 @@ static int uvc_ioctl_querycap(struct file *file, void *fh, struct uvc_video_chain *chain = handle->chain; struct uvc_streaming *stream = handle->stream; - strlcpy(cap->driver, "uvcvideo", sizeof(cap->driver)); - strlcpy(cap->card, vdev->name, sizeof(cap->card)); + strscpy(cap->driver, "uvcvideo", sizeof(cap->driver)); + strscpy(cap->card, vdev->name, sizeof(cap->card)); usb_make_path(stream->dev->udev, cap->bus_info, sizeof(cap->bus_info)); cap->capabilities = V4L2_CAP_DEVICE_CAPS | V4L2_CAP_STREAMING | chain->caps; @@ -618,7 +618,7 @@ static int uvc_ioctl_enum_fmt(struct uvc_streaming *stream, fmt->flags = 0; if (format->flags & UVC_FMT_FLAG_COMPRESSED) fmt->flags |= V4L2_FMT_FLAG_COMPRESSED; - strlcpy(fmt->description, format->name, sizeof(fmt->description)); + strscpy(fmt->description, format->name, sizeof(fmt->description)); fmt->description[sizeof(fmt->description) - 1] = 0; fmt->pixelformat = format->fcc; return 0; @@ -859,7 +859,7 @@ static int uvc_ioctl_enum_input(struct file *file, void *fh, memset(input, 0, sizeof(*input)); input->index = index; - strlcpy(input->name, iterm->name, sizeof(input->name)); + strscpy(input->name, iterm->name, sizeof(input->name)); if (UVC_ENTITY_TYPE(iterm) == UVC_ITT_CAMERA) input->type = V4L2_INPUT_TYPE_CAMERA; @@ -939,7 +939,7 @@ static int uvc_ioctl_query_ext_ctrl(struct file *file, void *fh, qec->id = qc.id; qec->type = qc.type; - strlcpy(qec->name, qc.name, sizeof(qec->name)); + strscpy(qec->name, qc.name, sizeof(qec->name)); qec->minimum = qc.minimum; qec->maximum = qc.maximum; qec->step = qc.step; diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index e5f5d84f1d1d..591eae3d0b0d 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -234,7 +234,7 @@ struct uvc_control_mapping { enum v4l2_ctrl_type v4l2_type; u32 data_type; - struct uvc_menu_info *menu_info; + const struct uvc_menu_info *menu_info; u32 menu_count; u32 master_id; @@ -572,15 +572,21 @@ struct uvc_streaming { } clock; }; +struct uvc_device_info { + u32 quirks; + u32 meta_format; +}; + struct uvc_device { struct usb_device *udev; struct usb_interface *intf; unsigned long warnings; u32 quirks; - u32 meta_format; int intfnum; char name[32]; + const struct uvc_device_info *info; + struct mutex lock; /* Protects users */ unsigned int users; atomic_t nmappings; diff --git a/drivers/media/usb/zr364xx/zr364xx.c b/drivers/media/usb/zr364xx/zr364xx.c index b8886102c5ed..ab35554cbffa 100644 --- a/drivers/media/usb/zr364xx/zr364xx.c +++ b/drivers/media/usb/zr364xx/zr364xx.c @@ -702,9 +702,9 @@ static int zr364xx_vidioc_querycap(struct file *file, void *priv, { struct zr364xx_camera *cam = video_drvdata(file); - strlcpy(cap->driver, DRIVER_DESC, sizeof(cap->driver)); - strlcpy(cap->card, cam->udev->product, sizeof(cap->card)); - strlcpy(cap->bus_info, dev_name(&cam->udev->dev), + strscpy(cap->driver, DRIVER_DESC, sizeof(cap->driver)); + strscpy(cap->card, cam->udev->product, sizeof(cap->card)); + strscpy(cap->bus_info, dev_name(&cam->udev->dev), sizeof(cap->bus_info)); cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | @@ -719,7 +719,7 @@ static int zr364xx_vidioc_enum_input(struct file *file, void *priv, { if (i->index != 0) return -EINVAL; - strcpy(i->name, DRIVER_DESC " Camera"); + strscpy(i->name, DRIVER_DESC " Camera", sizeof(i->name)); i->type = V4L2_INPUT_TYPE_CAMERA; return 0; } @@ -765,7 +765,7 @@ static int zr364xx_vidioc_enum_fmt_vid_cap(struct file *file, if (f->index > 0) return -EINVAL; f->flags = V4L2_FMT_FLAG_COMPRESSED; - strcpy(f->description, formats[0].name); + strscpy(f->description, formats[0].name, sizeof(f->description)); f->pixelformat = formats[0].fourcc; return 0; } diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c index 7f858c39753c..03a340cb5a9b 100644 --- a/drivers/media/v4l2-core/tuner-core.c +++ b/drivers/media/v4l2-core/tuner-core.c @@ -94,9 +94,56 @@ static const struct v4l2_subdev_ops tuner_ops; } while (0) /* - * Internal struct used inside the driver + * Internal enums/struct used inside the driver */ +/** + * enum tuner_pad_index - tuner pad index for MEDIA_ENT_F_TUNER + * + * @TUNER_PAD_RF_INPUT: + * Radiofrequency (RF) sink pad, usually linked to a RF connector entity. + * @TUNER_PAD_OUTPUT: + * tuner video output source pad. Contains the video chrominance + * and luminance or the hole bandwidth of the signal converted to + * an Intermediate Frequency (IF) or to baseband (on zero-IF tuners). + * @TUNER_PAD_AUD_OUT: + * Tuner audio output source pad. Tuners used to decode analog TV + * signals have an extra pad for audio output. Old tuners use an + * analog stage with a saw filter for the audio IF frequency. The + * output of the pad is, in this case, the audio IF, with should be + * decoded either by the bridge chipset (that's the case of cx2388x + * chipsets) or may require an external IF sound processor, like + * msp34xx. On modern silicon tuners, the audio IF decoder is usually + * incorporated at the tuner. On such case, the output of this pad + * is an audio sampled data. + * @TUNER_NUM_PADS: + * Number of pads of the tuner. + */ +enum tuner_pad_index { + TUNER_PAD_RF_INPUT, + TUNER_PAD_OUTPUT, + TUNER_PAD_AUD_OUT, + TUNER_NUM_PADS +}; + +/** + * enum if_vid_dec_pad_index - video IF-PLL pad index + * for MEDIA_ENT_F_IF_VID_DECODER + * + * @IF_VID_DEC_PAD_IF_INPUT: + * video Intermediate Frequency (IF) sink pad + * @IF_VID_DEC_PAD_OUT: + * IF-PLL video output source pad. Contains the video chrominance + * and luminance IF signals. + * @IF_VID_DEC_PAD_NUM_PADS: + * Number of pads of the video IF-PLL. + */ +enum if_vid_dec_pad_index { + IF_VID_DEC_PAD_IF_INPUT, + IF_VID_DEC_PAD_OUT, + IF_VID_DEC_PAD_NUM_PADS +}; + struct tuner { /* device */ struct dvb_frontend fe; @@ -685,15 +732,20 @@ register_client: */ if (t->type == TUNER_TDA9887) { t->pad[IF_VID_DEC_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK; + t->pad[IF_VID_DEC_PAD_IF_INPUT].sig_type = PAD_SIGNAL_ANALOG; t->pad[IF_VID_DEC_PAD_OUT].flags = MEDIA_PAD_FL_SOURCE; + t->pad[IF_VID_DEC_PAD_OUT].sig_type = PAD_SIGNAL_ANALOG; ret = media_entity_pads_init(&t->sd.entity, IF_VID_DEC_PAD_NUM_PADS, &t->pad[0]); t->sd.entity.function = MEDIA_ENT_F_IF_VID_DECODER; } else { t->pad[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK; + t->pad[TUNER_PAD_RF_INPUT].sig_type = PAD_SIGNAL_ANALOG; t->pad[TUNER_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; + t->pad[TUNER_PAD_OUTPUT].sig_type = PAD_SIGNAL_ANALOG; t->pad[TUNER_PAD_AUD_OUT].flags = MEDIA_PAD_FL_SOURCE; + t->pad[TUNER_PAD_AUD_OUT].sig_type = PAD_SIGNAL_AUDIO; ret = media_entity_pads_init(&t->sd.entity, TUNER_NUM_PADS, &t->pad[0]); t->sd.entity.function = MEDIA_ENT_F_TUNER; diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c index 2b08d03b251d..a6d91370838d 100644 --- a/drivers/media/v4l2-core/v4l2-async.c +++ b/drivers/media/v4l2-core/v4l2-async.c @@ -57,6 +57,7 @@ static bool match_i2c(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd) { #if IS_ENABLED(CONFIG_I2C) struct i2c_client *client = i2c_verify_client(sd->dev); + return client && asd->match.i2c.adapter_id == client->adapter->nr && asd->match.i2c.address == client->addr; @@ -89,10 +90,11 @@ static LIST_HEAD(subdev_list); static LIST_HEAD(notifier_list); static DEFINE_MUTEX(list_lock); -static struct v4l2_async_subdev *v4l2_async_find_match( - struct v4l2_async_notifier *notifier, struct v4l2_subdev *sd) +static struct v4l2_async_subdev * +v4l2_async_find_match(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *sd) { - bool (*match)(struct v4l2_subdev *, struct v4l2_async_subdev *); + bool (*match)(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd); struct v4l2_async_subdev *asd; list_for_each_entry(asd, ¬ifier->waiting, list) { @@ -124,9 +126,34 @@ static struct v4l2_async_subdev *v4l2_async_find_match( return NULL; } +/* Compare two async sub-device descriptors for equivalence */ +static bool asd_equal(struct v4l2_async_subdev *asd_x, + struct v4l2_async_subdev *asd_y) +{ + if (asd_x->match_type != asd_y->match_type) + return false; + + switch (asd_x->match_type) { + case V4L2_ASYNC_MATCH_DEVNAME: + return strcmp(asd_x->match.device_name, + asd_y->match.device_name) == 0; + case V4L2_ASYNC_MATCH_I2C: + return asd_x->match.i2c.adapter_id == + asd_y->match.i2c.adapter_id && + asd_x->match.i2c.address == + asd_y->match.i2c.address; + case V4L2_ASYNC_MATCH_FWNODE: + return asd_x->match.fwnode == asd_y->match.fwnode; + default: + break; + } + + return false; +} + /* Find the sub-device notifier registered by a sub-device driver. */ -static struct v4l2_async_notifier *v4l2_async_find_subdev_notifier( - struct v4l2_subdev *sd) +static struct v4l2_async_notifier * +v4l2_async_find_subdev_notifier(struct v4l2_subdev *sd) { struct v4l2_async_notifier *n; @@ -138,8 +165,8 @@ static struct v4l2_async_notifier *v4l2_async_find_subdev_notifier( } /* Get v4l2_device related to the notifier if one can be found. */ -static struct v4l2_device *v4l2_async_notifier_find_v4l2_dev( - struct v4l2_async_notifier *notifier) +static struct v4l2_device * +v4l2_async_notifier_find_v4l2_dev(struct v4l2_async_notifier *notifier) { while (notifier->parent) notifier = notifier->parent; @@ -150,8 +177,8 @@ static struct v4l2_device *v4l2_async_notifier_find_v4l2_dev( /* * Return true if all child sub-device notifiers are complete, false otherwise. */ -static bool v4l2_async_notifier_can_complete( - struct v4l2_async_notifier *notifier) +static bool +v4l2_async_notifier_can_complete(struct v4l2_async_notifier *notifier) { struct v4l2_subdev *sd; @@ -174,8 +201,8 @@ static bool v4l2_async_notifier_can_complete( * Complete the master notifier if possible. This is done when all async * sub-devices have been bound; v4l2_device is also available then. */ -static int v4l2_async_notifier_try_complete( - struct v4l2_async_notifier *notifier) +static int +v4l2_async_notifier_try_complete(struct v4l2_async_notifier *notifier) { /* Quick check whether there are still more sub-devices here. */ if (!list_empty(¬ifier->waiting)) @@ -196,8 +223,8 @@ static int v4l2_async_notifier_try_complete( return v4l2_async_notifier_call_complete(notifier); } -static int v4l2_async_notifier_try_all_subdevs( - struct v4l2_async_notifier *notifier); +static int +v4l2_async_notifier_try_all_subdevs(struct v4l2_async_notifier *notifier); static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier, struct v4l2_device *v4l2_dev, @@ -243,8 +270,8 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier, } /* Test all async sub-devices in a notifier for a match. */ -static int v4l2_async_notifier_try_all_subdevs( - struct v4l2_async_notifier *notifier) +static int +v4l2_async_notifier_try_all_subdevs(struct v4l2_async_notifier *notifier) { struct v4l2_device *v4l2_dev = v4l2_async_notifier_find_v4l2_dev(notifier); @@ -281,14 +308,17 @@ again: static void v4l2_async_cleanup(struct v4l2_subdev *sd) { v4l2_device_unregister_subdev(sd); - /* Subdevice driver will reprobe and put the subdev back onto the list */ + /* + * Subdevice driver will reprobe and put the subdev back + * onto the list + */ list_del_init(&sd->async_list); sd->asd = NULL; } /* Unbind all sub-devices in the notifier tree. */ -static void v4l2_async_notifier_unbind_all_subdevs( - struct v4l2_async_notifier *notifier) +static void +v4l2_async_notifier_unbind_all_subdevs(struct v4l2_async_notifier *notifier) { struct v4l2_subdev *sd, *tmp; @@ -308,29 +338,23 @@ static void v4l2_async_notifier_unbind_all_subdevs( notifier->parent = NULL; } -/* See if an fwnode can be found in a notifier's lists. */ -static bool __v4l2_async_notifier_fwnode_has_async_subdev( - struct v4l2_async_notifier *notifier, struct fwnode_handle *fwnode) +/* See if an async sub-device can be found in a notifier's lists. */ +static bool +__v4l2_async_notifier_has_async_subdev(struct v4l2_async_notifier *notifier, + struct v4l2_async_subdev *asd) { - struct v4l2_async_subdev *asd; + struct v4l2_async_subdev *asd_y; struct v4l2_subdev *sd; - list_for_each_entry(asd, ¬ifier->waiting, list) { - if (asd->match_type != V4L2_ASYNC_MATCH_FWNODE) - continue; - - if (asd->match.fwnode == fwnode) + list_for_each_entry(asd_y, ¬ifier->waiting, list) + if (asd_equal(asd, asd_y)) return true; - } list_for_each_entry(sd, ¬ifier->done, async_list) { if (WARN_ON(!sd->asd)) continue; - if (sd->asd->match_type != V4L2_ASYNC_MATCH_FWNODE) - continue; - - if (sd->asd->match.fwnode == fwnode) + if (asd_equal(asd, sd->asd)) return true; } @@ -338,76 +362,91 @@ static bool __v4l2_async_notifier_fwnode_has_async_subdev( } /* - * Find out whether an async sub-device was set up for an fwnode already or + * Find out whether an async sub-device was set up already or * whether it exists in a given notifier before @this_index. + * If @this_index < 0, search the notifier's entire @asd_list. */ -static bool v4l2_async_notifier_fwnode_has_async_subdev( - struct v4l2_async_notifier *notifier, struct fwnode_handle *fwnode, - unsigned int this_index) +static bool +v4l2_async_notifier_has_async_subdev(struct v4l2_async_notifier *notifier, + struct v4l2_async_subdev *asd, + int this_index) { - unsigned int j; + struct v4l2_async_subdev *asd_y; + int j = 0; lockdep_assert_held(&list_lock); - /* Check that an fwnode is not being added more than once. */ - for (j = 0; j < this_index; j++) { - struct v4l2_async_subdev *asd = notifier->subdevs[this_index]; - struct v4l2_async_subdev *other_asd = notifier->subdevs[j]; - - if (other_asd->match_type == V4L2_ASYNC_MATCH_FWNODE && - asd->match.fwnode == - other_asd->match.fwnode) + /* Check that an asd is not being added more than once. */ + list_for_each_entry(asd_y, ¬ifier->asd_list, asd_list) { + if (this_index >= 0 && j++ >= this_index) + break; + if (asd_equal(asd, asd_y)) return true; } - /* Check than an fwnode did not exist in other notifiers. */ + /* Check that an asd does not exist in other notifiers. */ list_for_each_entry(notifier, ¬ifier_list, list) - if (__v4l2_async_notifier_fwnode_has_async_subdev( - notifier, fwnode)) + if (__v4l2_async_notifier_has_async_subdev(notifier, asd)) return true; return false; } -static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier) +static int v4l2_async_notifier_asd_valid(struct v4l2_async_notifier *notifier, + struct v4l2_async_subdev *asd, + int this_index) { struct device *dev = notifier->v4l2_dev ? notifier->v4l2_dev->dev : NULL; - struct v4l2_async_subdev *asd; - int ret; - int i; - if (notifier->num_subdevs > V4L2_MAX_SUBDEVS) + if (!asd) + return -EINVAL; + + switch (asd->match_type) { + case V4L2_ASYNC_MATCH_CUSTOM: + case V4L2_ASYNC_MATCH_DEVNAME: + case V4L2_ASYNC_MATCH_I2C: + case V4L2_ASYNC_MATCH_FWNODE: + if (v4l2_async_notifier_has_async_subdev(notifier, asd, + this_index)) { + dev_dbg(dev, "subdev descriptor already listed in this or other notifiers\n"); + return -EEXIST; + } + break; + default: + dev_err(dev, "Invalid match type %u on %p\n", + asd->match_type, asd); return -EINVAL; + } + + return 0; +} + +void v4l2_async_notifier_init(struct v4l2_async_notifier *notifier) +{ + mutex_lock(&list_lock); + + INIT_LIST_HEAD(¬ifier->asd_list); + + mutex_unlock(&list_lock); +} +EXPORT_SYMBOL(v4l2_async_notifier_init); + +static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier) +{ + struct v4l2_async_subdev *asd; + int ret, i = 0; INIT_LIST_HEAD(¬ifier->waiting); INIT_LIST_HEAD(¬ifier->done); mutex_lock(&list_lock); - for (i = 0; i < notifier->num_subdevs; i++) { - asd = notifier->subdevs[i]; - - switch (asd->match_type) { - case V4L2_ASYNC_MATCH_CUSTOM: - case V4L2_ASYNC_MATCH_DEVNAME: - case V4L2_ASYNC_MATCH_I2C: - break; - case V4L2_ASYNC_MATCH_FWNODE: - if (v4l2_async_notifier_fwnode_has_async_subdev( - notifier, asd->match.fwnode, i)) { - dev_err(dev, - "fwnode has already been registered or in notifier's subdev list\n"); - ret = -EEXIST; - goto err_unlock; - } - break; - default: - dev_err(dev, "Invalid match type %u on %p\n", - asd->match_type, asd); - ret = -EINVAL; + list_for_each_entry(asd, ¬ifier->asd_list, asd_list) { + ret = v4l2_async_notifier_asd_valid(notifier, asd, i++); + if (ret) goto err_unlock; - } + list_add_tail(&asd->list, ¬ifier->waiting); } @@ -474,8 +513,8 @@ int v4l2_async_subdev_notifier_register(struct v4l2_subdev *sd, } EXPORT_SYMBOL(v4l2_async_subdev_notifier_register); -static void __v4l2_async_notifier_unregister( - struct v4l2_async_notifier *notifier) +static void +__v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier) { if (!notifier || (!notifier->v4l2_dev && !notifier->sd)) return; @@ -498,36 +537,132 @@ void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier) } EXPORT_SYMBOL(v4l2_async_notifier_unregister); -void v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier) +static void __v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier) { - unsigned int i; + struct v4l2_async_subdev *asd, *tmp; - if (!notifier || !notifier->max_subdevs) + if (!notifier) return; - for (i = 0; i < notifier->num_subdevs; i++) { - struct v4l2_async_subdev *asd = notifier->subdevs[i]; - + list_for_each_entry_safe(asd, tmp, ¬ifier->asd_list, asd_list) { switch (asd->match_type) { case V4L2_ASYNC_MATCH_FWNODE: fwnode_handle_put(asd->match.fwnode); break; default: - WARN_ON_ONCE(true); break; } + list_del(&asd->asd_list); kfree(asd); } +} - notifier->max_subdevs = 0; - notifier->num_subdevs = 0; +void v4l2_async_notifier_cleanup(struct v4l2_async_notifier *notifier) +{ + mutex_lock(&list_lock); + + __v4l2_async_notifier_cleanup(notifier); - kvfree(notifier->subdevs); - notifier->subdevs = NULL; + mutex_unlock(&list_lock); } EXPORT_SYMBOL_GPL(v4l2_async_notifier_cleanup); +int v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier, + struct v4l2_async_subdev *asd) +{ + int ret; + + mutex_lock(&list_lock); + + ret = v4l2_async_notifier_asd_valid(notifier, asd, -1); + if (ret) + goto unlock; + + list_add_tail(&asd->asd_list, ¬ifier->asd_list); + +unlock: + mutex_unlock(&list_lock); + return ret; +} +EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_subdev); + +struct v4l2_async_subdev * +v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier, + struct fwnode_handle *fwnode, + unsigned int asd_struct_size) +{ + struct v4l2_async_subdev *asd; + int ret; + + asd = kzalloc(asd_struct_size, GFP_KERNEL); + if (!asd) + return ERR_PTR(-ENOMEM); + + asd->match_type = V4L2_ASYNC_MATCH_FWNODE; + asd->match.fwnode = fwnode; + + ret = v4l2_async_notifier_add_subdev(notifier, asd); + if (ret) { + kfree(asd); + return ERR_PTR(ret); + } + + return asd; +} +EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_fwnode_subdev); + +struct v4l2_async_subdev * +v4l2_async_notifier_add_i2c_subdev(struct v4l2_async_notifier *notifier, + int adapter_id, unsigned short address, + unsigned int asd_struct_size) +{ + struct v4l2_async_subdev *asd; + int ret; + + asd = kzalloc(asd_struct_size, GFP_KERNEL); + if (!asd) + return ERR_PTR(-ENOMEM); + + asd->match_type = V4L2_ASYNC_MATCH_I2C; + asd->match.i2c.adapter_id = adapter_id; + asd->match.i2c.address = address; + + ret = v4l2_async_notifier_add_subdev(notifier, asd); + if (ret) { + kfree(asd); + return ERR_PTR(ret); + } + + return asd; +} +EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_i2c_subdev); + +struct v4l2_async_subdev * +v4l2_async_notifier_add_devname_subdev(struct v4l2_async_notifier *notifier, + const char *device_name, + unsigned int asd_struct_size) +{ + struct v4l2_async_subdev *asd; + int ret; + + asd = kzalloc(asd_struct_size, GFP_KERNEL); + if (!asd) + return ERR_PTR(-ENOMEM); + + asd->match_type = V4L2_ASYNC_MATCH_DEVNAME; + asd->match.device_name = device_name; + + ret = v4l2_async_notifier_add_subdev(notifier, asd); + if (ret) { + kfree(asd); + return ERR_PTR(ret); + } + + return asd; +} +EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_devname_subdev); + int v4l2_async_register_subdev(struct v4l2_subdev *sd) { struct v4l2_async_notifier *subdev_notifier; @@ -601,7 +736,7 @@ void v4l2_async_unregister_subdev(struct v4l2_subdev *sd) mutex_lock(&list_lock); __v4l2_async_notifier_unregister(sd->subdev_notifier); - v4l2_async_notifier_cleanup(sd->subdev_notifier); + __v4l2_async_notifier_cleanup(sd->subdev_notifier); kfree(sd->subdev_notifier); sd->subdev_notifier = NULL; diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c index b518b92d6d96..50763fb42a1b 100644 --- a/drivers/media/v4l2-core/v4l2-common.c +++ b/drivers/media/v4l2-core/v4l2-common.c @@ -100,7 +100,7 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 _min, s32 _max, s32 _ qctrl->step = step; qctrl->default_value = def; qctrl->reserved[0] = qctrl->reserved[1] = 0; - strlcpy(qctrl->name, name, sizeof(qctrl->name)); + strscpy(qctrl->name, name, sizeof(qctrl->name)); return 0; } EXPORT_SYMBOL(v4l2_ctrl_query_fill); @@ -109,6 +109,19 @@ EXPORT_SYMBOL(v4l2_ctrl_query_fill); #if IS_ENABLED(CONFIG_I2C) +void v4l2_i2c_subdev_set_name(struct v4l2_subdev *sd, struct i2c_client *client, + const char *devname, const char *postfix) +{ + if (!devname) + devname = client->dev.driver->name; + if (!postfix) + postfix = ""; + + snprintf(sd->name, sizeof(sd->name), "%s%s %d-%04x", devname, postfix, + i2c_adapter_id(client->adapter), client->addr); +} +EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_set_name); + void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client, const struct v4l2_subdev_ops *ops) { @@ -120,10 +133,7 @@ void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client, /* i2c_client and v4l2_subdev point to one another */ v4l2_set_subdevdata(sd, client); i2c_set_clientdata(client, sd); - /* initialize name */ - snprintf(sd->name, sizeof(sd->name), "%s %d-%04x", - client->dev.driver->name, i2c_adapter_id(client->adapter), - client->addr); + v4l2_i2c_subdev_set_name(sd, client, NULL, NULL); } EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_init); @@ -186,7 +196,7 @@ struct v4l2_subdev *v4l2_i2c_new_subdev(struct v4l2_device *v4l2_dev, /* Setup the i2c board info with the device type and the device address. */ memset(&info, 0, sizeof(info)); - strlcpy(info.type, client_type, sizeof(info.type)); + strscpy(info.type, client_type, sizeof(info.type)); info.addr = addr; return v4l2_i2c_new_subdev_board(v4l2_dev, adapter, &info, probe_addrs); @@ -255,7 +265,8 @@ void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi, v4l2_set_subdevdata(sd, spi); spi_set_drvdata(spi, sd); /* initialize name */ - strlcpy(sd->name, spi->dev.driver->name, sizeof(sd->name)); + snprintf(sd->name, sizeof(sd->name), "%s %s", + spi->dev.driver->name, dev_name(&spi->dev)); } EXPORT_SYMBOL_GPL(v4l2_spi_subdev_init); diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index 599c1cbff3b9..4c0ecf29d278 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -2511,20 +2511,15 @@ void v4l2_ctrl_activate(struct v4l2_ctrl *ctrl, bool active) } EXPORT_SYMBOL(v4l2_ctrl_activate); -/* Grab/ungrab a control. - Typically used when streaming starts and you want to grab controls, - preventing the user from changing them. - - Just call this and the framework will block any attempts to change - these controls. */ -void v4l2_ctrl_grab(struct v4l2_ctrl *ctrl, bool grabbed) +void __v4l2_ctrl_grab(struct v4l2_ctrl *ctrl, bool grabbed) { bool old; if (ctrl == NULL) return; - v4l2_ctrl_lock(ctrl); + lockdep_assert_held(ctrl->handler->lock); + if (grabbed) /* set V4L2_CTRL_FLAG_GRABBED */ old = test_and_set_bit(1, &ctrl->flags); @@ -2533,9 +2528,8 @@ void v4l2_ctrl_grab(struct v4l2_ctrl *ctrl, bool grabbed) old = test_and_clear_bit(1, &ctrl->flags); if (old != grabbed) send_event(NULL, ctrl, V4L2_EVENT_CTRL_CH_FLAGS); - v4l2_ctrl_unlock(ctrl); } -EXPORT_SYMBOL(v4l2_ctrl_grab); +EXPORT_SYMBOL(__v4l2_ctrl_grab); /* Log the control name and value */ static void log_ctrl(const struct v4l2_ctrl *ctrl, @@ -2722,7 +2716,7 @@ int v4l2_query_ext_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_query_ext_ctr qc->id = id; else qc->id = ctrl->id; - strlcpy(qc->name, ctrl->name, sizeof(qc->name)); + strscpy(qc->name, ctrl->name, sizeof(qc->name)); qc->flags = user_flags(ctrl); qc->type = ctrl->type; qc->elem_size = ctrl->elem_size; @@ -2754,7 +2748,7 @@ int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc) qc->id = qec.id; qc->type = qec.type; qc->flags = qec.flags; - strlcpy(qc->name, qec.name, sizeof(qc->name)); + strscpy(qc->name, qec.name, sizeof(qc->name)); switch (qc->type) { case V4L2_CTRL_TYPE_INTEGER: case V4L2_CTRL_TYPE_BOOLEAN: @@ -2813,7 +2807,7 @@ int v4l2_querymenu(struct v4l2_ctrl_handler *hdl, struct v4l2_querymenu *qm) if (ctrl->type == V4L2_CTRL_TYPE_MENU) { if (ctrl->qmenu[i] == NULL || ctrl->qmenu[i][0] == '\0') return -EINVAL; - strlcpy(qm->name, ctrl->qmenu[i], sizeof(qm->name)); + strscpy(qm->name, ctrl->qmenu[i], sizeof(qm->name)); } else { qm->value = ctrl->qmenu_int[i]; } @@ -3442,7 +3436,7 @@ int __v4l2_ctrl_s_ctrl_string(struct v4l2_ctrl *ctrl, const char *s) /* It's a driver bug if this happens. */ WARN_ON(ctrl->type != V4L2_CTRL_TYPE_STRING); - strlcpy(ctrl->p_new.p_char, s, ctrl->maximum + 1); + strscpy(ctrl->p_new.p_char, s, ctrl->maximum + 1); return set_ctrl(NULL, ctrl, 0); } EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_string); diff --git a/drivers/media/v4l2-core/v4l2-device.c b/drivers/media/v4l2-core/v4l2-device.c index 3940e55c72f1..098562901f25 100644 --- a/drivers/media/v4l2-core/v4l2-device.c +++ b/drivers/media/v4l2-core/v4l2-device.c @@ -245,7 +245,7 @@ int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev) } video_set_drvdata(vdev, sd); - strlcpy(vdev->name, sd->name, sizeof(vdev->name)); + strscpy(vdev->name, sd->name, sizeof(vdev->name)); vdev->v4l2_dev = v4l2_dev; vdev->fops = &v4l2_subdev_fops; vdev->release = v4l2_device_release_subdev_node; diff --git a/drivers/media/v4l2-core/v4l2-dv-timings.c b/drivers/media/v4l2-core/v4l2-dv-timings.c index c81faea96fba..4f23e939ead0 100644 --- a/drivers/media/v4l2-core/v4l2-dv-timings.c +++ b/drivers/media/v4l2-core/v4l2-dv-timings.c @@ -15,6 +15,7 @@ #include <media/v4l2-dv-timings.h> #include <linux/math64.h> #include <linux/hdmi.h> +#include <media/cec.h> MODULE_AUTHOR("Hans Verkuil"); MODULE_DESCRIPTION("V4L2 DV Timings Helper Functions"); @@ -373,6 +374,45 @@ struct v4l2_fract v4l2_dv_timings_aspect_ratio(const struct v4l2_dv_timings *t) } EXPORT_SYMBOL_GPL(v4l2_dv_timings_aspect_ratio); +/** v4l2_calc_timeperframe - helper function to calculate timeperframe based + * v4l2_dv_timings fields. + * @t - Timings for the video mode. + * + * Calculates the expected timeperframe using the pixel clock value and + * horizontal/vertical measures. This means that v4l2_dv_timings structure + * must be correctly and fully filled. + */ +struct v4l2_fract v4l2_calc_timeperframe(const struct v4l2_dv_timings *t) +{ + const struct v4l2_bt_timings *bt = &t->bt; + struct v4l2_fract fps_fract = { 1, 1 }; + unsigned long n, d; + u32 htot, vtot, fps; + u64 pclk; + + if (t->type != V4L2_DV_BT_656_1120) + return fps_fract; + + htot = V4L2_DV_BT_FRAME_WIDTH(bt); + vtot = V4L2_DV_BT_FRAME_HEIGHT(bt); + pclk = bt->pixelclock; + + if ((bt->flags & V4L2_DV_FL_CAN_DETECT_REDUCED_FPS) && + (bt->flags & V4L2_DV_FL_REDUCED_FPS)) + pclk = div_u64(pclk * 1000ULL, 1001); + + fps = (htot * vtot) > 0 ? div_u64((100 * pclk), (htot * vtot)) : 0; + if (!fps) + return fps_fract; + + rational_best_approximation(fps, 100, fps, 100, &n, &d); + + fps_fract.numerator = d; + fps_fract.denominator = n; + return fps_fract; +} +EXPORT_SYMBOL_GPL(v4l2_calc_timeperframe); + /* * CVT defines * Based on Coordinated Video Timings Standard @@ -837,9 +877,9 @@ v4l2_hdmi_rx_colorimetry(const struct hdmi_avi_infoframe *avi, switch (avi->colorimetry) { case HDMI_COLORIMETRY_EXTENDED: switch (avi->extended_colorimetry) { - case HDMI_EXTENDED_COLORIMETRY_ADOBE_RGB: - c.colorspace = V4L2_COLORSPACE_ADOBERGB; - c.xfer_func = V4L2_XFER_FUNC_ADOBERGB; + case HDMI_EXTENDED_COLORIMETRY_OPRGB: + c.colorspace = V4L2_COLORSPACE_OPRGB; + c.xfer_func = V4L2_XFER_FUNC_OPRGB; break; case HDMI_EXTENDED_COLORIMETRY_BT2020: c.colorspace = V4L2_COLORSPACE_BT2020; @@ -908,10 +948,10 @@ v4l2_hdmi_rx_colorimetry(const struct hdmi_avi_infoframe *avi, c.ycbcr_enc = V4L2_YCBCR_ENC_601; c.xfer_func = V4L2_XFER_FUNC_SRGB; break; - case HDMI_EXTENDED_COLORIMETRY_ADOBE_YCC_601: - c.colorspace = V4L2_COLORSPACE_ADOBERGB; + case HDMI_EXTENDED_COLORIMETRY_OPYCC_601: + c.colorspace = V4L2_COLORSPACE_OPRGB; c.ycbcr_enc = V4L2_YCBCR_ENC_601; - c.xfer_func = V4L2_XFER_FUNC_ADOBERGB; + c.xfer_func = V4L2_XFER_FUNC_OPRGB; break; case HDMI_EXTENDED_COLORIMETRY_BT2020: c.colorspace = V4L2_COLORSPACE_BT2020; @@ -942,3 +982,153 @@ v4l2_hdmi_rx_colorimetry(const struct hdmi_avi_infoframe *avi, return c; } EXPORT_SYMBOL_GPL(v4l2_hdmi_rx_colorimetry); + +/** + * v4l2_get_edid_phys_addr() - find and return the physical address + * + * @edid: pointer to the EDID data + * @size: size in bytes of the EDID data + * @offset: If not %NULL then the location of the physical address + * bytes in the EDID will be returned here. This is set to 0 + * if there is no physical address found. + * + * Return: the physical address or CEC_PHYS_ADDR_INVALID if there is none. + */ +u16 v4l2_get_edid_phys_addr(const u8 *edid, unsigned int size, + unsigned int *offset) +{ + unsigned int loc = cec_get_edid_spa_location(edid, size); + + if (offset) + *offset = loc; + if (loc == 0) + return CEC_PHYS_ADDR_INVALID; + return (edid[loc] << 8) | edid[loc + 1]; +} +EXPORT_SYMBOL_GPL(v4l2_get_edid_phys_addr); + +/** + * v4l2_set_edid_phys_addr() - find and set the physical address + * + * @edid: pointer to the EDID data + * @size: size in bytes of the EDID data + * @phys_addr: the new physical address + * + * This function finds the location of the physical address in the EDID + * and fills in the given physical address and updates the checksum + * at the end of the EDID block. It does nothing if the EDID doesn't + * contain a physical address. + */ +void v4l2_set_edid_phys_addr(u8 *edid, unsigned int size, u16 phys_addr) +{ + unsigned int loc = cec_get_edid_spa_location(edid, size); + u8 sum = 0; + unsigned int i; + + if (loc == 0) + return; + edid[loc] = phys_addr >> 8; + edid[loc + 1] = phys_addr & 0xff; + loc &= ~0x7f; + + /* update the checksum */ + for (i = loc; i < loc + 127; i++) + sum += edid[i]; + edid[i] = 256 - sum; +} +EXPORT_SYMBOL_GPL(v4l2_set_edid_phys_addr); + +/** + * v4l2_phys_addr_for_input() - calculate the PA for an input + * + * @phys_addr: the physical address of the parent + * @input: the number of the input port, must be between 1 and 15 + * + * This function calculates a new physical address based on the input + * port number. For example: + * + * PA = 0.0.0.0 and input = 2 becomes 2.0.0.0 + * + * PA = 3.0.0.0 and input = 1 becomes 3.1.0.0 + * + * PA = 3.2.1.0 and input = 5 becomes 3.2.1.5 + * + * PA = 3.2.1.3 and input = 5 becomes f.f.f.f since it maxed out the depth. + * + * Return: the new physical address or CEC_PHYS_ADDR_INVALID. + */ +u16 v4l2_phys_addr_for_input(u16 phys_addr, u8 input) +{ + /* Check if input is sane */ + if (WARN_ON(input == 0 || input > 0xf)) + return CEC_PHYS_ADDR_INVALID; + + if (phys_addr == 0) + return input << 12; + + if ((phys_addr & 0x0fff) == 0) + return phys_addr | (input << 8); + + if ((phys_addr & 0x00ff) == 0) + return phys_addr | (input << 4); + + if ((phys_addr & 0x000f) == 0) + return phys_addr | input; + + /* + * All nibbles are used so no valid physical addresses can be assigned + * to the input. + */ + return CEC_PHYS_ADDR_INVALID; +} +EXPORT_SYMBOL_GPL(v4l2_phys_addr_for_input); + +/** + * v4l2_phys_addr_validate() - validate a physical address from an EDID + * + * @phys_addr: the physical address to validate + * @parent: if not %NULL, then this is filled with the parents PA. + * @port: if not %NULL, then this is filled with the input port. + * + * This validates a physical address as read from an EDID. If the + * PA is invalid (such as 1.0.1.0 since '0' is only allowed at the end), + * then it will return -EINVAL. + * + * The parent PA is passed into %parent and the input port is passed into + * %port. For example: + * + * PA = 0.0.0.0: has parent 0.0.0.0 and input port 0. + * + * PA = 1.0.0.0: has parent 0.0.0.0 and input port 1. + * + * PA = 3.2.0.0: has parent 3.0.0.0 and input port 2. + * + * PA = f.f.f.f: has parent f.f.f.f and input port 0. + * + * Return: 0 if the PA is valid, -EINVAL if not. + */ +int v4l2_phys_addr_validate(u16 phys_addr, u16 *parent, u16 *port) +{ + int i; + + if (parent) + *parent = phys_addr; + if (port) + *port = 0; + if (phys_addr == CEC_PHYS_ADDR_INVALID) + return 0; + for (i = 0; i < 16; i += 4) + if (phys_addr & (0xf << i)) + break; + if (i == 16) + return 0; + if (parent) + *parent = phys_addr & (0xfff0 << i); + if (port) + *port = (phys_addr >> i) & 0xf; + for (i += 4; i < 16; i += 4) + if ((phys_addr & (0xf << i)) == 0) + return -EINVAL; + return 0; +} +EXPORT_SYMBOL_GPL(v4l2_phys_addr_validate); diff --git a/drivers/media/v4l2-core/v4l2-flash-led-class.c b/drivers/media/v4l2-core/v4l2-flash-led-class.c index 215b4804ada2..1697932af5ea 100644 --- a/drivers/media/v4l2-core/v4l2-flash-led-class.c +++ b/drivers/media/v4l2-core/v4l2-flash-led-class.c @@ -640,7 +640,7 @@ static struct v4l2_flash *__v4l2_flash_init( v4l2_subdev_init(sd, &v4l2_flash_subdev_ops); sd->internal_ops = &v4l2_flash_subdev_internal_ops; sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - strlcpy(sd->name, config->dev_name, sizeof(sd->name)); + strscpy(sd->name, config->dev_name, sizeof(sd->name)); ret = media_entity_pads_init(&sd->entity, 0, NULL); if (ret < 0) diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c index 169bdbb1f61a..218f0da0ce76 100644 --- a/drivers/media/v4l2-core/v4l2-fwnode.c +++ b/drivers/media/v4l2-core/v4l2-fwnode.c @@ -36,194 +36,469 @@ enum v4l2_fwnode_bus_type { V4L2_FWNODE_BUS_TYPE_CSI2_CPHY, V4L2_FWNODE_BUS_TYPE_CSI1, V4L2_FWNODE_BUS_TYPE_CCP2, + V4L2_FWNODE_BUS_TYPE_CSI2_DPHY, + V4L2_FWNODE_BUS_TYPE_PARALLEL, + V4L2_FWNODE_BUS_TYPE_BT656, NR_OF_V4L2_FWNODE_BUS_TYPE, }; +static const struct v4l2_fwnode_bus_conv { + enum v4l2_fwnode_bus_type fwnode_bus_type; + enum v4l2_mbus_type mbus_type; + const char *name; +} busses[] = { + { + V4L2_FWNODE_BUS_TYPE_GUESS, + V4L2_MBUS_UNKNOWN, + "not specified", + }, { + V4L2_FWNODE_BUS_TYPE_CSI2_CPHY, + V4L2_MBUS_CSI2_CPHY, + "MIPI CSI-2 C-PHY", + }, { + V4L2_FWNODE_BUS_TYPE_CSI1, + V4L2_MBUS_CSI1, + "MIPI CSI-1", + }, { + V4L2_FWNODE_BUS_TYPE_CCP2, + V4L2_MBUS_CCP2, + "compact camera port 2", + }, { + V4L2_FWNODE_BUS_TYPE_CSI2_DPHY, + V4L2_MBUS_CSI2_DPHY, + "MIPI CSI-2 D-PHY", + }, { + V4L2_FWNODE_BUS_TYPE_PARALLEL, + V4L2_MBUS_PARALLEL, + "parallel", + }, { + V4L2_FWNODE_BUS_TYPE_BT656, + V4L2_MBUS_BT656, + "Bt.656", + } +}; + +static const struct v4l2_fwnode_bus_conv * +get_v4l2_fwnode_bus_conv_by_fwnode_bus(enum v4l2_fwnode_bus_type type) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(busses); i++) + if (busses[i].fwnode_bus_type == type) + return &busses[i]; + + return NULL; +} + +static enum v4l2_mbus_type +v4l2_fwnode_bus_type_to_mbus(enum v4l2_fwnode_bus_type type) +{ + const struct v4l2_fwnode_bus_conv *conv = + get_v4l2_fwnode_bus_conv_by_fwnode_bus(type); + + return conv ? conv->mbus_type : V4L2_MBUS_UNKNOWN; +} + +static const char * +v4l2_fwnode_bus_type_to_string(enum v4l2_fwnode_bus_type type) +{ + const struct v4l2_fwnode_bus_conv *conv = + get_v4l2_fwnode_bus_conv_by_fwnode_bus(type); + + return conv ? conv->name : "not found"; +} + +static const struct v4l2_fwnode_bus_conv * +get_v4l2_fwnode_bus_conv_by_mbus(enum v4l2_mbus_type type) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(busses); i++) + if (busses[i].mbus_type == type) + return &busses[i]; + + return NULL; +} + +static const char * +v4l2_fwnode_mbus_type_to_string(enum v4l2_mbus_type type) +{ + const struct v4l2_fwnode_bus_conv *conv = + get_v4l2_fwnode_bus_conv_by_mbus(type); + + return conv ? conv->name : "not found"; +} + static int v4l2_fwnode_endpoint_parse_csi2_bus(struct fwnode_handle *fwnode, - struct v4l2_fwnode_endpoint *vep) + struct v4l2_fwnode_endpoint *vep, + enum v4l2_mbus_type bus_type) { struct v4l2_fwnode_bus_mipi_csi2 *bus = &vep->bus.mipi_csi2; - bool have_clk_lane = false; + bool have_clk_lane = false, have_data_lanes = false, + have_lane_polarities = false; unsigned int flags = 0, lanes_used = 0; + u32 array[1 + V4L2_FWNODE_CSI2_MAX_DATA_LANES]; + u32 clock_lane = 0; + unsigned int num_data_lanes = 0; + bool use_default_lane_mapping = false; unsigned int i; u32 v; int rval; + if (bus_type == V4L2_MBUS_CSI2_DPHY || + bus_type == V4L2_MBUS_CSI2_CPHY) { + use_default_lane_mapping = true; + + num_data_lanes = min_t(u32, bus->num_data_lanes, + V4L2_FWNODE_CSI2_MAX_DATA_LANES); + + clock_lane = bus->clock_lane; + if (clock_lane) + use_default_lane_mapping = false; + + for (i = 0; i < num_data_lanes; i++) { + array[i] = bus->data_lanes[i]; + if (array[i]) + use_default_lane_mapping = false; + } + + if (use_default_lane_mapping) + pr_debug("using default lane mapping\n"); + } + rval = fwnode_property_read_u32_array(fwnode, "data-lanes", NULL, 0); if (rval > 0) { - u32 array[1 + V4L2_FWNODE_CSI2_MAX_DATA_LANES]; - - bus->num_data_lanes = + num_data_lanes = min_t(int, V4L2_FWNODE_CSI2_MAX_DATA_LANES, rval); fwnode_property_read_u32_array(fwnode, "data-lanes", array, - bus->num_data_lanes); + num_data_lanes); - for (i = 0; i < bus->num_data_lanes; i++) { - if (lanes_used & BIT(array[i])) - pr_warn("duplicated lane %u in data-lanes\n", - array[i]); - lanes_used |= BIT(array[i]); + have_data_lanes = true; + } - bus->data_lanes[i] = array[i]; + for (i = 0; i < num_data_lanes; i++) { + if (lanes_used & BIT(array[i])) { + if (have_data_lanes || !use_default_lane_mapping) + pr_warn("duplicated lane %u in data-lanes, using defaults\n", + array[i]); + use_default_lane_mapping = true; } + lanes_used |= BIT(array[i]); - rval = fwnode_property_read_u32_array(fwnode, - "lane-polarities", NULL, - 0); - if (rval > 0) { - if (rval != 1 + bus->num_data_lanes /* clock+data */) { - pr_warn("invalid number of lane-polarities entries (need %u, got %u)\n", - 1 + bus->num_data_lanes, rval); - return -EINVAL; - } - - fwnode_property_read_u32_array(fwnode, - "lane-polarities", array, - 1 + bus->num_data_lanes); + if (have_data_lanes) + pr_debug("lane %u position %u\n", i, array[i]); + } - for (i = 0; i < 1 + bus->num_data_lanes; i++) - bus->lane_polarities[i] = array[i]; + rval = fwnode_property_read_u32_array(fwnode, "lane-polarities", NULL, + 0); + if (rval > 0) { + if (rval != 1 + num_data_lanes /* clock+data */) { + pr_warn("invalid number of lane-polarities entries (need %u, got %u)\n", + 1 + num_data_lanes, rval); + return -EINVAL; } + have_lane_polarities = true; } if (!fwnode_property_read_u32(fwnode, "clock-lanes", &v)) { - if (lanes_used & BIT(v)) - pr_warn("duplicated lane %u in clock-lanes\n", v); - lanes_used |= BIT(v); - - bus->clock_lane = v; + clock_lane = v; + pr_debug("clock lane position %u\n", v); have_clk_lane = true; } - if (fwnode_property_present(fwnode, "clock-noncontinuous")) + if (lanes_used & BIT(clock_lane)) { + if (have_clk_lane || !use_default_lane_mapping) + pr_warn("duplicated lane %u in clock-lanes, using defaults\n", + v); + use_default_lane_mapping = true; + } + + if (fwnode_property_present(fwnode, "clock-noncontinuous")) { flags |= V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK; - else if (have_clk_lane || bus->num_data_lanes > 0) + pr_debug("non-continuous clock\n"); + } else { flags |= V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; + } - bus->flags = flags; - vep->bus_type = V4L2_MBUS_CSI2; + if (bus_type == V4L2_MBUS_CSI2_DPHY || + bus_type == V4L2_MBUS_CSI2_CPHY || lanes_used || + have_clk_lane || (flags & ~V4L2_MBUS_CSI2_CONTINUOUS_CLOCK)) { + bus->flags = flags; + if (bus_type == V4L2_MBUS_UNKNOWN) + vep->bus_type = V4L2_MBUS_CSI2_DPHY; + bus->num_data_lanes = num_data_lanes; + + if (use_default_lane_mapping) { + bus->clock_lane = 0; + for (i = 0; i < num_data_lanes; i++) + bus->data_lanes[i] = 1 + i; + } else { + bus->clock_lane = clock_lane; + for (i = 0; i < num_data_lanes; i++) + bus->data_lanes[i] = array[i]; + } + + if (have_lane_polarities) { + fwnode_property_read_u32_array(fwnode, + "lane-polarities", array, + 1 + num_data_lanes); + + for (i = 0; i < 1 + num_data_lanes; i++) { + bus->lane_polarities[i] = array[i]; + pr_debug("lane %u polarity %sinverted", + i, array[i] ? "" : "not "); + } + } else { + pr_debug("no lane polarities defined, assuming not inverted\n"); + } + } return 0; } -static void v4l2_fwnode_endpoint_parse_parallel_bus( - struct fwnode_handle *fwnode, struct v4l2_fwnode_endpoint *vep) +#define PARALLEL_MBUS_FLAGS (V4L2_MBUS_HSYNC_ACTIVE_HIGH | \ + V4L2_MBUS_HSYNC_ACTIVE_LOW | \ + V4L2_MBUS_VSYNC_ACTIVE_HIGH | \ + V4L2_MBUS_VSYNC_ACTIVE_LOW | \ + V4L2_MBUS_FIELD_EVEN_HIGH | \ + V4L2_MBUS_FIELD_EVEN_LOW) + +static void +v4l2_fwnode_endpoint_parse_parallel_bus(struct fwnode_handle *fwnode, + struct v4l2_fwnode_endpoint *vep, + enum v4l2_mbus_type bus_type) { struct v4l2_fwnode_bus_parallel *bus = &vep->bus.parallel; unsigned int flags = 0; u32 v; - if (!fwnode_property_read_u32(fwnode, "hsync-active", &v)) + if (bus_type == V4L2_MBUS_PARALLEL || bus_type == V4L2_MBUS_BT656) + flags = bus->flags; + + if (!fwnode_property_read_u32(fwnode, "hsync-active", &v)) { + flags &= ~(V4L2_MBUS_HSYNC_ACTIVE_HIGH | + V4L2_MBUS_HSYNC_ACTIVE_LOW); flags |= v ? V4L2_MBUS_HSYNC_ACTIVE_HIGH : V4L2_MBUS_HSYNC_ACTIVE_LOW; + pr_debug("hsync-active %s\n", v ? "high" : "low"); + } - if (!fwnode_property_read_u32(fwnode, "vsync-active", &v)) + if (!fwnode_property_read_u32(fwnode, "vsync-active", &v)) { + flags &= ~(V4L2_MBUS_VSYNC_ACTIVE_HIGH | + V4L2_MBUS_VSYNC_ACTIVE_LOW); flags |= v ? V4L2_MBUS_VSYNC_ACTIVE_HIGH : V4L2_MBUS_VSYNC_ACTIVE_LOW; + pr_debug("vsync-active %s\n", v ? "high" : "low"); + } - if (!fwnode_property_read_u32(fwnode, "field-even-active", &v)) + if (!fwnode_property_read_u32(fwnode, "field-even-active", &v)) { + flags &= ~(V4L2_MBUS_FIELD_EVEN_HIGH | + V4L2_MBUS_FIELD_EVEN_LOW); flags |= v ? V4L2_MBUS_FIELD_EVEN_HIGH : V4L2_MBUS_FIELD_EVEN_LOW; - if (flags) - vep->bus_type = V4L2_MBUS_PARALLEL; - else - vep->bus_type = V4L2_MBUS_BT656; + pr_debug("field-even-active %s\n", v ? "high" : "low"); + } - if (!fwnode_property_read_u32(fwnode, "pclk-sample", &v)) + if (!fwnode_property_read_u32(fwnode, "pclk-sample", &v)) { + flags &= ~(V4L2_MBUS_PCLK_SAMPLE_RISING | + V4L2_MBUS_PCLK_SAMPLE_FALLING); flags |= v ? V4L2_MBUS_PCLK_SAMPLE_RISING : V4L2_MBUS_PCLK_SAMPLE_FALLING; + pr_debug("pclk-sample %s\n", v ? "high" : "low"); + } - if (!fwnode_property_read_u32(fwnode, "data-active", &v)) + if (!fwnode_property_read_u32(fwnode, "data-active", &v)) { + flags &= ~(V4L2_MBUS_PCLK_SAMPLE_RISING | + V4L2_MBUS_PCLK_SAMPLE_FALLING); flags |= v ? V4L2_MBUS_DATA_ACTIVE_HIGH : V4L2_MBUS_DATA_ACTIVE_LOW; + pr_debug("data-active %s\n", v ? "high" : "low"); + } - if (fwnode_property_present(fwnode, "slave-mode")) + if (fwnode_property_present(fwnode, "slave-mode")) { + pr_debug("slave mode\n"); + flags &= ~V4L2_MBUS_MASTER; flags |= V4L2_MBUS_SLAVE; - else + } else { + flags &= ~V4L2_MBUS_SLAVE; flags |= V4L2_MBUS_MASTER; + } - if (!fwnode_property_read_u32(fwnode, "bus-width", &v)) + if (!fwnode_property_read_u32(fwnode, "bus-width", &v)) { bus->bus_width = v; + pr_debug("bus-width %u\n", v); + } - if (!fwnode_property_read_u32(fwnode, "data-shift", &v)) + if (!fwnode_property_read_u32(fwnode, "data-shift", &v)) { bus->data_shift = v; + pr_debug("data-shift %u\n", v); + } - if (!fwnode_property_read_u32(fwnode, "sync-on-green-active", &v)) + if (!fwnode_property_read_u32(fwnode, "sync-on-green-active", &v)) { + flags &= ~(V4L2_MBUS_VIDEO_SOG_ACTIVE_HIGH | + V4L2_MBUS_VIDEO_SOG_ACTIVE_LOW); flags |= v ? V4L2_MBUS_VIDEO_SOG_ACTIVE_HIGH : V4L2_MBUS_VIDEO_SOG_ACTIVE_LOW; + pr_debug("sync-on-green-active %s\n", v ? "high" : "low"); + } - if (!fwnode_property_read_u32(fwnode, "data-enable-active", &v)) + if (!fwnode_property_read_u32(fwnode, "data-enable-active", &v)) { + flags &= ~(V4L2_MBUS_DATA_ENABLE_HIGH | + V4L2_MBUS_DATA_ENABLE_LOW); flags |= v ? V4L2_MBUS_DATA_ENABLE_HIGH : V4L2_MBUS_DATA_ENABLE_LOW; + pr_debug("data-enable-active %s\n", v ? "high" : "low"); + } - bus->flags = flags; - + switch (bus_type) { + default: + bus->flags = flags; + if (flags & PARALLEL_MBUS_FLAGS) + vep->bus_type = V4L2_MBUS_PARALLEL; + else + vep->bus_type = V4L2_MBUS_BT656; + break; + case V4L2_MBUS_PARALLEL: + vep->bus_type = V4L2_MBUS_PARALLEL; + bus->flags = flags; + break; + case V4L2_MBUS_BT656: + vep->bus_type = V4L2_MBUS_BT656; + bus->flags = flags & ~PARALLEL_MBUS_FLAGS; + break; + } } static void v4l2_fwnode_endpoint_parse_csi1_bus(struct fwnode_handle *fwnode, struct v4l2_fwnode_endpoint *vep, - u32 bus_type) + enum v4l2_mbus_type bus_type) { struct v4l2_fwnode_bus_mipi_csi1 *bus = &vep->bus.mipi_csi1; u32 v; - if (!fwnode_property_read_u32(fwnode, "clock-inv", &v)) + if (!fwnode_property_read_u32(fwnode, "clock-inv", &v)) { bus->clock_inv = v; + pr_debug("clock-inv %u\n", v); + } - if (!fwnode_property_read_u32(fwnode, "strobe", &v)) + if (!fwnode_property_read_u32(fwnode, "strobe", &v)) { bus->strobe = v; + pr_debug("strobe %u\n", v); + } - if (!fwnode_property_read_u32(fwnode, "data-lanes", &v)) + if (!fwnode_property_read_u32(fwnode, "data-lanes", &v)) { bus->data_lane = v; + pr_debug("data-lanes %u\n", v); + } - if (!fwnode_property_read_u32(fwnode, "clock-lanes", &v)) + if (!fwnode_property_read_u32(fwnode, "clock-lanes", &v)) { bus->clock_lane = v; + pr_debug("clock-lanes %u\n", v); + } - if (bus_type == V4L2_FWNODE_BUS_TYPE_CCP2) + if (bus_type == V4L2_MBUS_CCP2) vep->bus_type = V4L2_MBUS_CCP2; else vep->bus_type = V4L2_MBUS_CSI1; } -int v4l2_fwnode_endpoint_parse(struct fwnode_handle *fwnode, - struct v4l2_fwnode_endpoint *vep) +static int __v4l2_fwnode_endpoint_parse(struct fwnode_handle *fwnode, + struct v4l2_fwnode_endpoint *vep) { - u32 bus_type = 0; + u32 bus_type = V4L2_FWNODE_BUS_TYPE_GUESS; + enum v4l2_mbus_type mbus_type; int rval; - fwnode_graph_parse_endpoint(fwnode, &vep->base); + if (vep->bus_type == V4L2_MBUS_UNKNOWN) { + /* Zero fields from bus union to until the end */ + memset(&vep->bus, 0, + sizeof(*vep) - offsetof(typeof(*vep), bus)); + } - /* Zero fields from bus_type to until the end */ - memset(&vep->bus_type, 0, sizeof(*vep) - - offsetof(typeof(*vep), bus_type)); + pr_debug("===== begin V4L2 endpoint properties\n"); + + /* + * Zero the fwnode graph endpoint memory in case we don't end up parsing + * the endpoint. + */ + memset(&vep->base, 0, sizeof(vep->base)); fwnode_property_read_u32(fwnode, "bus-type", &bus_type); + pr_debug("fwnode video bus type %s (%u), mbus type %s (%u)\n", + v4l2_fwnode_bus_type_to_string(bus_type), bus_type, + v4l2_fwnode_mbus_type_to_string(vep->bus_type), + vep->bus_type); + mbus_type = v4l2_fwnode_bus_type_to_mbus(bus_type); + + if (vep->bus_type != V4L2_MBUS_UNKNOWN) { + if (mbus_type != V4L2_MBUS_UNKNOWN && + vep->bus_type != mbus_type) { + pr_debug("expecting bus type %s\n", + v4l2_fwnode_mbus_type_to_string(vep->bus_type)); + return -ENXIO; + } + } else { + vep->bus_type = mbus_type; + } - switch (bus_type) { - case V4L2_FWNODE_BUS_TYPE_GUESS: - rval = v4l2_fwnode_endpoint_parse_csi2_bus(fwnode, vep); + switch (vep->bus_type) { + case V4L2_MBUS_UNKNOWN: + rval = v4l2_fwnode_endpoint_parse_csi2_bus(fwnode, vep, + V4L2_MBUS_UNKNOWN); if (rval) return rval; - /* - * Parse the parallel video bus properties only if none - * of the MIPI CSI-2 specific properties were found. - */ - if (vep->bus.mipi_csi2.flags == 0) - v4l2_fwnode_endpoint_parse_parallel_bus(fwnode, vep); - - return 0; - case V4L2_FWNODE_BUS_TYPE_CCP2: - case V4L2_FWNODE_BUS_TYPE_CSI1: - v4l2_fwnode_endpoint_parse_csi1_bus(fwnode, vep, bus_type); - - return 0; + + if (vep->bus_type == V4L2_MBUS_UNKNOWN) + v4l2_fwnode_endpoint_parse_parallel_bus(fwnode, vep, + V4L2_MBUS_UNKNOWN); + + pr_debug("assuming media bus type %s (%u)\n", + v4l2_fwnode_mbus_type_to_string(vep->bus_type), + vep->bus_type); + + break; + case V4L2_MBUS_CCP2: + case V4L2_MBUS_CSI1: + v4l2_fwnode_endpoint_parse_csi1_bus(fwnode, vep, vep->bus_type); + + break; + case V4L2_MBUS_CSI2_DPHY: + case V4L2_MBUS_CSI2_CPHY: + rval = v4l2_fwnode_endpoint_parse_csi2_bus(fwnode, vep, + vep->bus_type); + if (rval) + return rval; + + break; + case V4L2_MBUS_PARALLEL: + case V4L2_MBUS_BT656: + v4l2_fwnode_endpoint_parse_parallel_bus(fwnode, vep, + vep->bus_type); + + break; default: - pr_warn("unsupported bus type %u\n", bus_type); + pr_warn("unsupported bus type %u\n", mbus_type); return -EINVAL; } + + fwnode_graph_parse_endpoint(fwnode, &vep->base); + + return 0; +} + +int v4l2_fwnode_endpoint_parse(struct fwnode_handle *fwnode, + struct v4l2_fwnode_endpoint *vep) +{ + int ret; + + ret = __v4l2_fwnode_endpoint_parse(fwnode, vep); + + pr_debug("===== end V4L2 endpoint properties\n"); + + return ret; } EXPORT_SYMBOL_GPL(v4l2_fwnode_endpoint_parse); @@ -233,49 +508,48 @@ void v4l2_fwnode_endpoint_free(struct v4l2_fwnode_endpoint *vep) return; kfree(vep->link_frequencies); - kfree(vep); } EXPORT_SYMBOL_GPL(v4l2_fwnode_endpoint_free); -struct v4l2_fwnode_endpoint *v4l2_fwnode_endpoint_alloc_parse( - struct fwnode_handle *fwnode) +int v4l2_fwnode_endpoint_alloc_parse(struct fwnode_handle *fwnode, + struct v4l2_fwnode_endpoint *vep) { - struct v4l2_fwnode_endpoint *vep; int rval; - vep = kzalloc(sizeof(*vep), GFP_KERNEL); - if (!vep) - return ERR_PTR(-ENOMEM); - - rval = v4l2_fwnode_endpoint_parse(fwnode, vep); + rval = __v4l2_fwnode_endpoint_parse(fwnode, vep); if (rval < 0) - goto out_err; + return rval; rval = fwnode_property_read_u64_array(fwnode, "link-frequencies", NULL, 0); if (rval > 0) { + unsigned int i; + vep->link_frequencies = kmalloc_array(rval, sizeof(*vep->link_frequencies), GFP_KERNEL); - if (!vep->link_frequencies) { - rval = -ENOMEM; - goto out_err; - } + if (!vep->link_frequencies) + return -ENOMEM; vep->nr_of_link_frequencies = rval; - rval = fwnode_property_read_u64_array( - fwnode, "link-frequencies", vep->link_frequencies, - vep->nr_of_link_frequencies); - if (rval < 0) - goto out_err; + rval = fwnode_property_read_u64_array(fwnode, + "link-frequencies", + vep->link_frequencies, + vep->nr_of_link_frequencies); + if (rval < 0) { + v4l2_fwnode_endpoint_free(vep); + return rval; + } + + for (i = 0; i < vep->nr_of_link_frequencies; i++) + pr_info("link-frequencies %u value %llu\n", i, + vep->link_frequencies[i]); } - return vep; + pr_debug("===== end V4L2 endpoint properties\n"); -out_err: - v4l2_fwnode_endpoint_free(vep); - return ERR_PTR(rval); + return 0; } EXPORT_SYMBOL_GPL(v4l2_fwnode_endpoint_alloc_parse); @@ -320,43 +594,16 @@ void v4l2_fwnode_put_link(struct v4l2_fwnode_link *link) } EXPORT_SYMBOL_GPL(v4l2_fwnode_put_link); -static int v4l2_async_notifier_realloc(struct v4l2_async_notifier *notifier, - unsigned int max_subdevs) -{ - struct v4l2_async_subdev **subdevs; - - if (max_subdevs <= notifier->max_subdevs) - return 0; - - subdevs = kvmalloc_array( - max_subdevs, sizeof(*notifier->subdevs), - GFP_KERNEL | __GFP_ZERO); - if (!subdevs) - return -ENOMEM; - - if (notifier->subdevs) { - memcpy(subdevs, notifier->subdevs, - sizeof(*subdevs) * notifier->num_subdevs); - - kvfree(notifier->subdevs); - } - - notifier->subdevs = subdevs; - notifier->max_subdevs = max_subdevs; - - return 0; -} - -static int v4l2_async_notifier_fwnode_parse_endpoint( - struct device *dev, struct v4l2_async_notifier *notifier, - struct fwnode_handle *endpoint, unsigned int asd_struct_size, - int (*parse_endpoint)(struct device *dev, - struct v4l2_fwnode_endpoint *vep, - struct v4l2_async_subdev *asd)) +static int +v4l2_async_notifier_fwnode_parse_endpoint(struct device *dev, + struct v4l2_async_notifier *notifier, + struct fwnode_handle *endpoint, + unsigned int asd_struct_size, + parse_endpoint_func parse_endpoint) { + struct v4l2_fwnode_endpoint vep = { .bus_type = 0 }; struct v4l2_async_subdev *asd; - struct v4l2_fwnode_endpoint *vep; - int ret = 0; + int ret; asd = kzalloc(asd_struct_size, GFP_KERNEL); if (!asd) @@ -367,32 +614,36 @@ static int v4l2_async_notifier_fwnode_parse_endpoint( fwnode_graph_get_remote_port_parent(endpoint); if (!asd->match.fwnode) { dev_warn(dev, "bad remote port parent\n"); - ret = -EINVAL; + ret = -ENOTCONN; goto out_err; } - vep = v4l2_fwnode_endpoint_alloc_parse(endpoint); - if (IS_ERR(vep)) { - ret = PTR_ERR(vep); + ret = v4l2_fwnode_endpoint_alloc_parse(endpoint, &vep); + if (ret) { dev_warn(dev, "unable to parse V4L2 fwnode endpoint (%d)\n", ret); goto out_err; } - ret = parse_endpoint ? parse_endpoint(dev, vep, asd) : 0; + ret = parse_endpoint ? parse_endpoint(dev, &vep, asd) : 0; if (ret == -ENOTCONN) - dev_dbg(dev, "ignoring port@%u/endpoint@%u\n", vep->base.port, - vep->base.id); + dev_dbg(dev, "ignoring port@%u/endpoint@%u\n", vep.base.port, + vep.base.id); else if (ret < 0) dev_warn(dev, "driver could not parse port@%u/endpoint@%u (%d)\n", - vep->base.port, vep->base.id, ret); - v4l2_fwnode_endpoint_free(vep); + vep.base.port, vep.base.id, ret); + v4l2_fwnode_endpoint_free(&vep); if (ret < 0) goto out_err; - notifier->subdevs[notifier->num_subdevs] = asd; - notifier->num_subdevs++; + ret = v4l2_async_notifier_add_subdev(notifier, asd); + if (ret < 0) { + /* not an error if asd already exists */ + if (ret == -EEXIST) + ret = 0; + goto out_err; + } return 0; @@ -403,56 +654,21 @@ out_err: return ret == -ENOTCONN ? 0 : ret; } -static int __v4l2_async_notifier_parse_fwnode_endpoints( - struct device *dev, struct v4l2_async_notifier *notifier, - size_t asd_struct_size, unsigned int port, bool has_port, - int (*parse_endpoint)(struct device *dev, - struct v4l2_fwnode_endpoint *vep, - struct v4l2_async_subdev *asd)) +static int +__v4l2_async_notifier_parse_fwnode_ep(struct device *dev, + struct v4l2_async_notifier *notifier, + size_t asd_struct_size, + unsigned int port, + bool has_port, + parse_endpoint_func parse_endpoint) { struct fwnode_handle *fwnode; - unsigned int max_subdevs = notifier->max_subdevs; - int ret; + int ret = 0; if (WARN_ON(asd_struct_size < sizeof(struct v4l2_async_subdev))) return -EINVAL; - for (fwnode = NULL; (fwnode = fwnode_graph_get_next_endpoint( - dev_fwnode(dev), fwnode)); ) { - struct fwnode_handle *dev_fwnode; - bool is_available; - - dev_fwnode = fwnode_graph_get_port_parent(fwnode); - is_available = fwnode_device_is_available(dev_fwnode); - fwnode_handle_put(dev_fwnode); - if (!is_available) - continue; - - if (has_port) { - struct fwnode_endpoint ep; - - ret = fwnode_graph_parse_endpoint(fwnode, &ep); - if (ret) { - fwnode_handle_put(fwnode); - return ret; - } - - if (ep.port != port) - continue; - } - max_subdevs++; - } - - /* No subdevs to add? Return here. */ - if (max_subdevs == notifier->max_subdevs) - return 0; - - ret = v4l2_async_notifier_realloc(notifier, max_subdevs); - if (ret) - return ret; - - for (fwnode = NULL; (fwnode = fwnode_graph_get_next_endpoint( - dev_fwnode(dev), fwnode)); ) { + fwnode_graph_for_each_endpoint(dev_fwnode(dev), fwnode) { struct fwnode_handle *dev_fwnode; bool is_available; @@ -473,13 +689,11 @@ static int __v4l2_async_notifier_parse_fwnode_endpoints( continue; } - if (WARN_ON(notifier->num_subdevs >= notifier->max_subdevs)) { - ret = -EINVAL; - break; - } - - ret = v4l2_async_notifier_fwnode_parse_endpoint( - dev, notifier, fwnode, asd_struct_size, parse_endpoint); + ret = v4l2_async_notifier_fwnode_parse_endpoint(dev, + notifier, + fwnode, + asd_struct_size, + parse_endpoint); if (ret < 0) break; } @@ -489,27 +703,29 @@ static int __v4l2_async_notifier_parse_fwnode_endpoints( return ret; } -int v4l2_async_notifier_parse_fwnode_endpoints( - struct device *dev, struct v4l2_async_notifier *notifier, - size_t asd_struct_size, - int (*parse_endpoint)(struct device *dev, - struct v4l2_fwnode_endpoint *vep, - struct v4l2_async_subdev *asd)) +int +v4l2_async_notifier_parse_fwnode_endpoints(struct device *dev, + struct v4l2_async_notifier *notifier, + size_t asd_struct_size, + parse_endpoint_func parse_endpoint) { - return __v4l2_async_notifier_parse_fwnode_endpoints( - dev, notifier, asd_struct_size, 0, false, parse_endpoint); + return __v4l2_async_notifier_parse_fwnode_ep(dev, notifier, + asd_struct_size, 0, + false, parse_endpoint); } EXPORT_SYMBOL_GPL(v4l2_async_notifier_parse_fwnode_endpoints); -int v4l2_async_notifier_parse_fwnode_endpoints_by_port( - struct device *dev, struct v4l2_async_notifier *notifier, - size_t asd_struct_size, unsigned int port, - int (*parse_endpoint)(struct device *dev, - struct v4l2_fwnode_endpoint *vep, - struct v4l2_async_subdev *asd)) +int +v4l2_async_notifier_parse_fwnode_endpoints_by_port(struct device *dev, + struct v4l2_async_notifier *notifier, + size_t asd_struct_size, + unsigned int port, + parse_endpoint_func parse_endpoint) { - return __v4l2_async_notifier_parse_fwnode_endpoints( - dev, notifier, asd_struct_size, port, true, parse_endpoint); + return __v4l2_async_notifier_parse_fwnode_ep(dev, notifier, + asd_struct_size, + port, true, + parse_endpoint); } EXPORT_SYMBOL_GPL(v4l2_async_notifier_parse_fwnode_endpoints_by_port); @@ -524,17 +740,18 @@ EXPORT_SYMBOL_GPL(v4l2_async_notifier_parse_fwnode_endpoints_by_port); * -ENOMEM if memory allocation failed * -EINVAL if property parsing failed */ -static int v4l2_fwnode_reference_parse( - struct device *dev, struct v4l2_async_notifier *notifier, - const char *prop) +static int v4l2_fwnode_reference_parse(struct device *dev, + struct v4l2_async_notifier *notifier, + const char *prop) { struct fwnode_reference_args args; unsigned int index; int ret; for (index = 0; - !(ret = fwnode_property_get_reference_args( - dev_fwnode(dev), prop, NULL, 0, index, &args)); + !(ret = fwnode_property_get_reference_args(dev_fwnode(dev), + prop, NULL, 0, + index, &args)); index++) fwnode_handle_put(args.fwnode); @@ -548,31 +765,25 @@ static int v4l2_fwnode_reference_parse( if (ret != -ENOENT && ret != -ENODATA) return ret; - ret = v4l2_async_notifier_realloc(notifier, - notifier->num_subdevs + index); - if (ret) - return ret; - - for (index = 0; !fwnode_property_get_reference_args( - dev_fwnode(dev), prop, NULL, 0, index, &args); + for (index = 0; + !fwnode_property_get_reference_args(dev_fwnode(dev), prop, NULL, + 0, index, &args); index++) { struct v4l2_async_subdev *asd; - if (WARN_ON(notifier->num_subdevs >= notifier->max_subdevs)) { - ret = -EINVAL; - goto error; - } + asd = v4l2_async_notifier_add_fwnode_subdev(notifier, + args.fwnode, + sizeof(*asd)); + if (IS_ERR(asd)) { + ret = PTR_ERR(asd); + /* not an error if asd already exists */ + if (ret == -EEXIST) { + fwnode_handle_put(args.fwnode); + continue; + } - asd = kzalloc(sizeof(*asd), GFP_KERNEL); - if (!asd) { - ret = -ENOMEM; goto error; } - - notifier->subdevs[notifier->num_subdevs] = asd; - asd->match.fwnode = args.fwnode; - asd->match_type = V4L2_ASYNC_MATCH_FWNODE; - notifier->num_subdevs++; } return 0; @@ -738,9 +949,12 @@ error: * -EINVAL if property parsing otherwise failed * -ENOMEM if memory allocation failed */ -static struct fwnode_handle *v4l2_fwnode_reference_get_int_prop( - struct fwnode_handle *fwnode, const char *prop, unsigned int index, - const char * const *props, unsigned int nprops) +static struct fwnode_handle * +v4l2_fwnode_reference_get_int_prop(struct fwnode_handle *fwnode, + const char *prop, + unsigned int index, + const char * const *props, + unsigned int nprops) { struct fwnode_reference_args fwnode_args; u64 *args = fwnode_args.args; @@ -792,6 +1006,12 @@ static struct fwnode_handle *v4l2_fwnode_reference_get_int_prop( return fwnode; } +struct v4l2_fwnode_int_props { + const char *name; + const char * const *props; + unsigned int nprops; +}; + /* * v4l2_fwnode_reference_parse_int_props - parse references for async * sub-devices @@ -815,13 +1035,17 @@ static struct fwnode_handle *v4l2_fwnode_reference_get_int_prop( * -EINVAL if property parsing otherwisefailed * -ENOMEM if memory allocation failed */ -static int v4l2_fwnode_reference_parse_int_props( - struct device *dev, struct v4l2_async_notifier *notifier, - const char *prop, const char * const *props, unsigned int nprops) +static int +v4l2_fwnode_reference_parse_int_props(struct device *dev, + struct v4l2_async_notifier *notifier, + const struct v4l2_fwnode_int_props *p) { struct fwnode_handle *fwnode; unsigned int index; int ret; + const char *prop = p->name; + const char * const *props = p->props; + unsigned int nprops = p->nprops; index = 0; do { @@ -843,31 +1067,26 @@ static int v4l2_fwnode_reference_parse_int_props( index++; } while (1); - ret = v4l2_async_notifier_realloc(notifier, - notifier->num_subdevs + index); - if (ret) - return -ENOMEM; - - for (index = 0; !IS_ERR((fwnode = v4l2_fwnode_reference_get_int_prop( - dev_fwnode(dev), prop, index, props, - nprops))); index++) { + for (index = 0; + !IS_ERR((fwnode = v4l2_fwnode_reference_get_int_prop(dev_fwnode(dev), + prop, index, + props, + nprops))); + index++) { struct v4l2_async_subdev *asd; - if (WARN_ON(notifier->num_subdevs >= notifier->max_subdevs)) { - ret = -EINVAL; - goto error; - } + asd = v4l2_async_notifier_add_fwnode_subdev(notifier, fwnode, + sizeof(*asd)); + if (IS_ERR(asd)) { + ret = PTR_ERR(asd); + /* not an error if asd already exists */ + if (ret == -EEXIST) { + fwnode_handle_put(fwnode); + continue; + } - asd = kzalloc(sizeof(struct v4l2_async_subdev), GFP_KERNEL); - if (!asd) { - ret = -ENOMEM; goto error; } - - notifier->subdevs[notifier->num_subdevs] = asd; - asd->match.fwnode = fwnode; - asd->match_type = V4L2_ASYNC_MATCH_FWNODE; - notifier->num_subdevs++; } return PTR_ERR(fwnode) == -ENOENT ? 0 : PTR_ERR(fwnode); @@ -877,15 +1096,11 @@ error: return ret; } -int v4l2_async_notifier_parse_fwnode_sensor_common( - struct device *dev, struct v4l2_async_notifier *notifier) +int v4l2_async_notifier_parse_fwnode_sensor_common(struct device *dev, + struct v4l2_async_notifier *notifier) { static const char * const led_props[] = { "led" }; - static const struct { - const char *name; - const char * const *props; - unsigned int nprops; - } props[] = { + static const struct v4l2_fwnode_int_props props[] = { { "flash-leds", led_props, ARRAY_SIZE(led_props) }, { "lens-focus", NULL, 0 }, }; @@ -895,12 +1110,12 @@ int v4l2_async_notifier_parse_fwnode_sensor_common( int ret; if (props[i].props && is_acpi_node(dev_fwnode(dev))) - ret = v4l2_fwnode_reference_parse_int_props( - dev, notifier, props[i].name, - props[i].props, props[i].nprops); + ret = v4l2_fwnode_reference_parse_int_props(dev, + notifier, + &props[i]); else - ret = v4l2_fwnode_reference_parse( - dev, notifier, props[i].name); + ret = v4l2_fwnode_reference_parse(dev, notifier, + props[i].name); if (ret && ret != -ENOENT) { dev_warn(dev, "parsing property \"%s\" failed (%d)\n", props[i].name, ret); @@ -924,6 +1139,8 @@ int v4l2_async_register_subdev_sensor_common(struct v4l2_subdev *sd) if (!notifier) return -ENOMEM; + v4l2_async_notifier_init(notifier); + ret = v4l2_async_notifier_parse_fwnode_sensor_common(sd->dev, notifier); if (ret < 0) @@ -952,6 +1169,68 @@ out_cleanup: } EXPORT_SYMBOL_GPL(v4l2_async_register_subdev_sensor_common); +int v4l2_async_register_fwnode_subdev(struct v4l2_subdev *sd, + size_t asd_struct_size, + unsigned int *ports, + unsigned int num_ports, + parse_endpoint_func parse_endpoint) +{ + struct v4l2_async_notifier *notifier; + struct device *dev = sd->dev; + struct fwnode_handle *fwnode; + int ret; + + if (WARN_ON(!dev)) + return -ENODEV; + + fwnode = dev_fwnode(dev); + if (!fwnode_device_is_available(fwnode)) + return -ENODEV; + + notifier = kzalloc(sizeof(*notifier), GFP_KERNEL); + if (!notifier) + return -ENOMEM; + + v4l2_async_notifier_init(notifier); + + if (!ports) { + ret = v4l2_async_notifier_parse_fwnode_endpoints(dev, notifier, + asd_struct_size, + parse_endpoint); + if (ret < 0) + goto out_cleanup; + } else { + unsigned int i; + + for (i = 0; i < num_ports; i++) { + ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port(dev, notifier, asd_struct_size, ports[i], parse_endpoint); + if (ret < 0) + goto out_cleanup; + } + } + + ret = v4l2_async_subdev_notifier_register(sd, notifier); + if (ret < 0) + goto out_cleanup; + + ret = v4l2_async_register_subdev(sd); + if (ret < 0) + goto out_unregister; + + sd->subdev_notifier = notifier; + + return 0; + +out_unregister: + v4l2_async_notifier_unregister(notifier); +out_cleanup: + v4l2_async_notifier_cleanup(notifier); + kfree(notifier); + + return ret; +} +EXPORT_SYMBOL_GPL(v4l2_async_register_fwnode_subdev); + MODULE_LICENSE("GPL"); MODULE_AUTHOR("Sakari Ailus <sakari.ailus@linux.intel.com>"); MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>"); diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 54afc9c7ee6e..7de041bae84f 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -121,7 +121,7 @@ int v4l2_video_std_construct(struct v4l2_standard *vs, vs->id = id; v4l2_video_std_frame_period(id, &vs->frameperiod); vs->framelines = (id & V4L2_STD_525_60) ? 525 : 625; - strlcpy(vs->name, name, sizeof(vs->name)); + strscpy(vs->name, name, sizeof(vs->name)); return 0; } EXPORT_SYMBOL(v4l2_video_std_construct); @@ -1352,7 +1352,7 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) } if (descr) - WARN_ON(strlcpy(fmt->description, descr, sz) >= sz); + WARN_ON(strscpy(fmt->description, descr, sz) >= sz); fmt->flags = flags; } @@ -2391,7 +2391,7 @@ static int v4l_dbg_g_chip_info(const struct v4l2_ioctl_ops *ops, p->flags |= V4L2_CHIP_FL_WRITABLE; if (ops->vidioc_g_register) p->flags |= V4L2_CHIP_FL_READABLE; - strlcpy(p->name, vfd->v4l2_dev->name, sizeof(p->name)); + strscpy(p->name, vfd->v4l2_dev->name, sizeof(p->name)); if (ops->vidioc_g_chip_info) return ops->vidioc_g_chip_info(file, fh, arg); if (p->match.addr) @@ -2408,7 +2408,7 @@ static int v4l_dbg_g_chip_info(const struct v4l2_ioctl_ops *ops, p->flags |= V4L2_CHIP_FL_WRITABLE; if (sd->ops->core && sd->ops->core->g_register) p->flags |= V4L2_CHIP_FL_READABLE; - strlcpy(p->name, sd->name, sizeof(p->name)); + strscpy(p->name, sd->name, sizeof(p->name)); return 0; } break; diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c index 0fc185a2ce90..014a2a97cadd 100644 --- a/drivers/media/v4l2-core/v4l2-mc.c +++ b/drivers/media/v4l2-core/v4l2-mc.c @@ -28,7 +28,7 @@ int v4l2_mc_create_media_graph(struct media_device *mdev) struct media_entity *io_v4l = NULL, *io_vbi = NULL, *io_swradio = NULL; bool is_webcam = false; u32 flags; - int ret; + int ret, pad_sink, pad_source; if (!mdev) return 0; @@ -63,8 +63,10 @@ int v4l2_mc_create_media_graph(struct media_device *mdev) } /* It should have at least one I/O entity */ - if (!io_v4l && !io_vbi && !io_swradio) + if (!io_v4l && !io_vbi && !io_swradio) { + dev_warn(mdev->dev, "Didn't find any I/O entity\n"); return -EINVAL; + } /* * Here, webcams are modelled on a very simple way: the sensor is @@ -74,8 +76,10 @@ int v4l2_mc_create_media_graph(struct media_device *mdev) * PC-consumer's hardware. */ if (is_webcam) { - if (!io_v4l) + if (!io_v4l) { + dev_warn(mdev->dev, "Didn't find a MEDIA_ENT_F_IO_V4L\n"); return -EINVAL; + } media_device_for_each_entity(entity, mdev) { if (entity->function != MEDIA_ENT_F_CAM_SENSOR) @@ -83,46 +87,91 @@ int v4l2_mc_create_media_graph(struct media_device *mdev) ret = media_create_pad_link(entity, 0, io_v4l, 0, MEDIA_LNK_FL_ENABLED); - if (ret) + if (ret) { + dev_warn(mdev->dev, "Failed to create a sensor link\n"); return ret; + } } if (!decoder) return 0; } /* The device isn't a webcam. So, it should have a decoder */ - if (!decoder) + if (!decoder) { + dev_warn(mdev->dev, "Decoder not found\n"); return -EINVAL; + } /* Link the tuner and IF video output pads */ if (tuner) { if (if_vid) { - ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT, - if_vid, - IF_VID_DEC_PAD_IF_INPUT, + pad_source = media_get_pad_index(tuner, false, + PAD_SIGNAL_ANALOG); + pad_sink = media_get_pad_index(if_vid, true, + PAD_SIGNAL_ANALOG); + if (pad_source < 0 || pad_sink < 0) { + dev_warn(mdev->dev, "Couldn't get tuner and/or PLL pad(s): (%d, %d)\n", + pad_source, pad_sink); + return -EINVAL; + } + ret = media_create_pad_link(tuner, pad_source, + if_vid, pad_sink, MEDIA_LNK_FL_ENABLED); - if (ret) + if (ret) { + dev_warn(mdev->dev, "Couldn't create tuner->PLL link)\n"); return ret; - ret = media_create_pad_link(if_vid, IF_VID_DEC_PAD_OUT, - decoder, DEMOD_PAD_IF_INPUT, - MEDIA_LNK_FL_ENABLED); - if (ret) + } + + pad_source = media_get_pad_index(if_vid, false, + PAD_SIGNAL_ANALOG); + pad_sink = media_get_pad_index(decoder, true, + PAD_SIGNAL_ANALOG); + if (pad_source < 0 || pad_sink < 0) { + dev_warn(mdev->dev, "get decoder and/or PLL pad(s): (%d, %d)\n", + pad_source, pad_sink); + return -EINVAL; + } + ret = media_create_pad_link(if_vid, pad_source, + decoder, pad_sink, + MEDIA_LNK_FL_ENABLED); + if (ret) { + dev_warn(mdev->dev, "couldn't link PLL to decoder\n"); return ret; + } } else { - ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT, - decoder, DEMOD_PAD_IF_INPUT, - MEDIA_LNK_FL_ENABLED); + pad_source = media_get_pad_index(tuner, false, + PAD_SIGNAL_ANALOG); + pad_sink = media_get_pad_index(decoder, true, + PAD_SIGNAL_ANALOG); + if (pad_source < 0 || pad_sink < 0) { + dev_warn(mdev->dev, "couldn't get tuner and/or decoder pad(s): (%d, %d)\n", + pad_source, pad_sink); + return -EINVAL; + } + ret = media_create_pad_link(tuner, pad_source, + decoder, pad_sink, + MEDIA_LNK_FL_ENABLED); if (ret) return ret; } if (if_aud) { - ret = media_create_pad_link(tuner, TUNER_PAD_AUD_OUT, - if_aud, - IF_AUD_DEC_PAD_IF_INPUT, + pad_source = media_get_pad_index(tuner, false, + PAD_SIGNAL_AUDIO); + pad_sink = media_get_pad_index(if_aud, true, + PAD_SIGNAL_AUDIO); + if (pad_source < 0 || pad_sink < 0) { + dev_warn(mdev->dev, "couldn't get tuner and/or decoder pad(s) for audio: (%d, %d)\n", + pad_source, pad_sink); + return -EINVAL; + } + ret = media_create_pad_link(tuner, pad_source, + if_aud, pad_sink, MEDIA_LNK_FL_ENABLED); - if (ret) + if (ret) { + dev_warn(mdev->dev, "couldn't link tuner->audio PLL\n"); return ret; + } } else { if_aud = tuner; } @@ -131,27 +180,48 @@ int v4l2_mc_create_media_graph(struct media_device *mdev) /* Create demod to V4L, VBI and SDR radio links */ if (io_v4l) { - ret = media_create_pad_link(decoder, DEMOD_PAD_VID_OUT, - io_v4l, 0, - MEDIA_LNK_FL_ENABLED); - if (ret) + pad_source = media_get_pad_index(decoder, false, PAD_SIGNAL_DV); + if (pad_source < 0) { + dev_warn(mdev->dev, "couldn't get decoder output pad for V4L I/O\n"); + return -EINVAL; + } + ret = media_create_pad_link(decoder, pad_source, + io_v4l, 0, + MEDIA_LNK_FL_ENABLED); + if (ret) { + dev_warn(mdev->dev, "couldn't link decoder output to V4L I/O\n"); return ret; + } } if (io_swradio) { - ret = media_create_pad_link(decoder, DEMOD_PAD_VID_OUT, - io_swradio, 0, - MEDIA_LNK_FL_ENABLED); - if (ret) + pad_source = media_get_pad_index(decoder, false, PAD_SIGNAL_DV); + if (pad_source < 0) { + dev_warn(mdev->dev, "couldn't get decoder output pad for SDR\n"); + return -EINVAL; + } + ret = media_create_pad_link(decoder, pad_source, + io_swradio, 0, + MEDIA_LNK_FL_ENABLED); + if (ret) { + dev_warn(mdev->dev, "couldn't link decoder output to SDR\n"); return ret; + } } if (io_vbi) { - ret = media_create_pad_link(decoder, DEMOD_PAD_VBI_OUT, + pad_source = media_get_pad_index(decoder, false, PAD_SIGNAL_DV); + if (pad_source < 0) { + dev_warn(mdev->dev, "couldn't get decoder output pad for VBI\n"); + return -EINVAL; + } + ret = media_create_pad_link(decoder, pad_source, io_vbi, 0, MEDIA_LNK_FL_ENABLED); - if (ret) + if (ret) { + dev_warn(mdev->dev, "couldn't link decoder output to VBI\n"); return ret; + } } /* Create links for the media connectors */ @@ -161,15 +231,26 @@ int v4l2_mc_create_media_graph(struct media_device *mdev) case MEDIA_ENT_F_CONN_RF: if (!tuner) continue; - + pad_sink = media_get_pad_index(tuner, true, + PAD_SIGNAL_ANALOG); + if (pad_sink < 0) { + dev_warn(mdev->dev, "couldn't get tuner analog pad sink\n"); + return -EINVAL; + } ret = media_create_pad_link(entity, 0, tuner, - TUNER_PAD_RF_INPUT, + pad_sink, flags); break; case MEDIA_ENT_F_CONN_SVIDEO: case MEDIA_ENT_F_CONN_COMPOSITE: + pad_sink = media_get_pad_index(decoder, true, + PAD_SIGNAL_ANALOG); + if (pad_sink < 0) { + dev_warn(mdev->dev, "couldn't get tuner analog pad sink\n"); + return -EINVAL; + } ret = media_create_pad_link(entity, 0, decoder, - DEMOD_PAD_IF_INPUT, + pad_sink, flags); break; default: diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index 2b63fa6b6fc9..792f41dffe23 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -273,7 +273,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) p->flags |= V4L2_CHIP_FL_WRITABLE; if (sd->ops->core && sd->ops->core->g_register) p->flags |= V4L2_CHIP_FL_READABLE; - strlcpy(p->name, sd->name, sizeof(p->name)); + strscpy(p->name, sd->name, sizeof(p->name)); return 0; } #endif diff --git a/drivers/staging/media/bcm2048/radio-bcm2048.c b/drivers/staging/media/bcm2048/radio-bcm2048.c index a90b2eb112f9..874d290f9622 100644 --- a/drivers/staging/media/bcm2048/radio-bcm2048.c +++ b/drivers/staging/media/bcm2048/radio-bcm2048.c @@ -2304,9 +2304,9 @@ static int bcm2048_vidioc_querycap(struct file *file, void *priv, { struct bcm2048_device *bdev = video_get_drvdata(video_devdata(file)); - strlcpy(capability->driver, BCM2048_DRIVER_NAME, + strscpy(capability->driver, BCM2048_DRIVER_NAME, sizeof(capability->driver)); - strlcpy(capability->card, BCM2048_DRIVER_CARD, + strscpy(capability->card, BCM2048_DRIVER_CARD, sizeof(capability->card)); snprintf(capability->bus_info, 32, "I2C: 0x%X", bdev->client->addr); capability->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO | diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipe.c b/drivers/staging/media/davinci_vpfe/dm365_ipipe.c index 4d09e8141fed..dcfeac818451 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_ipipe.c +++ b/drivers/staging/media/davinci_vpfe/dm365_ipipe.c @@ -1801,7 +1801,7 @@ vpfe_ipipe_init(struct vpfe_ipipe_device *ipipe, struct platform_device *pdev) v4l2_subdev_init(sd, &ipipe_v4l2_ops); sd->internal_ops = &ipipe_v4l2_internal_ops; - strlcpy(sd->name, "DAVINCI IPIPE", sizeof(sd->name)); + strscpy(sd->name, "DAVINCI IPIPE", sizeof(sd->name)); sd->grp_id = 1 << 16; /* group ID for davinci subdevs */ v4l2_set_subdevdata(sd, ipipe); sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c index 11c9edfbdbe3..a53231b08d30 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c +++ b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c @@ -1020,7 +1020,7 @@ int vpfe_ipipeif_init(struct vpfe_ipipeif_device *ipipeif, v4l2_subdev_init(sd, &ipipeif_v4l2_ops); sd->internal_ops = &ipipeif_v4l2_internal_ops; - strlcpy(sd->name, "DAVINCI IPIPEIF", sizeof(sd->name)); + strscpy(sd->name, "DAVINCI IPIPEIF", sizeof(sd->name)); sd->grp_id = 1 << 16; /* group ID for davinci subdevs */ v4l2_set_subdevdata(sd, ipipeif); diff --git a/drivers/staging/media/davinci_vpfe/dm365_isif.c b/drivers/staging/media/davinci_vpfe/dm365_isif.c index 745e33fa6bea..39eb0819ab4e 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_isif.c +++ b/drivers/staging/media/davinci_vpfe/dm365_isif.c @@ -2038,7 +2038,7 @@ int vpfe_isif_init(struct vpfe_isif_device *isif, struct platform_device *pdev) isif->video_out.ops = &isif_video_ops; v4l2_subdev_init(sd, &isif_v4l2_ops); sd->internal_ops = &isif_v4l2_internal_ops; - strlcpy(sd->name, "DAVINCI ISIF", sizeof(sd->name)); + strscpy(sd->name, "DAVINCI ISIF", sizeof(sd->name)); sd->grp_id = 1 << 16; /* group ID for davinci subdevs */ v4l2_set_subdevdata(sd, isif); sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE; diff --git a/drivers/staging/media/davinci_vpfe/dm365_resizer.c b/drivers/staging/media/davinci_vpfe/dm365_resizer.c index 6c5fcd6c691a..72bbbc34d18c 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_resizer.c +++ b/drivers/staging/media/davinci_vpfe/dm365_resizer.c @@ -1903,7 +1903,7 @@ int vpfe_resizer_init(struct vpfe_resizer_device *vpfe_rsz, v4l2_subdev_init(sd, &resizer_v4l2_ops); sd->internal_ops = &resizer_v4l2_internal_ops; - strlcpy(sd->name, "DAVINCI RESIZER CROP", sizeof(sd->name)); + strscpy(sd->name, "DAVINCI RESIZER CROP", sizeof(sd->name)); sd->grp_id = 1 << 16; /* group ID for davinci subdevs */ v4l2_set_subdevdata(sd, vpfe_rsz); sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; @@ -1927,7 +1927,7 @@ int vpfe_resizer_init(struct vpfe_resizer_device *vpfe_rsz, v4l2_subdev_init(sd, &resizer_v4l2_ops); sd->internal_ops = &resizer_v4l2_internal_ops; - strlcpy(sd->name, "DAVINCI RESIZER A", sizeof(sd->name)); + strscpy(sd->name, "DAVINCI RESIZER A", sizeof(sd->name)); sd->grp_id = 1 << 16; /* group ID for davinci subdevs */ v4l2_set_subdevdata(sd, vpfe_rsz); sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; @@ -1949,7 +1949,7 @@ int vpfe_resizer_init(struct vpfe_resizer_device *vpfe_rsz, v4l2_subdev_init(sd, &resizer_v4l2_ops); sd->internal_ops = &resizer_v4l2_internal_ops; - strlcpy(sd->name, "DAVINCI RESIZER B", sizeof(sd->name)); + strscpy(sd->name, "DAVINCI RESIZER B", sizeof(sd->name)); sd->grp_id = 1 << 16; /* group ID for davinci subdevs */ v4l2_set_subdevdata(sd, vpfe_rsz); sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; diff --git a/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c b/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c index e55c815b9b65..bdf6ee5ad96c 100644 --- a/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c +++ b/drivers/staging/media/davinci_vpfe/vpfe_mc_capture.c @@ -639,7 +639,8 @@ static int vpfe_probe(struct platform_device *pdev) goto probe_disable_clock; vpfe_dev->media_dev.dev = vpfe_dev->pdev; - strcpy((char *)&vpfe_dev->media_dev.model, "davinci-media"); + strscpy((char *)&vpfe_dev->media_dev.model, "davinci-media", + sizeof(vpfe_dev->media_dev.model)); ret = media_device_register(&vpfe_dev->media_dev); if (ret) { diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.c b/drivers/staging/media/davinci_vpfe/vpfe_video.c index 1269a983455e..5e42490331b7 100644 --- a/drivers/staging/media/davinci_vpfe/vpfe_video.c +++ b/drivers/staging/media/davinci_vpfe/vpfe_video.c @@ -618,9 +618,9 @@ static int vpfe_querycap(struct file *file, void *priv, cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING | V4L2_CAP_DEVICE_CAPS; - strlcpy(cap->driver, CAPTURE_DRV_NAME, sizeof(cap->driver)); - strlcpy(cap->bus_info, "VPFE", sizeof(cap->bus_info)); - strlcpy(cap->card, vpfe_dev->cfg->card_name, sizeof(cap->card)); + strscpy(cap->driver, CAPTURE_DRV_NAME, sizeof(cap->driver)); + strscpy(cap->bus_info, "VPFE", sizeof(cap->bus_info)); + strscpy(cap->card, vpfe_dev->cfg->card_name, sizeof(cap->card)); return 0; } diff --git a/drivers/staging/media/imx/TODO b/drivers/staging/media/imx/TODO index 9eb7326f3fc6..aeeb15494a49 100644 --- a/drivers/staging/media/imx/TODO +++ b/drivers/staging/media/imx/TODO @@ -17,29 +17,15 @@ decided whether this feature is useful enough to make it generally available by exporting to v4l2-core. -- The OF graph is walked at probe time to form the list of fwnodes to - be passed to v4l2_async_notifier_register(), starting from the IPU - CSI ports. And after all async subdevices have been bound, - v4l2_fwnode_parse_link() is used to form the media links between - the entities discovered by walking the OF graph. +- After all async subdevices have been bound, v4l2_fwnode_parse_link() + is used to form the media links between the devices discovered in + the OF graph. While this approach allows support for arbitrary OF graphs, there are some assumptions for this to work: - 1. All port parent nodes reachable in the graph from the IPU CSI - ports bind to V4L2 async subdevice drivers. - - If a device has mixed-use ports such as video plus audio, the - endpoints from the audio ports are followed to devices that must - bind to V4L2 subdevice drivers, and not for example, to an ALSA - driver or a non-V4L2 media driver. If the device were bound to - such a driver, imx-media would never get an async completion - notification because the device fwnode was added to the async - list, but the driver does not interface with the V4L2 async - framework. - - 2. Every port reachable in the graph is treated as a media pad, - owned by the V4L2 subdevice that is bound to the port's parent. + 1. If a port owned by a device in the graph has endpoint nodes, the + port is treated as a media pad. This presents problems for devices that don't make this port = pad assumption. Examples are SMIAPP compatible cameras which define only @@ -54,9 +40,8 @@ possible long-term solution is to implement a subdev API that maps a port id to a media pad index. - 3. Every endpoint of a port reachable in the graph is treated as - a media link, between V4L2 subdevices that are bound to the - port parents of the local and remote endpoints. + 2. Every endpoint of a port owned by a device in the graph is treated + as a media link. Which means a port must not contain mixed-use endpoints, they must all refer to media links between V4L2 subdevices. diff --git a/drivers/staging/media/imx/imx-media-capture.c b/drivers/staging/media/imx/imx-media-capture.c index 256039ce561e..b37e1186eb2f 100644 --- a/drivers/staging/media/imx/imx-media-capture.c +++ b/drivers/staging/media/imx/imx-media-capture.c @@ -73,8 +73,8 @@ static int vidioc_querycap(struct file *file, void *fh, { struct capture_priv *priv = video_drvdata(file); - strlcpy(cap->driver, "imx-media-capture", sizeof(cap->driver)); - strlcpy(cap->card, "imx-media-capture", sizeof(cap->card)); + strscpy(cap->driver, "imx-media-capture", sizeof(cap->driver)); + strscpy(cap->card, "imx-media-capture", sizeof(cap->card)); snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", priv->src_sd->name); diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c index cd2c291e1e94..4223f8d418ae 100644 --- a/drivers/staging/media/imx/imx-media-csi.c +++ b/drivers/staging/media/imx/imx-media-csi.c @@ -124,7 +124,7 @@ static inline struct csi_priv *sd_to_dev(struct v4l2_subdev *sdev) static inline bool is_parallel_bus(struct v4l2_fwnode_endpoint *ep) { - return ep->bus_type != V4L2_MBUS_CSI2; + return ep->bus_type != V4L2_MBUS_CSI2_DPHY; } static inline bool is_parallel_16bit_bus(struct v4l2_fwnode_endpoint *ep) @@ -165,6 +165,9 @@ static int csi_get_upstream_endpoint(struct csi_priv *priv, struct v4l2_subdev *sd; struct media_pad *pad; + if (!IS_ENABLED(CONFIG_OF)) + return -ENXIO; + if (!priv->src_sd) return -EPIPE; @@ -1050,7 +1053,7 @@ static int csi_link_validate(struct v4l2_subdev *sd, struct v4l2_subdev_format *sink_fmt) { struct csi_priv *priv = v4l2_get_subdevdata(sd); - struct v4l2_fwnode_endpoint upstream_ep = {}; + struct v4l2_fwnode_endpoint upstream_ep = { .bus_type = 0 }; bool is_csi2; int ret; @@ -1164,7 +1167,7 @@ static int csi_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_mbus_code_enum *code) { struct csi_priv *priv = v4l2_get_subdevdata(sd); - struct v4l2_fwnode_endpoint upstream_ep; + struct v4l2_fwnode_endpoint upstream_ep = { .bus_type = 0 }; const struct imx_media_pixfmt *incc; struct v4l2_mbus_framefmt *infmt; int ret = 0; @@ -1403,7 +1406,7 @@ static int csi_set_fmt(struct v4l2_subdev *sd, { struct csi_priv *priv = v4l2_get_subdevdata(sd); struct imx_media_video_dev *vdev = priv->vdev; - struct v4l2_fwnode_endpoint upstream_ep; + struct v4l2_fwnode_endpoint upstream_ep = { .bus_type = 0 }; const struct imx_media_pixfmt *cc; struct v4l2_pix_format vdev_fmt; struct v4l2_mbus_framefmt *fmt; @@ -1542,7 +1545,7 @@ static int csi_set_selection(struct v4l2_subdev *sd, struct v4l2_subdev_selection *sel) { struct csi_priv *priv = v4l2_get_subdevdata(sd); - struct v4l2_fwnode_endpoint upstream_ep; + struct v4l2_fwnode_endpoint upstream_ep = { .bus_type = 0 }; struct v4l2_mbus_framefmt *infmt; struct v4l2_rect *crop, *compose; int pad, ret; @@ -1780,6 +1783,61 @@ static const struct v4l2_subdev_internal_ops csi_internal_ops = { .unregistered = csi_unregistered, }; +static int imx_csi_parse_endpoint(struct device *dev, + struct v4l2_fwnode_endpoint *vep, + struct v4l2_async_subdev *asd) +{ + return fwnode_device_is_available(asd->match.fwnode) ? 0 : -EINVAL; +} + +static int imx_csi_async_register(struct csi_priv *priv) +{ + struct v4l2_async_notifier *notifier; + struct fwnode_handle *fwnode; + unsigned int port; + int ret; + + notifier = kzalloc(sizeof(*notifier), GFP_KERNEL); + if (!notifier) + return -ENOMEM; + + v4l2_async_notifier_init(notifier); + + fwnode = dev_fwnode(priv->dev); + + /* get this CSI's port id */ + ret = fwnode_property_read_u32(fwnode, "reg", &port); + if (ret < 0) + goto out_free; + + ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port( + priv->dev->parent, notifier, sizeof(struct v4l2_async_subdev), + port, imx_csi_parse_endpoint); + if (ret < 0) + goto out_cleanup; + + ret = v4l2_async_subdev_notifier_register(&priv->sd, notifier); + if (ret < 0) + goto out_cleanup; + + ret = v4l2_async_register_subdev(&priv->sd); + if (ret < 0) + goto out_unregister; + + priv->sd.subdev_notifier = notifier; + + return 0; + +out_unregister: + v4l2_async_notifier_unregister(notifier); +out_cleanup: + v4l2_async_notifier_cleanup(notifier); +out_free: + kfree(notifier); + + return ret; +} + static int imx_csi_probe(struct platform_device *pdev) { struct ipu_client_platformdata *pdata; @@ -1849,7 +1907,7 @@ static int imx_csi_probe(struct platform_device *pdev) goto free; } - ret = v4l2_async_register_subdev(&priv->sd); + ret = imx_csi_async_register(priv); if (ret) goto free; diff --git a/drivers/staging/media/imx/imx-media-dev.c b/drivers/staging/media/imx/imx-media-dev.c index 3f48f5ceb6ea..026b9cbe581d 100644 --- a/drivers/staging/media/imx/imx-media-dev.c +++ b/drivers/staging/media/imx/imx-media-dev.c @@ -29,47 +29,14 @@ static inline struct imx_media_dev *notifier2dev(struct v4l2_async_notifier *n) { - return container_of(n, struct imx_media_dev, subdev_notifier); + return container_of(n, struct imx_media_dev, notifier); } /* - * Find an asd by fwnode or device name. This is called during - * driver load to form the async subdev list and bind them. - */ -static struct v4l2_async_subdev * -find_async_subdev(struct imx_media_dev *imxmd, - struct fwnode_handle *fwnode, - const char *devname) -{ - struct imx_media_async_subdev *imxasd; - struct v4l2_async_subdev *asd; - - list_for_each_entry(imxasd, &imxmd->asd_list, list) { - asd = &imxasd->asd; - switch (asd->match_type) { - case V4L2_ASYNC_MATCH_FWNODE: - if (fwnode && asd->match.fwnode == fwnode) - return asd; - break; - case V4L2_ASYNC_MATCH_DEVNAME: - if (devname && !strcmp(asd->match.device_name, - devname)) - return asd; - break; - default: - break; - } - } - - return NULL; -} - - -/* - * Adds a subdev to the async subdev list. If fwnode is non-NULL, adds - * the async as a V4L2_ASYNC_MATCH_FWNODE match type, otherwise as - * a V4L2_ASYNC_MATCH_DEVNAME match type using the dev_name of the - * given platform_device. This is called during driver load when + * Adds a subdev to the root notifier's async subdev list. If fwnode is + * non-NULL, adds the async as a V4L2_ASYNC_MATCH_FWNODE match type, + * otherwise as a V4L2_ASYNC_MATCH_DEVNAME match type using the dev_name + * of the given platform_device. This is called during driver load when * forming the async subdev list. */ int imx_media_add_async_subdev(struct imx_media_dev *imxmd, @@ -80,52 +47,43 @@ int imx_media_add_async_subdev(struct imx_media_dev *imxmd, struct imx_media_async_subdev *imxasd; struct v4l2_async_subdev *asd; const char *devname = NULL; - int ret = 0; - - mutex_lock(&imxmd->mutex); + int ret; - if (pdev) + if (fwnode) { + asd = v4l2_async_notifier_add_fwnode_subdev( + &imxmd->notifier, fwnode, sizeof(*imxasd)); + } else { devname = dev_name(&pdev->dev); - - /* return -EEXIST if this asd already added */ - if (find_async_subdev(imxmd, fwnode, devname)) { - if (np) - dev_dbg(imxmd->md.dev, "%s: already added %pOFn\n", - __func__, np); - else - dev_dbg(imxmd->md.dev, "%s: already added %s\n", - __func__, devname); - ret = -EEXIST; - goto out; + asd = v4l2_async_notifier_add_devname_subdev( + &imxmd->notifier, devname, sizeof(*imxasd)); } - imxasd = devm_kzalloc(imxmd->md.dev, sizeof(*imxasd), GFP_KERNEL); - if (!imxasd) { - ret = -ENOMEM; - goto out; + if (IS_ERR(asd)) { + ret = PTR_ERR(asd); + if (ret == -EEXIST) { + if (np) + dev_dbg(imxmd->md.dev, "%s: already added %pOFn\n", + __func__, np); + else + dev_dbg(imxmd->md.dev, "%s: already added %s\n", + __func__, devname); + } + return ret; } - asd = &imxasd->asd; - if (fwnode) { - asd->match_type = V4L2_ASYNC_MATCH_FWNODE; - asd->match.fwnode = fwnode; + imxasd = to_imx_media_asd(asd); + + if (devname) + imxasd->pdev = pdev; + + if (np) dev_dbg(imxmd->md.dev, "%s: added %pOFn, match type FWNODE\n", __func__, np); - } else { - asd->match_type = V4L2_ASYNC_MATCH_DEVNAME; - asd->match.device_name = devname; - imxasd->pdev = pdev; + else dev_dbg(imxmd->md.dev, "%s: added %s, match type DEVNAME\n", __func__, devname); - } - - list_add_tail(&imxasd->list, &imxmd->asd_list); - - imxmd->subdev_notifier.num_subdevs++; -out: - mutex_unlock(&imxmd->mutex); - return ret; + return 0; } /* @@ -180,7 +138,7 @@ out: } /* - * create the media links for all subdevs that registered async. + * Create the media links for all subdevs that registered. * Called after all async subdevs have bound. */ static int imx_media_create_links(struct v4l2_async_notifier *notifier) @@ -189,14 +147,7 @@ static int imx_media_create_links(struct v4l2_async_notifier *notifier) struct v4l2_subdev *sd; int ret; - /* - * Only links are created between subdevices that are known - * to the async notifier. If there are other non-async subdevices, - * they were created internally by some subdevice (smiapp is one - * example). In those cases it is expected the subdevice is - * responsible for creating those internal links. - */ - list_for_each_entry(sd, ¬ifier->done, async_list) { + list_for_each_entry(sd, &imxmd->v4l2_dev.subdevs, list) { switch (sd->grp_id) { case IMX_MEDIA_GRP_ID_VDIC: case IMX_MEDIA_GRP_ID_IC_PRP: @@ -216,7 +167,10 @@ static int imx_media_create_links(struct v4l2_async_notifier *notifier) imx_media_create_csi_of_links(imxmd, sd); break; default: - /* this is an external fwnode subdev */ + /* + * if this subdev has fwnode links, create media + * links for them. + */ imx_media_create_of_links(imxmd, sd); break; } @@ -492,10 +446,8 @@ static int imx_media_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *node = dev->of_node; - struct imx_media_async_subdev *imxasd; - struct v4l2_async_subdev **subdevs; struct imx_media_dev *imxmd; - int num_subdevs, i, ret; + int ret; imxmd = devm_kzalloc(dev, sizeof(*imxmd), GFP_KERNEL); if (!imxmd) @@ -503,14 +455,14 @@ static int imx_media_probe(struct platform_device *pdev) dev_set_drvdata(dev, imxmd); - strlcpy(imxmd->md.model, "imx-media", sizeof(imxmd->md.model)); + strscpy(imxmd->md.model, "imx-media", sizeof(imxmd->md.model)); imxmd->md.ops = &imx_media_md_ops; imxmd->md.dev = dev; mutex_init(&imxmd->mutex); imxmd->v4l2_dev.mdev = &imxmd->md; - strlcpy(imxmd->v4l2_dev.name, "imx-media", + strscpy(imxmd->v4l2_dev.name, "imx-media", sizeof(imxmd->v4l2_dev.name)); media_device_init(&imxmd->md); @@ -524,47 +476,34 @@ static int imx_media_probe(struct platform_device *pdev) dev_set_drvdata(imxmd->v4l2_dev.dev, imxmd); - INIT_LIST_HEAD(&imxmd->asd_list); INIT_LIST_HEAD(&imxmd->vdev_list); + v4l2_async_notifier_init(&imxmd->notifier); + ret = imx_media_add_of_subdevs(imxmd, node); if (ret) { v4l2_err(&imxmd->v4l2_dev, "add_of_subdevs failed with %d\n", ret); - goto unreg_dev; + goto notifier_cleanup; } ret = imx_media_add_internal_subdevs(imxmd); if (ret) { v4l2_err(&imxmd->v4l2_dev, "add_internal_subdevs failed with %d\n", ret); - goto unreg_dev; + goto notifier_cleanup; } - num_subdevs = imxmd->subdev_notifier.num_subdevs; - /* no subdevs? just bail */ - if (num_subdevs == 0) { + if (list_empty(&imxmd->notifier.asd_list)) { ret = -ENODEV; - goto unreg_dev; + goto notifier_cleanup; } - subdevs = devm_kcalloc(imxmd->md.dev, num_subdevs, sizeof(*subdevs), - GFP_KERNEL); - if (!subdevs) { - ret = -ENOMEM; - goto unreg_dev; - } - - i = 0; - list_for_each_entry(imxasd, &imxmd->asd_list, list) - subdevs[i++] = &imxasd->asd; - /* prepare the async subdev notifier and register it */ - imxmd->subdev_notifier.subdevs = subdevs; - imxmd->subdev_notifier.ops = &imx_media_subdev_ops; + imxmd->notifier.ops = &imx_media_subdev_ops; ret = v4l2_async_notifier_register(&imxmd->v4l2_dev, - &imxmd->subdev_notifier); + &imxmd->notifier); if (ret) { v4l2_err(&imxmd->v4l2_dev, "v4l2_async_notifier_register failed with %d\n", ret); @@ -575,7 +514,8 @@ static int imx_media_probe(struct platform_device *pdev) del_int: imx_media_remove_internal_subdevs(imxmd); -unreg_dev: +notifier_cleanup: + v4l2_async_notifier_cleanup(&imxmd->notifier); v4l2_device_unregister(&imxmd->v4l2_dev); cleanup: media_device_cleanup(&imxmd->md); @@ -589,8 +529,9 @@ static int imx_media_remove(struct platform_device *pdev) v4l2_info(&imxmd->v4l2_dev, "Removing imx-media\n"); - v4l2_async_notifier_unregister(&imxmd->subdev_notifier); + v4l2_async_notifier_unregister(&imxmd->notifier); imx_media_remove_internal_subdevs(imxmd); + v4l2_async_notifier_cleanup(&imxmd->notifier); v4l2_device_unregister(&imxmd->v4l2_dev); media_device_unregister(&imxmd->md); media_device_cleanup(&imxmd->md); diff --git a/drivers/staging/media/imx/imx-media-internal-sd.c b/drivers/staging/media/imx/imx-media-internal-sd.c index daf66c2d69ab..0fdc45dbfb76 100644 --- a/drivers/staging/media/imx/imx-media-internal-sd.c +++ b/drivers/staging/media/imx/imx-media-internal-sd.c @@ -350,8 +350,11 @@ remove: void imx_media_remove_internal_subdevs(struct imx_media_dev *imxmd) { struct imx_media_async_subdev *imxasd; + struct v4l2_async_subdev *asd; + + list_for_each_entry(asd, &imxmd->notifier.asd_list, asd_list) { + imxasd = to_imx_media_asd(asd); - list_for_each_entry(imxasd, &imxmd->asd_list, list) { if (!imxasd->pdev) continue; diff --git a/drivers/staging/media/imx/imx-media-of.c b/drivers/staging/media/imx/imx-media-of.c index 163437e421c5..b2e840f96c50 100644 --- a/drivers/staging/media/imx/imx-media-of.c +++ b/drivers/staging/media/imx/imx-media-of.c @@ -20,74 +20,19 @@ #include <video/imx-ipu-v3.h> #include "imx-media.h" -static int of_get_port_count(const struct device_node *np) +static int of_add_csi(struct imx_media_dev *imxmd, struct device_node *csi_np) { - struct device_node *ports, *child; - int num = 0; - - /* check if this node has a ports subnode */ - ports = of_get_child_by_name(np, "ports"); - if (ports) - np = ports; - - for_each_child_of_node(np, child) - if (of_node_cmp(child->name, "port") == 0) - num++; - - of_node_put(ports); - return num; -} - -/* - * find the remote device node given local endpoint node - */ -static bool of_get_remote(struct device_node *epnode, - struct device_node **remote_node) -{ - struct device_node *rp, *rpp; - struct device_node *remote; - bool is_csi_port; - - rp = of_graph_get_remote_port(epnode); - rpp = of_graph_get_remote_port_parent(epnode); - - if (of_device_is_compatible(rpp, "fsl,imx6q-ipu")) { - /* the remote is one of the CSI ports */ - remote = rp; - of_node_put(rpp); - is_csi_port = true; - } else { - remote = rpp; - of_node_put(rp); - is_csi_port = false; - } - - if (!of_device_is_available(remote)) { - of_node_put(remote); - *remote_node = NULL; - } else { - *remote_node = remote; - } - - return is_csi_port; -} - -static int -of_parse_subdev(struct imx_media_dev *imxmd, struct device_node *sd_np, - bool is_csi_port) -{ - int i, num_ports, ret; + int ret; - if (!of_device_is_available(sd_np)) { + if (!of_device_is_available(csi_np)) { dev_dbg(imxmd->md.dev, "%s: %pOFn not enabled\n", __func__, - sd_np); + csi_np); /* unavailable is not an error */ return 0; } - /* register this subdev with async notifier */ - ret = imx_media_add_async_subdev(imxmd, of_fwnode_handle(sd_np), - NULL); + /* add CSI fwnode to async notifier */ + ret = imx_media_add_async_subdev(imxmd, of_fwnode_handle(csi_np), NULL); if (ret) { if (ret == -EEXIST) { /* already added, everything is fine */ @@ -98,42 +43,7 @@ of_parse_subdev(struct imx_media_dev *imxmd, struct device_node *sd_np, return ret; } - /* - * the ipu-csi has one sink port. The source pads are not - * represented in the device tree by port nodes, but are - * described by the internal pads and links later. - */ - num_ports = is_csi_port ? 1 : of_get_port_count(sd_np); - - for (i = 0; i < num_ports; i++) { - struct device_node *epnode = NULL, *port, *remote_np; - - port = is_csi_port ? sd_np : of_graph_get_port_by_id(sd_np, i); - if (!port) - continue; - - for_each_child_of_node(port, epnode) { - bool remote_is_csi; - - remote_is_csi = of_get_remote(epnode, &remote_np); - if (!remote_np) - continue; - - ret = of_parse_subdev(imxmd, remote_np, remote_is_csi); - of_node_put(remote_np); - if (ret) - break; - } - - if (port != sd_np) - of_node_put(port); - if (ret) { - of_node_put(epnode); - break; - } - } - - return ret; + return 0; } int imx_media_add_of_subdevs(struct imx_media_dev *imxmd, @@ -147,7 +57,7 @@ int imx_media_add_of_subdevs(struct imx_media_dev *imxmd, if (!csi_np) break; - ret = of_parse_subdev(imxmd, csi_np, true); + ret = of_add_csi(imxmd, csi_np); of_node_put(csi_np); if (ret) return ret; diff --git a/drivers/staging/media/imx/imx-media-utils.c b/drivers/staging/media/imx/imx-media-utils.c index 8aa13403b09d..0eaa353d5cb3 100644 --- a/drivers/staging/media/imx/imx-media-utils.c +++ b/drivers/staging/media/imx/imx-media-utils.c @@ -88,7 +88,7 @@ static const struct imx_media_pixfmt rgb_formats[] = { .cs = IPUV3_COLORSPACE_RGB, .bpp = 24, }, { - .fourcc = V4L2_PIX_FMT_RGB32, + .fourcc = V4L2_PIX_FMT_XRGB32, .codes = {MEDIA_BUS_FMT_ARGB8888_1X32}, .cs = IPUV3_COLORSPACE_RGB, .bpp = 32, @@ -212,7 +212,7 @@ static const struct imx_media_pixfmt ipu_yuv_formats[] = { static const struct imx_media_pixfmt ipu_rgb_formats[] = { { - .fourcc = V4L2_PIX_FMT_RGB32, + .fourcc = V4L2_PIX_FMT_XRGB32, .codes = {MEDIA_BUS_FMT_ARGB8888_1X32}, .cs = IPUV3_COLORSPACE_RGB, .bpp = 32, diff --git a/drivers/staging/media/imx/imx-media.h b/drivers/staging/media/imx/imx-media.h index 57bd094cf765..bc7feb81937c 100644 --- a/drivers/staging/media/imx/imx-media.h +++ b/drivers/staging/media/imx/imx-media.h @@ -119,12 +119,11 @@ struct imx_media_internal_sd_platformdata { int ipu_id; }; - struct imx_media_async_subdev { + /* the base asd - must be first in this struct */ struct v4l2_async_subdev asd; /* the platform device of IPU-internal subdevs */ struct platform_device *pdev; - struct list_head list; }; static inline struct imx_media_async_subdev * @@ -149,8 +148,7 @@ struct imx_media_dev { struct ipu_soc *ipu[2]; /* for async subdev registration */ - struct list_head asd_list; - struct v4l2_async_notifier subdev_notifier; + struct v4l2_async_notifier notifier; }; enum codespace_sel { diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c index ceeeb3069a02..6a1cee55a49b 100644 --- a/drivers/staging/media/imx/imx6-mipi-csi2.c +++ b/drivers/staging/media/imx/imx6-mipi-csi2.c @@ -551,35 +551,34 @@ static const struct v4l2_subdev_internal_ops csi2_internal_ops = { .registered = csi2_registered, }; -static int csi2_parse_endpoints(struct csi2_dev *csi2) +static int csi2_parse_endpoint(struct device *dev, + struct v4l2_fwnode_endpoint *vep, + struct v4l2_async_subdev *asd) { - struct device_node *node = csi2->dev->of_node; - struct device_node *epnode; - struct v4l2_fwnode_endpoint ep; + struct v4l2_subdev *sd = dev_get_drvdata(dev); + struct csi2_dev *csi2 = sd_to_dev(sd); - epnode = of_graph_get_endpoint_by_regs(node, 0, -1); - if (!epnode) { - v4l2_err(&csi2->sd, "failed to get sink endpoint node\n"); + if (!fwnode_device_is_available(asd->match.fwnode)) { + v4l2_err(&csi2->sd, "remote is not available\n"); return -EINVAL; } - v4l2_fwnode_endpoint_parse(of_fwnode_handle(epnode), &ep); - of_node_put(epnode); - - if (ep.bus_type != V4L2_MBUS_CSI2) { + if (vep->bus_type != V4L2_MBUS_CSI2_DPHY) { v4l2_err(&csi2->sd, "invalid bus type, must be MIPI CSI2\n"); return -EINVAL; } - csi2->bus = ep.bus.mipi_csi2; + csi2->bus = vep->bus.mipi_csi2; dev_dbg(csi2->dev, "data lanes: %d\n", csi2->bus.num_data_lanes); dev_dbg(csi2->dev, "flags: 0x%08x\n", csi2->bus.flags); + return 0; } static int csi2_probe(struct platform_device *pdev) { + unsigned int sink_port = 0; struct csi2_dev *csi2; struct resource *res; int ret; @@ -597,14 +596,10 @@ static int csi2_probe(struct platform_device *pdev) csi2->sd.dev = &pdev->dev; csi2->sd.owner = THIS_MODULE; csi2->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; - strcpy(csi2->sd.name, DEVICE_NAME); + strscpy(csi2->sd.name, DEVICE_NAME, sizeof(csi2->sd.name)); csi2->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; csi2->sd.grp_id = IMX_MEDIA_GRP_ID_CSI2; - ret = csi2_parse_endpoints(csi2); - if (ret) - return ret; - csi2->pllref_clk = devm_clk_get(&pdev->dev, "ref"); if (IS_ERR(csi2->pllref_clk)) { v4l2_err(&csi2->sd, "failed to get pll reference clock\n"); @@ -654,7 +649,9 @@ static int csi2_probe(struct platform_device *pdev) platform_set_drvdata(pdev, &csi2->sd); - ret = v4l2_async_register_subdev(&csi2->sd); + ret = v4l2_async_register_fwnode_subdev( + &csi2->sd, sizeof(struct v4l2_async_subdev), + &sink_port, 1, csi2_parse_endpoint); if (ret) goto dphy_off; diff --git a/drivers/staging/media/imx074/imx074.c b/drivers/staging/media/imx074/imx074.c index 77f1e0243d6e..1676c166dc83 100644 --- a/drivers/staging/media/imx074/imx074.c +++ b/drivers/staging/media/imx074/imx074.c @@ -223,7 +223,6 @@ static int imx074_get_selection(struct v4l2_subdev *sd, switch (sel->target) { case V4L2_SEL_TGT_CROP_BOUNDS: - case V4L2_SEL_TGT_CROP_DEFAULT: case V4L2_SEL_TGT_CROP: return 0; default: @@ -263,7 +262,7 @@ static int imx074_s_power(struct v4l2_subdev *sd, int on) static int imx074_g_mbus_config(struct v4l2_subdev *sd, struct v4l2_mbus_config *cfg) { - cfg->type = V4L2_MBUS_CSI2; + cfg->type = V4L2_MBUS_CSI2_DPHY; cfg->flags = V4L2_MBUS_CSI2_2_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; diff --git a/drivers/staging/media/mt9t031/mt9t031.c b/drivers/staging/media/mt9t031/mt9t031.c index 4802d30e47de..4ff179302b4f 100644 --- a/drivers/staging/media/mt9t031/mt9t031.c +++ b/drivers/staging/media/mt9t031/mt9t031.c @@ -330,7 +330,6 @@ static int mt9t031_get_selection(struct v4l2_subdev *sd, switch (sel->target) { case V4L2_SEL_TGT_CROP_BOUNDS: - case V4L2_SEL_TGT_CROP_DEFAULT: sel->r.left = MT9T031_COLUMN_SKIP; sel->r.top = MT9T031_ROW_SKIP; sel->r.width = MT9T031_MAX_WIDTH; diff --git a/drivers/staging/media/omap4iss/Kconfig b/drivers/staging/media/omap4iss/Kconfig index dddd27335cb4..841cc0b3ce13 100644 --- a/drivers/staging/media/omap4iss/Kconfig +++ b/drivers/staging/media/omap4iss/Kconfig @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 + config VIDEO_OMAP4 tristate "OMAP 4 Camera support" depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && I2C diff --git a/drivers/staging/media/omap4iss/Makefile b/drivers/staging/media/omap4iss/Makefile index a716ce936cf6..e64d489a4a76 100644 --- a/drivers/staging/media/omap4iss/Makefile +++ b/drivers/staging/media/omap4iss/Makefile @@ -1,4 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0 +# # Makefile for OMAP4 ISS driver +# omap4-iss-objs += \ iss.o iss_csi2.o iss_csiphy.o iss_ipipeif.o iss_ipipe.o iss_resizer.o iss_video.o diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c index b1036baebb03..c8be1db532ab 100644 --- a/drivers/staging/media/omap4iss/iss.c +++ b/drivers/staging/media/omap4iss/iss.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * TI OMAP4 ISS V4L2 Driver * * Copyright (C) 2012, Texas Instruments * * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #include <linux/clk.h> @@ -989,7 +985,7 @@ static int iss_register_entities(struct iss_device *iss) int ret; iss->media_dev.dev = iss->dev; - strlcpy(iss->media_dev.model, "TI OMAP4 ISS", + strscpy(iss->media_dev.model, "TI OMAP4 ISS", sizeof(iss->media_dev.model)); iss->media_dev.hw_revision = iss->revision; iss->media_dev.ops = &iss_media_ops; diff --git a/drivers/staging/media/omap4iss/iss.h b/drivers/staging/media/omap4iss/iss.h index 760ee27da704..b88f9529683c 100644 --- a/drivers/staging/media/omap4iss/iss.h +++ b/drivers/staging/media/omap4iss/iss.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * TI OMAP4 ISS V4L2 Driver * * Copyright (C) 2012 Texas Instruments. * * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #ifndef _OMAP4_ISS_H_ diff --git a/drivers/staging/media/omap4iss/iss_csi2.c b/drivers/staging/media/omap4iss/iss_csi2.c index f6acc541e8a2..059cf5bd3c36 100644 --- a/drivers/staging/media/omap4iss/iss_csi2.c +++ b/drivers/staging/media/omap4iss/iss_csi2.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * TI OMAP4 ISS V4L2 Driver - CSI PHY module * * Copyright (C) 2012 Texas Instruments, Inc. * * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #include <linux/delay.h> diff --git a/drivers/staging/media/omap4iss/iss_csi2.h b/drivers/staging/media/omap4iss/iss_csi2.h index 24ab378d469f..3f7fd9cff41d 100644 --- a/drivers/staging/media/omap4iss/iss_csi2.h +++ b/drivers/staging/media/omap4iss/iss_csi2.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * TI OMAP4 ISS V4L2 Driver - CSI2 module * * Copyright (C) 2012 Texas Instruments, Inc. * * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #ifndef OMAP4_ISS_CSI2_H diff --git a/drivers/staging/media/omap4iss/iss_csiphy.c b/drivers/staging/media/omap4iss/iss_csiphy.c index 748607f8918f..96f2ce045138 100644 --- a/drivers/staging/media/omap4iss/iss_csiphy.c +++ b/drivers/staging/media/omap4iss/iss_csiphy.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * TI OMAP4 ISS V4L2 Driver - CSI PHY module * * Copyright (C) 2012 Texas Instruments, Inc. * * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #include <linux/delay.h> diff --git a/drivers/staging/media/omap4iss/iss_csiphy.h b/drivers/staging/media/omap4iss/iss_csiphy.h index a0f2d974daeb..44408e4fcf3b 100644 --- a/drivers/staging/media/omap4iss/iss_csiphy.h +++ b/drivers/staging/media/omap4iss/iss_csiphy.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * TI OMAP4 ISS V4L2 Driver - CSI PHY module * * Copyright (C) 2012 Texas Instruments, Inc. * * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #ifndef OMAP4_ISS_CSI_PHY_H diff --git a/drivers/staging/media/omap4iss/iss_ipipe.c b/drivers/staging/media/omap4iss/iss_ipipe.c index d86ef8a031f2..26be078b69f3 100644 --- a/drivers/staging/media/omap4iss/iss_ipipe.c +++ b/drivers/staging/media/omap4iss/iss_ipipe.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * TI OMAP4 ISS V4L2 Driver - ISP IPIPE module * * Copyright (C) 2012 Texas Instruments, Inc. * * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #include <linux/module.h> @@ -507,7 +503,7 @@ static int ipipe_init_entities(struct iss_ipipe_device *ipipe) v4l2_subdev_init(sd, &ipipe_v4l2_ops); sd->internal_ops = &ipipe_v4l2_internal_ops; - strlcpy(sd->name, "OMAP4 ISS ISP IPIPE", sizeof(sd->name)); + strscpy(sd->name, "OMAP4 ISS ISP IPIPE", sizeof(sd->name)); sd->grp_id = BIT(16); /* group ID for iss subdevs */ v4l2_set_subdevdata(sd, ipipe); sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; diff --git a/drivers/staging/media/omap4iss/iss_ipipe.h b/drivers/staging/media/omap4iss/iss_ipipe.h index d5b441d9cb31..53b42aac1696 100644 --- a/drivers/staging/media/omap4iss/iss_ipipe.h +++ b/drivers/staging/media/omap4iss/iss_ipipe.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * TI OMAP4 ISS V4L2 Driver - ISP IPIPE module * * Copyright (C) 2012 Texas Instruments, Inc. * * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #ifndef OMAP4_ISS_IPIPE_H diff --git a/drivers/staging/media/omap4iss/iss_ipipeif.c b/drivers/staging/media/omap4iss/iss_ipipeif.c index cb88b2bd0d82..c2978d02e797 100644 --- a/drivers/staging/media/omap4iss/iss_ipipeif.c +++ b/drivers/staging/media/omap4iss/iss_ipipeif.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * TI OMAP4 ISS V4L2 Driver - ISP IPIPEIF module * * Copyright (C) 2012 Texas Instruments, Inc. * * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #include <linux/module.h> @@ -738,7 +734,7 @@ static int ipipeif_init_entities(struct iss_ipipeif_device *ipipeif) v4l2_subdev_init(sd, &ipipeif_v4l2_ops); sd->internal_ops = &ipipeif_v4l2_internal_ops; - strlcpy(sd->name, "OMAP4 ISS ISP IPIPEIF", sizeof(sd->name)); + strscpy(sd->name, "OMAP4 ISS ISP IPIPEIF", sizeof(sd->name)); sd->grp_id = BIT(16); /* group ID for iss subdevs */ v4l2_set_subdevdata(sd, ipipeif); sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; diff --git a/drivers/staging/media/omap4iss/iss_ipipeif.h b/drivers/staging/media/omap4iss/iss_ipipeif.h index bad32b1d6ad8..69792333a62e 100644 --- a/drivers/staging/media/omap4iss/iss_ipipeif.h +++ b/drivers/staging/media/omap4iss/iss_ipipeif.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * TI OMAP4 ISS V4L2 Driver - ISP IPIPEIF module * * Copyright (C) 2012 Texas Instruments, Inc. * * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #ifndef OMAP4_ISS_IPIPEIF_H diff --git a/drivers/staging/media/omap4iss/iss_regs.h b/drivers/staging/media/omap4iss/iss_regs.h index cb415e898aca..09a7375c89ac 100644 --- a/drivers/staging/media/omap4iss/iss_regs.h +++ b/drivers/staging/media/omap4iss/iss_regs.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * TI OMAP4 ISS V4L2 Driver - Register defines * * Copyright (C) 2012 Texas Instruments. * * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #ifndef _OMAP4_ISS_REGS_H_ diff --git a/drivers/staging/media/omap4iss/iss_resizer.c b/drivers/staging/media/omap4iss/iss_resizer.c index 4bbfa20b3c38..3b6875cbca9b 100644 --- a/drivers/staging/media/omap4iss/iss_resizer.c +++ b/drivers/staging/media/omap4iss/iss_resizer.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * TI OMAP4 ISS V4L2 Driver - ISP RESIZER module * * Copyright (C) 2012 Texas Instruments, Inc. * * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #include <linux/module.h> @@ -781,7 +777,7 @@ static int resizer_init_entities(struct iss_resizer_device *resizer) v4l2_subdev_init(sd, &resizer_v4l2_ops); sd->internal_ops = &resizer_v4l2_internal_ops; - strlcpy(sd->name, "OMAP4 ISS ISP resizer", sizeof(sd->name)); + strscpy(sd->name, "OMAP4 ISS ISP resizer", sizeof(sd->name)); sd->grp_id = BIT(16); /* group ID for iss subdevs */ v4l2_set_subdevdata(sd, resizer); sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; diff --git a/drivers/staging/media/omap4iss/iss_resizer.h b/drivers/staging/media/omap4iss/iss_resizer.h index 8b7c5fe9ffed..cb937fccc21f 100644 --- a/drivers/staging/media/omap4iss/iss_resizer.h +++ b/drivers/staging/media/omap4iss/iss_resizer.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * TI OMAP4 ISS V4L2 Driver - ISP RESIZER module * * Copyright (C) 2012 Texas Instruments, Inc. * * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #ifndef OMAP4_ISS_RESIZER_H diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c index 16478fe9e3f8..c1322aeaf01e 100644 --- a/drivers/staging/media/omap4iss/iss_video.c +++ b/drivers/staging/media/omap4iss/iss_video.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * TI OMAP4 ISS V4L2 Driver - Generic video node * * Copyright (C) 2012 Texas Instruments, Inc. * * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #include <linux/clk.h> @@ -534,9 +530,9 @@ iss_video_querycap(struct file *file, void *fh, struct v4l2_capability *cap) { struct iss_video *video = video_drvdata(file); - strlcpy(cap->driver, ISS_VIDEO_DRIVER_NAME, sizeof(cap->driver)); - strlcpy(cap->card, video->video.name, sizeof(cap->card)); - strlcpy(cap->bus_info, "media", sizeof(cap->bus_info)); + strscpy(cap->driver, ISS_VIDEO_DRIVER_NAME, sizeof(cap->driver)); + strscpy(cap->card, video->video.name, sizeof(cap->card)); + strscpy(cap->bus_info, "media", sizeof(cap->bus_info)); if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; @@ -573,7 +569,7 @@ iss_video_enum_format(struct file *file, void *fh, struct v4l2_fmtdesc *f) if (index == 0) { f->pixelformat = info->pixelformat; - strlcpy(f->description, info->description, + strscpy(f->description, info->description, sizeof(f->description)); return 0; } @@ -1053,7 +1049,7 @@ iss_video_enum_input(struct file *file, void *fh, struct v4l2_input *input) if (input->index > 0) return -EINVAL; - strlcpy(input->name, "camera", sizeof(input->name)); + strscpy(input->name, "camera", sizeof(input->name)); input->type = V4L2_INPUT_TYPE_CAMERA; return 0; diff --git a/drivers/staging/media/omap4iss/iss_video.h b/drivers/staging/media/omap4iss/iss_video.h index d7e05d04512c..f22489edb562 100644 --- a/drivers/staging/media/omap4iss/iss_video.h +++ b/drivers/staging/media/omap4iss/iss_video.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * TI OMAP4 ISS V4L2 Driver - Generic video node * * Copyright (C) 2012 Texas Instruments, Inc. * * Author: Sergio Aguirre <sergio.a.aguirre@gmail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #ifndef OMAP4_ISS_VIDEO_H diff --git a/drivers/staging/media/zoran/zoran_card.c b/drivers/staging/media/zoran/zoran_card.c index a6b9ebd20263..94dadbba7cd5 100644 --- a/drivers/staging/media/zoran/zoran_card.c +++ b/drivers/staging/media/zoran/zoran_card.c @@ -706,7 +706,7 @@ zoran_register_i2c (struct zoran *zr) { zr->i2c_algo = zoran_i2c_bit_data_template; zr->i2c_algo.data = zr; - strlcpy(zr->i2c_adapter.name, ZR_DEVNAME(zr), + strscpy(zr->i2c_adapter.name, ZR_DEVNAME(zr), sizeof(zr->i2c_adapter.name)); i2c_set_adapdata(&zr->i2c_adapter, &zr->v4l2_dev); zr->i2c_adapter.algo_data = &zr->i2c_algo; @@ -1048,7 +1048,7 @@ static int zr36057_init (struct zoran *zr) *zr->video_dev = zoran_template; zr->video_dev->v4l2_dev = &zr->v4l2_dev; zr->video_dev->lock = &zr->lock; - strcpy(zr->video_dev->name, ZR_DEVNAME(zr)); + strscpy(zr->video_dev->name, ZR_DEVNAME(zr), sizeof(zr->video_dev->name)); /* It's not a mem2mem device, but you can both capture and output from one and the same device. This should really be split up into two device nodes, but that's a job for another day. */ @@ -1145,7 +1145,7 @@ static struct videocodec_master *zoran_setup_videocodec(struct zoran *zr, m->type = 0; m->flags = CODEC_FLAG_ENCODER | CODEC_FLAG_DECODER; - strlcpy(m->name, ZR_DEVNAME(zr), sizeof(m->name)); + strscpy(m->name, ZR_DEVNAME(zr), sizeof(m->name)); m->data = zr; switch (type) diff --git a/drivers/staging/media/zoran/zoran_driver.c b/drivers/staging/media/zoran/zoran_driver.c index d7842224fff6..27c76e2eeb41 100644 --- a/drivers/staging/media/zoran/zoran_driver.c +++ b/drivers/staging/media/zoran/zoran_driver.c @@ -692,7 +692,7 @@ static int zoran_jpg_queue_frame(struct zoran_fh *fh, int num, case BUZ_STATE_DONE: dprintk(2, KERN_WARNING - "%s: %s - queing frame in BUZ_STATE_DONE state!?\n", + "%s: %s - queuing frame in BUZ_STATE_DONE state!?\n", ZR_DEVNAME(zr), __func__); /* fall through */ case BUZ_STATE_USER: @@ -1510,8 +1510,8 @@ static int zoran_querycap(struct file *file, void *__fh, struct v4l2_capability struct zoran_fh *fh = __fh; struct zoran *zr = fh->zr; - strlcpy(cap->card, ZR_DEVNAME(zr), sizeof(cap->card)); - strlcpy(cap->driver, "zoran", sizeof(cap->driver)); + strscpy(cap->card, ZR_DEVNAME(zr), sizeof(cap->card)); + strscpy(cap->driver, "zoran", sizeof(cap->driver)); snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", pci_name(zr->pci_dev)); cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE | diff --git a/drivers/video/backlight/as3711_bl.c b/drivers/video/backlight/as3711_bl.c index ca544aa764b8..33f0f0f2e8b3 100644 --- a/drivers/video/backlight/as3711_bl.c +++ b/drivers/video/backlight/as3711_bl.c @@ -1,12 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 /* * AS3711 PMIC backlight driver, using DCDC Step Up Converters * * Copyright (C) 2012 Renesas Electronics Corporation * Author: Guennadi Liakhovetski, <g.liakhovetski@gmx.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the version 2 of the GNU General Public License as - * published by the Free Software Foundation */ #include <linux/backlight.h> @@ -488,5 +485,5 @@ module_platform_driver(as3711_backlight_driver); MODULE_DESCRIPTION("Backlight Driver for AS3711 PMICs"); MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:as3711-backlight"); diff --git a/drivers/video/fbdev/sh7760fb.c b/drivers/video/fbdev/sh7760fb.c index 96de91d76623..405715b60ec7 100644 --- a/drivers/video/fbdev/sh7760fb.c +++ b/drivers/video/fbdev/sh7760fb.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * SH7760/SH7763 LCDC Framebuffer driver. * @@ -5,10 +6,6 @@ * Manuel Lauss <mano@roarinelk.homelinux.net> * (c) 2008 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com> * - * This file is subject to the terms and conditions of the GNU General - * Public License. See the file COPYING in the main directory of this - * archive for more details. - * * PLEASE HAVE A LOOK AT Documentation/fb/sh7760fb.txt! * * Thanks to Siegfried Schaefer <s.schaefer at schaefer-edv.de> @@ -587,4 +584,4 @@ module_platform_driver(sh7760_lcdc_driver); MODULE_AUTHOR("Nobuhiro Iwamatsu, Manuel Lauss"); MODULE_DESCRIPTION("FBdev for SH7760/63 integrated LCD Controller"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c index 38716eb50408..8a3e8f61b991 100644 --- a/drivers/video/hdmi.c +++ b/drivers/video/hdmi.c @@ -592,10 +592,10 @@ hdmi_extended_colorimetry_get_name(enum hdmi_extended_colorimetry ext_col) return "xvYCC 709"; case HDMI_EXTENDED_COLORIMETRY_S_YCC_601: return "sYCC 601"; - case HDMI_EXTENDED_COLORIMETRY_ADOBE_YCC_601: - return "Adobe YCC 601"; - case HDMI_EXTENDED_COLORIMETRY_ADOBE_RGB: - return "Adobe RGB"; + case HDMI_EXTENDED_COLORIMETRY_OPYCC_601: + return "opYCC 601"; + case HDMI_EXTENDED_COLORIMETRY_OPRGB: + return "opRGB"; case HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM: return "BT.2020 Constant Luminance"; case HDMI_EXTENDED_COLORIMETRY_BT2020: diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index ce2cc2169040..6e30949d9f77 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -64,11 +64,6 @@ #include <linux/hiddev.h> -#define __DVB_CORE__ -#include <linux/dvb/audio.h> -#include <linux/dvb/dmx.h> -#include <linux/dvb/frontend.h> -#include <linux/dvb/video.h> #include <linux/sort.h> @@ -95,71 +90,6 @@ static int do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return vfs_ioctl(file, cmd, arg); } -struct compat_video_event { - int32_t type; - compat_time_t timestamp; - union { - video_size_t size; - unsigned int frame_rate; - } u; -}; - -static int do_video_get_event(struct file *file, - unsigned int cmd, struct compat_video_event __user *up) -{ - struct video_event __user *kevent = - compat_alloc_user_space(sizeof(*kevent)); - int err; - - if (kevent == NULL) - return -EFAULT; - - err = do_ioctl(file, cmd, (unsigned long)kevent); - if (!err) { - err = convert_in_user(&kevent->type, &up->type); - err |= convert_in_user(&kevent->timestamp, &up->timestamp); - err |= convert_in_user(&kevent->u.size.w, &up->u.size.w); - err |= convert_in_user(&kevent->u.size.h, &up->u.size.h); - err |= convert_in_user(&kevent->u.size.aspect_ratio, - &up->u.size.aspect_ratio); - if (err) - err = -EFAULT; - } - - return err; -} - -struct compat_video_still_picture { - compat_uptr_t iFrame; - int32_t size; -}; - -static int do_video_stillpicture(struct file *file, - unsigned int cmd, struct compat_video_still_picture __user *up) -{ - struct video_still_picture __user *up_native; - compat_uptr_t fp; - int32_t size; - int err; - - err = get_user(fp, &up->iFrame); - err |= get_user(size, &up->size); - if (err) - return -EFAULT; - - up_native = - compat_alloc_user_space(sizeof(struct video_still_picture)); - - err = put_user(compat_ptr(fp), &up_native->iFrame); - err |= put_user(size, &up_native->size); - if (err) - return -EFAULT; - - err = do_ioctl(file, cmd, (unsigned long) up_native); - - return err; -} - #ifdef CONFIG_BLOCK typedef struct sg_io_hdr32 { compat_int_t interface_id; /* [i] 'S' for SCSI generic (required) */ @@ -958,61 +888,6 @@ COMPATIBLE_IOCTL(HIDIOCGFLAG) COMPATIBLE_IOCTL(HIDIOCSFLAG) COMPATIBLE_IOCTL(HIDIOCGCOLLECTIONINDEX) COMPATIBLE_IOCTL(HIDIOCGCOLLECTIONINFO) -/* dvb */ -COMPATIBLE_IOCTL(AUDIO_STOP) -COMPATIBLE_IOCTL(AUDIO_PLAY) -COMPATIBLE_IOCTL(AUDIO_PAUSE) -COMPATIBLE_IOCTL(AUDIO_CONTINUE) -COMPATIBLE_IOCTL(AUDIO_SELECT_SOURCE) -COMPATIBLE_IOCTL(AUDIO_SET_MUTE) -COMPATIBLE_IOCTL(AUDIO_SET_AV_SYNC) -COMPATIBLE_IOCTL(AUDIO_SET_BYPASS_MODE) -COMPATIBLE_IOCTL(AUDIO_CHANNEL_SELECT) -COMPATIBLE_IOCTL(AUDIO_GET_STATUS) -COMPATIBLE_IOCTL(AUDIO_GET_CAPABILITIES) -COMPATIBLE_IOCTL(AUDIO_CLEAR_BUFFER) -COMPATIBLE_IOCTL(AUDIO_SET_ID) -COMPATIBLE_IOCTL(AUDIO_SET_MIXER) -COMPATIBLE_IOCTL(AUDIO_SET_STREAMTYPE) -COMPATIBLE_IOCTL(DMX_START) -COMPATIBLE_IOCTL(DMX_STOP) -COMPATIBLE_IOCTL(DMX_SET_FILTER) -COMPATIBLE_IOCTL(DMX_SET_PES_FILTER) -COMPATIBLE_IOCTL(DMX_SET_BUFFER_SIZE) -COMPATIBLE_IOCTL(DMX_GET_PES_PIDS) -COMPATIBLE_IOCTL(DMX_GET_STC) -COMPATIBLE_IOCTL(DMX_REQBUFS) -COMPATIBLE_IOCTL(DMX_QUERYBUF) -COMPATIBLE_IOCTL(DMX_EXPBUF) -COMPATIBLE_IOCTL(DMX_QBUF) -COMPATIBLE_IOCTL(DMX_DQBUF) -COMPATIBLE_IOCTL(VIDEO_STOP) -COMPATIBLE_IOCTL(VIDEO_PLAY) -COMPATIBLE_IOCTL(VIDEO_FREEZE) -COMPATIBLE_IOCTL(VIDEO_CONTINUE) -COMPATIBLE_IOCTL(VIDEO_SELECT_SOURCE) -COMPATIBLE_IOCTL(VIDEO_SET_BLANK) -COMPATIBLE_IOCTL(VIDEO_GET_STATUS) -COMPATIBLE_IOCTL(VIDEO_SET_DISPLAY_FORMAT) -COMPATIBLE_IOCTL(VIDEO_FAST_FORWARD) -COMPATIBLE_IOCTL(VIDEO_SLOWMOTION) -COMPATIBLE_IOCTL(VIDEO_GET_CAPABILITIES) -COMPATIBLE_IOCTL(VIDEO_CLEAR_BUFFER) -COMPATIBLE_IOCTL(VIDEO_SET_STREAMTYPE) -COMPATIBLE_IOCTL(VIDEO_SET_FORMAT) -COMPATIBLE_IOCTL(VIDEO_GET_SIZE) -/* cec */ -COMPATIBLE_IOCTL(CEC_ADAP_G_CAPS) -COMPATIBLE_IOCTL(CEC_ADAP_G_LOG_ADDRS) -COMPATIBLE_IOCTL(CEC_ADAP_S_LOG_ADDRS) -COMPATIBLE_IOCTL(CEC_ADAP_G_PHYS_ADDR) -COMPATIBLE_IOCTL(CEC_ADAP_S_PHYS_ADDR) -COMPATIBLE_IOCTL(CEC_G_MODE) -COMPATIBLE_IOCTL(CEC_S_MODE) -COMPATIBLE_IOCTL(CEC_TRANSMIT) -COMPATIBLE_IOCTL(CEC_RECEIVE) -COMPATIBLE_IOCTL(CEC_DQEVENT) - /* joystick */ COMPATIBLE_IOCTL(JSIOCGVERSION) COMPATIBLE_IOCTL(JSIOCGAXES) @@ -1080,12 +955,6 @@ static long do_ioctl_trans(unsigned int cmd, case RTC_EPOCH_READ32: case RTC_EPOCH_SET32: return rtc_ioctl(file, cmd, argp); - - /* dvb */ - case VIDEO_GET_EVENT: - return do_video_get_event(file, cmd, argp); - case VIDEO_STILLPICTURE: - return do_video_stillpicture(file, cmd, argp); } /* diff --git a/include/linux/hdmi.h b/include/linux/hdmi.h index d271ff23984f..4f3febc0f971 100644 --- a/include/linux/hdmi.h +++ b/include/linux/hdmi.h @@ -101,8 +101,8 @@ enum hdmi_extended_colorimetry { HDMI_EXTENDED_COLORIMETRY_XV_YCC_601, HDMI_EXTENDED_COLORIMETRY_XV_YCC_709, HDMI_EXTENDED_COLORIMETRY_S_YCC_601, - HDMI_EXTENDED_COLORIMETRY_ADOBE_YCC_601, - HDMI_EXTENDED_COLORIMETRY_ADOBE_RGB, + HDMI_EXTENDED_COLORIMETRY_OPYCC_601, + HDMI_EXTENDED_COLORIMETRY_OPRGB, /* The following EC values are only defined in CEA-861-F. */ HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM, diff --git a/include/media/cec.h b/include/media/cec.h index ff9847f7f99d..3fe5e5d2bb7e 100644 --- a/include/media/cec.h +++ b/include/media/cec.h @@ -63,7 +63,6 @@ struct cec_data { struct delayed_work work; struct completion c; u8 attempts; - bool new_initiator; bool blocking; bool completed; }; @@ -174,6 +173,7 @@ struct cec_adapter { bool is_configuring; bool is_configured; bool cec_pin_is_high; + u8 last_initiator; u32 monitor_all_cnt; u32 monitor_pin_cnt; u32 follower_cnt; @@ -198,9 +198,7 @@ struct cec_adapter { u16 phys_addrs[15]; u32 sequence; - char device_name[32]; char input_phys[32]; - char input_drv[32]; }; static inline void *cec_get_drvdata(const struct cec_adapter *adap) @@ -332,67 +330,6 @@ void cec_queue_pin_5v_event(struct cec_adapter *adap, bool is_high, ktime_t ts); u16 cec_get_edid_phys_addr(const u8 *edid, unsigned int size, unsigned int *offset); -/** - * cec_set_edid_phys_addr() - find and set the physical address - * - * @edid: pointer to the EDID data - * @size: size in bytes of the EDID data - * @phys_addr: the new physical address - * - * This function finds the location of the physical address in the EDID - * and fills in the given physical address and updates the checksum - * at the end of the EDID block. It does nothing if the EDID doesn't - * contain a physical address. - */ -void cec_set_edid_phys_addr(u8 *edid, unsigned int size, u16 phys_addr); - -/** - * cec_phys_addr_for_input() - calculate the PA for an input - * - * @phys_addr: the physical address of the parent - * @input: the number of the input port, must be between 1 and 15 - * - * This function calculates a new physical address based on the input - * port number. For example: - * - * PA = 0.0.0.0 and input = 2 becomes 2.0.0.0 - * - * PA = 3.0.0.0 and input = 1 becomes 3.1.0.0 - * - * PA = 3.2.1.0 and input = 5 becomes 3.2.1.5 - * - * PA = 3.2.1.3 and input = 5 becomes f.f.f.f since it maxed out the depth. - * - * Return: the new physical address or CEC_PHYS_ADDR_INVALID. - */ -u16 cec_phys_addr_for_input(u16 phys_addr, u8 input); - -/** - * cec_phys_addr_validate() - validate a physical address from an EDID - * - * @phys_addr: the physical address to validate - * @parent: if not %NULL, then this is filled with the parents PA. - * @port: if not %NULL, then this is filled with the input port. - * - * This validates a physical address as read from an EDID. If the - * PA is invalid (such as 1.0.1.0 since '0' is only allowed at the end), - * then it will return -EINVAL. - * - * The parent PA is passed into %parent and the input port is passed into - * %port. For example: - * - * PA = 0.0.0.0: has parent 0.0.0.0 and input port 0. - * - * PA = 1.0.0.0: has parent 0.0.0.0 and input port 1. - * - * PA = 3.2.0.0: has parent 3.0.0.0 and input port 2. - * - * PA = f.f.f.f: has parent f.f.f.f and input port 0. - * - * Return: 0 if the PA is valid, -EINVAL if not. - */ -int cec_phys_addr_validate(u16 phys_addr, u16 *parent, u16 *port); - #else static inline int cec_register_adapter(struct cec_adapter *adap, @@ -427,25 +364,6 @@ static inline u16 cec_get_edid_phys_addr(const u8 *edid, unsigned int size, return CEC_PHYS_ADDR_INVALID; } -static inline void cec_set_edid_phys_addr(u8 *edid, unsigned int size, - u16 phys_addr) -{ -} - -static inline u16 cec_phys_addr_for_input(u16 phys_addr, u8 input) -{ - return CEC_PHYS_ADDR_INVALID; -} - -static inline int cec_phys_addr_validate(u16 phys_addr, u16 *parent, u16 *port) -{ - if (parent) - *parent = phys_addr; - if (port) - *port = 0; - return 0; -} - #endif /** @@ -461,4 +379,74 @@ static inline void cec_phys_addr_invalidate(struct cec_adapter *adap) cec_s_phys_addr(adap, CEC_PHYS_ADDR_INVALID, false); } +/** + * cec_get_edid_spa_location() - find location of the Source Physical Address + * + * @edid: the EDID + * @size: the size of the EDID + * + * This EDID is expected to be a CEA-861 compliant, which means that there are + * at least two blocks and one or more of the extensions blocks are CEA-861 + * blocks. + * + * The returned location is guaranteed to be <= size-2. + * + * This is an inline function since it is used by both CEC and V4L2. + * Ideally this would go in a module shared by both, but it is overkill to do + * that for just a single function. + */ +static inline unsigned int cec_get_edid_spa_location(const u8 *edid, + unsigned int size) +{ + unsigned int blocks = size / 128; + unsigned int block; + u8 d; + + /* Sanity check: at least 2 blocks and a multiple of the block size */ + if (blocks < 2 || size % 128) + return 0; + + /* + * If there are fewer extension blocks than the size, then update + * 'blocks'. It is allowed to have more extension blocks than the size, + * since some hardware can only read e.g. 256 bytes of the EDID, even + * though more blocks are present. The first CEA-861 extension block + * should normally be in block 1 anyway. + */ + if (edid[0x7e] + 1 < blocks) + blocks = edid[0x7e] + 1; + + for (block = 1; block < blocks; block++) { + unsigned int offset = block * 128; + + /* Skip any non-CEA-861 extension blocks */ + if (edid[offset] != 0x02 || edid[offset + 1] != 0x03) + continue; + + /* search Vendor Specific Data Block (tag 3) */ + d = edid[offset + 2] & 0x7f; + /* Check if there are Data Blocks */ + if (d <= 4) + continue; + if (d > 4) { + unsigned int i = offset + 4; + unsigned int end = offset + d; + + /* Note: 'end' is always < 'size' */ + do { + u8 tag = edid[i] >> 5; + u8 len = edid[i] & 0x1f; + + if (tag == 3 && len >= 5 && i + len <= end && + edid[i + 1] == 0x03 && + edid[i + 2] == 0x0c && + edid[i + 3] == 0x00) + return i + 4; + i += len + 1; + } while (i < end); + } + } + return 0; +} + #endif /* _MEDIA_CEC_H */ diff --git a/include/media/media-entity.h b/include/media/media-entity.h index 3aa3d58d1d58..e5f6960d92f6 100644 --- a/include/media/media-entity.h +++ b/include/media/media-entity.h @@ -156,11 +156,40 @@ struct media_link { }; /** + * enum media_pad_signal_type - type of the signal inside a media pad + * + * @PAD_SIGNAL_DEFAULT: + * Default signal. Use this when all inputs or all outputs are + * uniquely identified by the pad number. + * @PAD_SIGNAL_ANALOG: + * The pad contains an analog signal. It can be Radio Frequency, + * Intermediate Frequency, a baseband signal or sub-cariers. + * Tuner inputs, IF-PLL demodulators, composite and s-video signals + * should use it. + * @PAD_SIGNAL_DV: + * Contains a digital video signal, with can be a bitstream of samples + * taken from an analog TV video source. On such case, it usually + * contains the VBI data on it. + * @PAD_SIGNAL_AUDIO: + * Contains an Intermediate Frequency analog signal from an audio + * sub-carrier or an audio bitstream. IF signals are provided by tuners + * and consumed by audio AM/FM decoders. Bitstream audio is provided by + * an audio decoder. + */ +enum media_pad_signal_type { + PAD_SIGNAL_DEFAULT = 0, + PAD_SIGNAL_ANALOG, + PAD_SIGNAL_DV, + PAD_SIGNAL_AUDIO, +}; + +/** * struct media_pad - A media pad graph object. * * @graph_obj: Embedded structure containing the media object common data * @entity: Entity this pad belongs to * @index: Pad index in the entity pads array, numbered from 0 to n + * @sig_type: Type of the signal inside a media pad * @flags: Pad flags, as defined in * :ref:`include/uapi/linux/media.h <media_header>` * (seek for ``MEDIA_PAD_FL_*``) @@ -169,6 +198,7 @@ struct media_pad { struct media_gobj graph_obj; /* must be first field in struct */ struct media_entity *entity; u16 index; + enum media_pad_signal_type sig_type; unsigned long flags; }; @@ -641,6 +671,24 @@ static inline void media_entity_cleanup(struct media_entity *entity) {} #endif /** + * media_get_pad_index() - retrieves a pad index from an entity + * + * @entity: entity where the pads belong + * @is_sink: true if the pad is a sink, false if it is a source + * @sig_type: type of signal of the pad to be search + * + * This helper function finds the first pad index inside an entity that + * satisfies both @is_sink and @sig_type conditions. + * + * Return: + * + * On success, return the pad number. If the pad was not found or the media + * entity is a NULL pointer, return -EINVAL. + */ +int media_get_pad_index(struct media_entity *entity, bool is_sink, + enum media_pad_signal_type sig_type); + +/** * media_create_pad_link() - creates a link between two entities. * * @source: pointer to &media_entity of the source pad. diff --git a/include/media/rc-core.h b/include/media/rc-core.h index 61571773a98d..c0cfbe16a854 100644 --- a/include/media/rc-core.h +++ b/include/media/rc-core.h @@ -317,13 +317,6 @@ struct ir_raw_event { unsigned carrier_report:1; }; -#define DEFINE_IR_RAW_EVENT(event) struct ir_raw_event event = {} - -static inline void init_ir_raw_event(struct ir_raw_event *ev) -{ - memset(ev, 0, sizeof(*ev)); -} - #define IR_DEFAULT_TIMEOUT MS_TO_NS(125) #define IR_MAX_DURATION 500000000 /* 500 ms */ #define US_TO_NS(usec) ((usec) * 1000) @@ -344,9 +337,7 @@ int ir_raw_encode_carrier(enum rc_proto protocol); static inline void ir_raw_event_reset(struct rc_dev *dev) { - struct ir_raw_event ev = { .reset = true }; - - ir_raw_event_store(dev, &ev); + ir_raw_event_store(dev, &((struct ir_raw_event) { .reset = true })); dev->idle = true; ir_raw_event_handle(dev); } diff --git a/include/media/rcar-fcp.h b/include/media/rcar-fcp.h index b60a7b176c37..179240fb163b 100644 --- a/include/media/rcar-fcp.h +++ b/include/media/rcar-fcp.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * rcar-fcp.h -- R-Car Frame Compression Processor Driver * * Copyright (C) 2016 Renesas Electronics Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #ifndef __MEDIA_RCAR_FCP_H__ #define __MEDIA_RCAR_FCP_H__ diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h index 1592d323c577..1497bda66c3b 100644 --- a/include/media/v4l2-async.h +++ b/include/media/v4l2-async.h @@ -20,9 +20,6 @@ struct v4l2_device; struct v4l2_subdev; struct v4l2_async_notifier; -/* A random max subdevice number, used to allocate an array on stack */ -#define V4L2_MAX_SUBDEVS 128U - /** * enum v4l2_async_match_type - type of asynchronous subdevice logic to be used * in order to identify a match @@ -73,6 +70,8 @@ enum v4l2_async_match_type { * @match.custom.priv: * Driver-specific private struct with match parameters * to be used if %V4L2_ASYNC_MATCH_CUSTOM. + * @asd_list: used to add struct v4l2_async_subdev objects to the + * master notifier @asd_list * @list: used to link struct v4l2_async_subdev objects, waiting to be * probed, to a notifier->waiting list * @@ -90,14 +89,15 @@ struct v4l2_async_subdev { unsigned short address; } i2c; struct { - bool (*match)(struct device *, - struct v4l2_async_subdev *); + bool (*match)(struct device *dev, + struct v4l2_async_subdev *sd); void *priv; } custom; } match; /* v4l2-async core private: not to be used by drivers */ struct list_head list; + struct list_head asd_list; }; /** @@ -121,30 +121,108 @@ struct v4l2_async_notifier_operations { * struct v4l2_async_notifier - v4l2_device notifier data * * @ops: notifier operations - * @num_subdevs: number of subdevices used in the subdevs array - * @max_subdevs: number of subdevices allocated in the subdevs array - * @subdevs: array of pointers to subdevice descriptors * @v4l2_dev: v4l2_device of the root notifier, NULL otherwise * @sd: sub-device that registered the notifier, NULL otherwise * @parent: parent notifier + * @asd_list: master list of struct v4l2_async_subdev * @waiting: list of struct v4l2_async_subdev, waiting for their drivers * @done: list of struct v4l2_subdev, already probed * @list: member in a global list of notifiers */ struct v4l2_async_notifier { const struct v4l2_async_notifier_operations *ops; - unsigned int num_subdevs; - unsigned int max_subdevs; - struct v4l2_async_subdev **subdevs; struct v4l2_device *v4l2_dev; struct v4l2_subdev *sd; struct v4l2_async_notifier *parent; + struct list_head asd_list; struct list_head waiting; struct list_head done; struct list_head list; }; /** + * v4l2_async_notifier_init - Initialize a notifier. + * + * @notifier: pointer to &struct v4l2_async_notifier + * + * This function initializes the notifier @asd_list. It must be called + * before the first call to @v4l2_async_notifier_add_subdev. + */ +void v4l2_async_notifier_init(struct v4l2_async_notifier *notifier); + +/** + * v4l2_async_notifier_add_subdev - Add an async subdev to the + * notifier's master asd list. + * + * @notifier: pointer to &struct v4l2_async_notifier + * @asd: pointer to &struct v4l2_async_subdev + * + * Call this function before registering a notifier to link the + * provided asd to the notifiers master @asd_list. + */ +int v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier, + struct v4l2_async_subdev *asd); + +/** + * v4l2_async_notifier_add_fwnode_subdev - Allocate and add a fwnode async + * subdev to the notifier's master asd_list. + * + * @notifier: pointer to &struct v4l2_async_notifier + * @fwnode: fwnode handle of the sub-device to be matched + * @asd_struct_size: size of the driver's async sub-device struct, including + * sizeof(struct v4l2_async_subdev). The &struct + * v4l2_async_subdev shall be the first member of + * the driver's async sub-device struct, i.e. both + * begin at the same memory address. + * + * Allocate a fwnode-matched asd of size asd_struct_size, and add it + * to the notifiers @asd_list. + */ +struct v4l2_async_subdev * +v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier, + struct fwnode_handle *fwnode, + unsigned int asd_struct_size); + +/** + * v4l2_async_notifier_add_i2c_subdev - Allocate and add an i2c async + * subdev to the notifier's master asd_list. + * + * @notifier: pointer to &struct v4l2_async_notifier + * @adapter_id: I2C adapter ID to be matched + * @address: I2C address of sub-device to be matched + * @asd_struct_size: size of the driver's async sub-device struct, including + * sizeof(struct v4l2_async_subdev). The &struct + * v4l2_async_subdev shall be the first member of + * the driver's async sub-device struct, i.e. both + * begin at the same memory address. + * + * Same as above but for I2C matched sub-devices. + */ +struct v4l2_async_subdev * +v4l2_async_notifier_add_i2c_subdev(struct v4l2_async_notifier *notifier, + int adapter_id, unsigned short address, + unsigned int asd_struct_size); + +/** + * v4l2_async_notifier_add_devname_subdev - Allocate and add a device-name + * async subdev to the notifier's master asd_list. + * + * @notifier: pointer to &struct v4l2_async_notifier + * @device_name: device name string to be matched + * @asd_struct_size: size of the driver's async sub-device struct, including + * sizeof(struct v4l2_async_subdev). The &struct + * v4l2_async_subdev shall be the first member of + * the driver's async sub-device struct, i.e. both + * begin at the same memory address. + * + * Same as above but for device-name matched sub-devices. + */ +struct v4l2_async_subdev * +v4l2_async_notifier_add_devname_subdev(struct v4l2_async_notifier *notifier, + const char *device_name, + unsigned int asd_struct_size); + +/** * v4l2_async_notifier_register - registers a subdevice asynchronous notifier * * @v4l2_dev: pointer to &struct v4l2_device @@ -164,7 +242,8 @@ int v4l2_async_subdev_notifier_register(struct v4l2_subdev *sd, struct v4l2_async_notifier *notifier); /** - * v4l2_async_notifier_unregister - unregisters a subdevice asynchronous notifier + * v4l2_async_notifier_unregister - unregisters a subdevice + * asynchronous notifier * * @notifier: pointer to &struct v4l2_async_notifier */ @@ -177,7 +256,9 @@ void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier); * Release memory resources related to a notifier, including the async * sub-devices allocated for the purposes of the notifier but not the notifier * itself. The user is responsible for calling this function to clean up the - * notifier after calling @v4l2_async_notifier_parse_fwnode_endpoints or + * notifier after calling + * @v4l2_async_notifier_add_subdev, + * @v4l2_async_notifier_parse_fwnode_endpoints or * @v4l2_fwnode_reference_parse_sensor_common. * * There is no harm from calling v4l2_async_notifier_cleanup in other @@ -213,8 +294,8 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd); * An error is returned if the module is no longer loaded on any attempts * to register it. */ -int __must_check v4l2_async_register_subdev_sensor_common( - struct v4l2_subdev *sd); +int __must_check +v4l2_async_register_subdev_sensor_common(struct v4l2_subdev *sd); /** * v4l2_async_unregister_subdev - unregisters a sub-device to the asynchronous diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index cdc87ec61e54..82715645617b 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -155,6 +155,18 @@ struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev, const unsigned short *probe_addrs); /** + * v4l2_i2c_subdev_set_name - Set name for an I²C sub-device + * + * @sd: pointer to &struct v4l2_subdev + * @client: pointer to struct i2c_client + * @devname: the name of the device; if NULL, the I²C device's name will be used + * @postfix: sub-device specific string to put right after the I²C device name; + * may be NULL + */ +void v4l2_i2c_subdev_set_name(struct v4l2_subdev *sd, struct i2c_client *client, + const char *devname, const char *postfix); + +/** * v4l2_i2c_subdev_init - Initializes a &struct v4l2_subdev with data from * an i2c_client struct. * @@ -283,7 +295,7 @@ struct v4l2_priv_tun_config { * @height: pointer to height that will be adjusted if needed. * @hmin: minimum height. * @hmax: maximum height. - * @halign: least significant bit on width. + * @halign: least significant bit on height. * @salign: least significant bit for the image size (e. g. * :math:`width * height`). * diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h index f615ba1b29dd..ff89df428f79 100644 --- a/include/media/v4l2-ctrls.h +++ b/include/media/v4l2-ctrls.h @@ -729,6 +729,22 @@ struct v4l2_ctrl *v4l2_ctrl_find(struct v4l2_ctrl_handler *hdl, u32 id); void v4l2_ctrl_activate(struct v4l2_ctrl *ctrl, bool active); /** + * __v4l2_ctrl_grab() - Unlocked variant of v4l2_ctrl_grab. + * + * @ctrl: The control to (de)activate. + * @grabbed: True if the control should become grabbed. + * + * This sets or clears the V4L2_CTRL_FLAG_GRABBED flag atomically. + * Does nothing if @ctrl == NULL. + * The V4L2_EVENT_CTRL event will be generated afterwards. + * This will usually be called when starting or stopping streaming in the + * driver. + * + * This function assumes that the control handler is locked by the caller. + */ +void __v4l2_ctrl_grab(struct v4l2_ctrl *ctrl, bool grabbed); + +/** * v4l2_ctrl_grab() - Mark the control as grabbed or not grabbed. * * @ctrl: The control to (de)activate. @@ -743,7 +759,15 @@ void v4l2_ctrl_activate(struct v4l2_ctrl *ctrl, bool active); * This function assumes that the control handler is not locked and will * take the lock itself. */ -void v4l2_ctrl_grab(struct v4l2_ctrl *ctrl, bool grabbed); +static inline void v4l2_ctrl_grab(struct v4l2_ctrl *ctrl, bool grabbed) +{ + if (!ctrl) + return; + + v4l2_ctrl_lock(ctrl); + __v4l2_ctrl_grab(ctrl, grabbed); + v4l2_ctrl_unlock(ctrl); +} /** *__v4l2_ctrl_modify_range() - Unlocked variant of v4l2_ctrl_modify_range() diff --git a/include/media/v4l2-dv-timings.h b/include/media/v4l2-dv-timings.h index 17cb27df1b81..2cc0cabc124f 100644 --- a/include/media/v4l2-dv-timings.h +++ b/include/media/v4l2-dv-timings.h @@ -10,6 +10,17 @@ #include <linux/videodev2.h> +/** + * v4l2_calc_timeperframe - helper function to calculate timeperframe based + * v4l2_dv_timings fields. + * @t: Timings for the video mode. + * + * Calculates the expected timeperframe using the pixel clock value and + * horizontal/vertical measures. This means that v4l2_dv_timings structure + * must be correctly and fully filled. + */ +struct v4l2_fract v4l2_calc_timeperframe(const struct v4l2_dv_timings *t); + /* * v4l2_dv_timings_presets: list of all dv_timings presets. */ @@ -234,4 +245,10 @@ v4l2_hdmi_rx_colorimetry(const struct hdmi_avi_infoframe *avi, const struct hdmi_vendor_infoframe *hdmi, unsigned int height); +u16 v4l2_get_edid_phys_addr(const u8 *edid, unsigned int size, + unsigned int *offset); +void v4l2_set_edid_phys_addr(u8 *edid, unsigned int size, u16 phys_addr); +u16 v4l2_phys_addr_for_input(u16 phys_addr, u8 input); +int v4l2_phys_addr_validate(u16 phys_addr, u16 *parent, u16 *port); + #endif diff --git a/include/media/v4l2-fwnode.h b/include/media/v4l2-fwnode.h index 9cccab618b98..6d9d9f1839ac 100644 --- a/include/media/v4l2-fwnode.h +++ b/include/media/v4l2-fwnode.h @@ -23,6 +23,7 @@ #include <linux/types.h> #include <media/v4l2-mediabus.h> +#include <media/v4l2-subdev.h> struct fwnode_handle; struct v4l2_async_notifier; @@ -70,8 +71,8 @@ struct v4l2_fwnode_bus_parallel { * @clock_lane: the number of the clock lane */ struct v4l2_fwnode_bus_mipi_csi1 { - bool clock_inv; - bool strobe; + unsigned char clock_inv:1; + unsigned char strobe:1; bool lane_polarity[2]; unsigned char data_lane; unsigned char clock_lane; @@ -130,19 +131,30 @@ struct v4l2_fwnode_link { * @fwnode: pointer to the endpoint's fwnode handle * @vep: pointer to the V4L2 fwnode data structure * - * All properties are optional. If none are found, we don't set any flags. This - * means the port has a static configuration and no properties have to be - * specified explicitly. If any properties that identify the bus as parallel - * are found and slave-mode isn't set, we set V4L2_MBUS_MASTER. Similarly, if - * we recognise the bus as serial CSI-2 and clock-noncontinuous isn't set, we - * set the V4L2_MBUS_CSI2_CONTINUOUS_CLOCK flag. The caller should hold a - * reference to @fwnode. + * This function parses the V4L2 fwnode endpoint specific parameters from the + * firmware. The caller is responsible for assigning @vep.bus_type to a valid + * media bus type. The caller may also set the default configuration for the + * endpoint --- a configuration that shall be in line with the DT binding + * documentation. Should a device support multiple bus types, the caller may + * call this function once the correct type is found --- with a default + * configuration valid for that type. + * + * As a compatibility means guessing the bus type is also supported by setting + * @vep.bus_type to V4L2_MBUS_UNKNOWN. The caller may not provide a default + * configuration in this case as the defaults are specific to a given bus type. + * This functionality is deprecated and should not be used in new drivers and it + * is only supported for CSI-2 D-PHY, parallel and Bt.656 busses. + * + * The function does not change the V4L2 fwnode endpoint state if it fails. * * NOTE: This function does not parse properties the size of which is variable * without a low fixed limit. Please use v4l2_fwnode_endpoint_alloc_parse() in * new drivers instead. * - * Return: 0 on success or a negative error code on failure. + * Return: %0 on success or a negative error code on failure: + * %-ENOMEM on memory allocation failure + * %-EINVAL on parsing failure + * %-ENXIO on mismatching bus types */ int v4l2_fwnode_endpoint_parse(struct fwnode_handle *fwnode, struct v4l2_fwnode_endpoint *vep); @@ -160,14 +172,23 @@ void v4l2_fwnode_endpoint_free(struct v4l2_fwnode_endpoint *vep); /** * v4l2_fwnode_endpoint_alloc_parse() - parse all fwnode node properties * @fwnode: pointer to the endpoint's fwnode handle + * @vep: pointer to the V4L2 fwnode data structure * - * All properties are optional. If none are found, we don't set any flags. This - * means the port has a static configuration and no properties have to be - * specified explicitly. If any properties that identify the bus as parallel - * are found and slave-mode isn't set, we set V4L2_MBUS_MASTER. Similarly, if - * we recognise the bus as serial CSI-2 and clock-noncontinuous isn't set, we - * set the V4L2_MBUS_CSI2_CONTINUOUS_CLOCK flag. The caller should hold a - * reference to @fwnode. + * This function parses the V4L2 fwnode endpoint specific parameters from the + * firmware. The caller is responsible for assigning @vep.bus_type to a valid + * media bus type. The caller may also set the default configuration for the + * endpoint --- a configuration that shall be in line with the DT binding + * documentation. Should a device support multiple bus types, the caller may + * call this function once the correct type is found --- with a default + * configuration valid for that type. + * + * As a compatibility means guessing the bus type is also supported by setting + * @vep.bus_type to V4L2_MBUS_UNKNOWN. The caller may not provide a default + * configuration in this case as the defaults are specific to a given bus type. + * This functionality is deprecated and should not be used in new drivers and it + * is only supported for CSI-2 D-PHY, parallel and Bt.656 busses. + * + * The function does not change the V4L2 fwnode endpoint state if it fails. * * v4l2_fwnode_endpoint_alloc_parse() has two important differences to * v4l2_fwnode_endpoint_parse(): @@ -177,11 +198,13 @@ void v4l2_fwnode_endpoint_free(struct v4l2_fwnode_endpoint *vep); * 2. The memory it has allocated to store the variable size data must be freed * using v4l2_fwnode_endpoint_free() when no longer needed. * - * Return: Pointer to v4l2_fwnode_endpoint if successful, on an error pointer - * on error. + * Return: %0 on success or a negative error code on failure: + * %-ENOMEM on memory allocation failure + * %-EINVAL on parsing failure + * %-ENXIO on mismatching bus types */ -struct v4l2_fwnode_endpoint *v4l2_fwnode_endpoint_alloc_parse( - struct fwnode_handle *fwnode); +int v4l2_fwnode_endpoint_alloc_parse(struct fwnode_handle *fwnode, + struct v4l2_fwnode_endpoint *vep); /** * v4l2_fwnode_parse_link() - parse a link between two endpoints @@ -213,7 +236,6 @@ int v4l2_fwnode_parse_link(struct fwnode_handle *fwnode, */ void v4l2_fwnode_put_link(struct v4l2_fwnode_link *link); - /** * typedef parse_endpoint_func - Driver's callback function to be called on * each V4L2 fwnode endpoint. @@ -232,7 +254,6 @@ typedef int (*parse_endpoint_func)(struct device *dev, struct v4l2_fwnode_endpoint *vep, struct v4l2_async_subdev *asd); - /** * v4l2_async_notifier_parse_fwnode_endpoints - Parse V4L2 fwnode endpoints in a * device node @@ -247,7 +268,7 @@ typedef int (*parse_endpoint_func)(struct device *dev, * endpoint. Optional. * * Parse the fwnode endpoints of the @dev device and populate the async sub- - * devices array of the notifier. The @parse_endpoint callback function is + * devices list in the notifier. The @parse_endpoint callback function is * called for each endpoint with the corresponding async sub-device pointer to * let the caller initialize the driver-specific part of the async sub-device * structure. @@ -258,11 +279,6 @@ typedef int (*parse_endpoint_func)(struct device *dev, * This function may not be called on a registered notifier and may be called on * a notifier only once. * - * Do not change the notifier's subdevs array, take references to the subdevs - * array itself or change the notifier's num_subdevs field. This is because this - * function allocates and reallocates the subdevs array based on parsing - * endpoints. - * * The &struct v4l2_fwnode_endpoint passed to the callback function * @parse_endpoint is released once the function is finished. If there is a need * to retain that configuration, the user needs to allocate memory for it. @@ -276,10 +292,11 @@ typedef int (*parse_endpoint_func)(struct device *dev, * %-EINVAL if graph or endpoint parsing failed * Other error codes as returned by @parse_endpoint */ -int v4l2_async_notifier_parse_fwnode_endpoints( - struct device *dev, struct v4l2_async_notifier *notifier, - size_t asd_struct_size, - parse_endpoint_func parse_endpoint); +int +v4l2_async_notifier_parse_fwnode_endpoints(struct device *dev, + struct v4l2_async_notifier *notifier, + size_t asd_struct_size, + parse_endpoint_func parse_endpoint); /** * v4l2_async_notifier_parse_fwnode_endpoints_by_port - Parse V4L2 fwnode @@ -303,7 +320,7 @@ int v4l2_async_notifier_parse_fwnode_endpoints( * devices). In this case the driver must know which ports to parse. * * Parse the fwnode endpoints of the @dev device on a given @port and populate - * the async sub-devices array of the notifier. The @parse_endpoint callback + * the async sub-devices list of the notifier. The @parse_endpoint callback * function is called for each endpoint with the corresponding async sub-device * pointer to let the caller initialize the driver-specific part of the async * sub-device structure. @@ -314,11 +331,6 @@ int v4l2_async_notifier_parse_fwnode_endpoints( * This function may not be called on a registered notifier and may be called on * a notifier only once per port. * - * Do not change the notifier's subdevs array, take references to the subdevs - * array itself or change the notifier's num_subdevs field. This is because this - * function allocates and reallocates the subdevs array based on parsing - * endpoints. - * * The &struct v4l2_fwnode_endpoint passed to the callback function * @parse_endpoint is released once the function is finished. If there is a need * to retain that configuration, the user needs to allocate memory for it. @@ -332,10 +344,12 @@ int v4l2_async_notifier_parse_fwnode_endpoints( * %-EINVAL if graph or endpoint parsing failed * Other error codes as returned by @parse_endpoint */ -int v4l2_async_notifier_parse_fwnode_endpoints_by_port( - struct device *dev, struct v4l2_async_notifier *notifier, - size_t asd_struct_size, unsigned int port, - parse_endpoint_func parse_endpoint); +int +v4l2_async_notifier_parse_fwnode_endpoints_by_port(struct device *dev, + struct v4l2_async_notifier *notifier, + size_t asd_struct_size, + unsigned int port, + parse_endpoint_func parse_endpoint); /** * v4l2_fwnode_reference_parse_sensor_common - parse common references on @@ -355,7 +369,44 @@ int v4l2_async_notifier_parse_fwnode_endpoints_by_port( * -ENOMEM if memory allocation failed * -EINVAL if property parsing failed */ -int v4l2_async_notifier_parse_fwnode_sensor_common( - struct device *dev, struct v4l2_async_notifier *notifier); +int v4l2_async_notifier_parse_fwnode_sensor_common(struct device *dev, + struct v4l2_async_notifier *notifier); + +/** + * v4l2_async_register_fwnode_subdev - registers a sub-device to the + * asynchronous sub-device framework + * and parses fwnode endpoints + * + * @sd: pointer to struct &v4l2_subdev + * @asd_struct_size: size of the driver's async sub-device struct, including + * sizeof(struct v4l2_async_subdev). The &struct + * v4l2_async_subdev shall be the first member of + * the driver's async sub-device struct, i.e. both + * begin at the same memory address. + * @ports: array of port id's to parse for fwnode endpoints. If NULL, will + * parse all ports owned by the sub-device. + * @num_ports: number of ports in @ports array. Ignored if @ports is NULL. + * @parse_endpoint: Driver's callback function called on each V4L2 fwnode + * endpoint. Optional. + * + * This function is just like v4l2_async_register_subdev() with the + * exception that calling it will also allocate a notifier for the + * sub-device, parse the sub-device's firmware node endpoints using + * v4l2_async_notifier_parse_fwnode_endpoints() or + * v4l2_async_notifier_parse_fwnode_endpoints_by_port(), and + * registers the sub-device notifier. The sub-device is similarly + * unregistered by calling v4l2_async_unregister_subdev(). + * + * While registered, the subdev module is marked as in-use. + * + * An error is returned if the module is no longer loaded on any attempts + * to register it. + */ +int +v4l2_async_register_fwnode_subdev(struct v4l2_subdev *sd, + size_t asd_struct_size, + unsigned int *ports, + unsigned int num_ports, + parse_endpoint_func parse_endpoint); #endif /* _V4L2_FWNODE_H */ diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h index 2634d9dc9916..bf5043c1ab6b 100644 --- a/include/media/v4l2-mc.h +++ b/include/media/v4l2-mc.h @@ -23,84 +23,6 @@ #include <media/v4l2-dev.h> #include <linux/types.h> -/** - * enum tuner_pad_index - tuner pad index for MEDIA_ENT_F_TUNER - * - * @TUNER_PAD_RF_INPUT: Radiofrequency (RF) sink pad, usually linked to a - * RF connector entity. - * @TUNER_PAD_OUTPUT: Tuner video output source pad. Contains the video - * chrominance and luminance or the hole bandwidth - * of the signal converted to an Intermediate Frequency - * (IF) or to baseband (on zero-IF tuners). - * @TUNER_PAD_AUD_OUT: Tuner audio output source pad. Tuners used to decode - * analog TV signals have an extra pad for audio output. - * Old tuners use an analog stage with a saw filter for - * the audio IF frequency. The output of the pad is, in - * this case, the audio IF, with should be decoded either - * by the bridge chipset (that's the case of cx2388x - * chipsets) or may require an external IF sound - * processor, like msp34xx. On modern silicon tuners, - * the audio IF decoder is usually incorporated at the - * tuner. On such case, the output of this pad is an - * audio sampled data. - * @TUNER_NUM_PADS: Number of pads of the tuner. - */ -enum tuner_pad_index { - TUNER_PAD_RF_INPUT, - TUNER_PAD_OUTPUT, - TUNER_PAD_AUD_OUT, - TUNER_NUM_PADS -}; - -/** - * enum if_vid_dec_pad_index - video IF-PLL pad index for - * MEDIA_ENT_F_IF_VID_DECODER - * - * @IF_VID_DEC_PAD_IF_INPUT: video Intermediate Frequency (IF) sink pad - * @IF_VID_DEC_PAD_OUT: IF-PLL video output source pad. Contains the - * video chrominance and luminance IF signals. - * @IF_VID_DEC_PAD_NUM_PADS: Number of pads of the video IF-PLL. - */ -enum if_vid_dec_pad_index { - IF_VID_DEC_PAD_IF_INPUT, - IF_VID_DEC_PAD_OUT, - IF_VID_DEC_PAD_NUM_PADS -}; - -/** - * enum if_aud_dec_pad_index - audio/sound IF-PLL pad index for - * MEDIA_ENT_F_IF_AUD_DECODER - * - * @IF_AUD_DEC_PAD_IF_INPUT: audio Intermediate Frequency (IF) sink pad - * @IF_AUD_DEC_PAD_OUT: IF-PLL audio output source pad. Contains the - * audio sampled stream data, usually connected - * to the bridge bus via an Inter-IC Sound (I2S) - * bus. - * @IF_AUD_DEC_PAD_NUM_PADS: Number of pads of the audio IF-PLL. - */ -enum if_aud_dec_pad_index { - IF_AUD_DEC_PAD_IF_INPUT, - IF_AUD_DEC_PAD_OUT, - IF_AUD_DEC_PAD_NUM_PADS -}; - -/** - * enum demod_pad_index - analog TV pad index for MEDIA_ENT_F_ATV_DECODER - * - * @DEMOD_PAD_IF_INPUT: IF input sink pad. - * @DEMOD_PAD_VID_OUT: Video output source pad. - * @DEMOD_PAD_VBI_OUT: Vertical Blank Interface (VBI) output source pad. - * @DEMOD_PAD_AUDIO_OUT: Audio output source pad. - * @DEMOD_NUM_PADS: Maximum number of output pads. - */ -enum demod_pad_index { - DEMOD_PAD_IF_INPUT, - DEMOD_PAD_VID_OUT, - DEMOD_PAD_VBI_OUT, - DEMOD_PAD_AUDIO_OUT, - DEMOD_NUM_PADS -}; - /* We don't need to include pci.h or usb.h here */ struct pci_dev; struct usb_device; diff --git a/include/media/v4l2-mediabus.h b/include/media/v4l2-mediabus.h index 4bbb5f3d2b02..66cb746ceeb5 100644 --- a/include/media/v4l2-mediabus.h +++ b/include/media/v4l2-mediabus.h @@ -14,7 +14,6 @@ #include <linux/v4l2-mediabus.h> #include <linux/bitops.h> - /* Parallel flags */ /* * Can the client run in master or in slave mode. By "Master mode" an operation @@ -63,26 +62,34 @@ #define V4L2_MBUS_CSI2_CONTINUOUS_CLOCK BIT(8) #define V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK BIT(9) -#define V4L2_MBUS_CSI2_LANES (V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_2_LANE | \ - V4L2_MBUS_CSI2_3_LANE | V4L2_MBUS_CSI2_4_LANE) -#define V4L2_MBUS_CSI2_CHANNELS (V4L2_MBUS_CSI2_CHANNEL_0 | V4L2_MBUS_CSI2_CHANNEL_1 | \ - V4L2_MBUS_CSI2_CHANNEL_2 | V4L2_MBUS_CSI2_CHANNEL_3) +#define V4L2_MBUS_CSI2_LANES (V4L2_MBUS_CSI2_1_LANE | \ + V4L2_MBUS_CSI2_2_LANE | \ + V4L2_MBUS_CSI2_3_LANE | \ + V4L2_MBUS_CSI2_4_LANE) +#define V4L2_MBUS_CSI2_CHANNELS (V4L2_MBUS_CSI2_CHANNEL_0 | \ + V4L2_MBUS_CSI2_CHANNEL_1 | \ + V4L2_MBUS_CSI2_CHANNEL_2 | \ + V4L2_MBUS_CSI2_CHANNEL_3) /** * enum v4l2_mbus_type - media bus type + * @V4L2_MBUS_UNKNOWN: unknown bus type, no V4L2 mediabus configuration * @V4L2_MBUS_PARALLEL: parallel interface with hsync and vsync * @V4L2_MBUS_BT656: parallel interface with embedded synchronisation, can * also be used for BT.1120 * @V4L2_MBUS_CSI1: MIPI CSI-1 serial interface * @V4L2_MBUS_CCP2: CCP2 (Compact Camera Port 2) - * @V4L2_MBUS_CSI2: MIPI CSI-2 serial interface + * @V4L2_MBUS_CSI2_DPHY: MIPI CSI-2 serial interface, with D-PHY + * @V4L2_MBUS_CSI2_CPHY: MIPI CSI-2 serial interface, with C-PHY */ enum v4l2_mbus_type { + V4L2_MBUS_UNKNOWN, V4L2_MBUS_PARALLEL, V4L2_MBUS_BT656, V4L2_MBUS_CSI1, V4L2_MBUS_CCP2, - V4L2_MBUS_CSI2, + V4L2_MBUS_CSI2_DPHY, + V4L2_MBUS_CSI2_CPHY, }; /** @@ -102,8 +109,9 @@ struct v4l2_mbus_config { * @pix_fmt: pointer to &struct v4l2_pix_format to be filled * @mbus_fmt: pointer to &struct v4l2_mbus_framefmt to be used as model */ -static inline void v4l2_fill_pix_format(struct v4l2_pix_format *pix_fmt, - const struct v4l2_mbus_framefmt *mbus_fmt) +static inline void +v4l2_fill_pix_format(struct v4l2_pix_format *pix_fmt, + const struct v4l2_mbus_framefmt *mbus_fmt) { pix_fmt->width = mbus_fmt->width; pix_fmt->height = mbus_fmt->height; @@ -124,7 +132,7 @@ static inline void v4l2_fill_pix_format(struct v4l2_pix_format *pix_fmt, * @code: data format code (from &enum v4l2_mbus_pixelcode) */ static inline void v4l2_fill_mbus_format(struct v4l2_mbus_framefmt *mbus_fmt, - const struct v4l2_pix_format *pix_fmt, + const struct v4l2_pix_format *pix_fmt, u32 code) { mbus_fmt->width = pix_fmt->width; @@ -144,9 +152,9 @@ static inline void v4l2_fill_mbus_format(struct v4l2_mbus_framefmt *mbus_fmt, * @pix_mp_fmt: pointer to &struct v4l2_pix_format_mplane to be filled * @mbus_fmt: pointer to &struct v4l2_mbus_framefmt to be used as model */ -static inline void v4l2_fill_pix_format_mplane( - struct v4l2_pix_format_mplane *pix_mp_fmt, - const struct v4l2_mbus_framefmt *mbus_fmt) +static inline void +v4l2_fill_pix_format_mplane(struct v4l2_pix_format_mplane *pix_mp_fmt, + const struct v4l2_mbus_framefmt *mbus_fmt) { pix_mp_fmt->width = mbus_fmt->width; pix_mp_fmt->height = mbus_fmt->height; @@ -164,9 +172,9 @@ static inline void v4l2_fill_pix_format_mplane( * @mbus_fmt: pointer to &struct v4l2_mbus_framefmt to be filled * @pix_mp_fmt: pointer to &struct v4l2_pix_format_mplane to be used as model */ -static inline void v4l2_fill_mbus_format_mplane( - struct v4l2_mbus_framefmt *mbus_fmt, - const struct v4l2_pix_format_mplane *pix_mp_fmt) +static inline void +v4l2_fill_mbus_format_mplane(struct v4l2_mbus_framefmt *mbus_fmt, + const struct v4l2_pix_format_mplane *pix_mp_fmt) { mbus_fmt->width = pix_mp_fmt->width; mbus_fmt->height = pix_mp_fmt->height; diff --git a/include/media/v4l2-rect.h b/include/media/v4l2-rect.h index 595c3ba05f23..c86474dc7b55 100644 --- a/include/media/v4l2-rect.h +++ b/include/media/v4l2-rect.h @@ -83,6 +83,32 @@ static inline bool v4l2_rect_same_size(const struct v4l2_rect *r1, } /** + * v4l2_rect_same_position() - return true if r1 has the same position as r2 + * @r1: rectangle. + * @r2: rectangle. + * + * Return true if both rectangles have the same position + */ +static inline bool v4l2_rect_same_position(const struct v4l2_rect *r1, + const struct v4l2_rect *r2) +{ + return r1->top == r2->top && r1->left == r2->left; +} + +/** + * v4l2_rect_equal() - return true if r1 equals r2 + * @r1: rectangle. + * @r2: rectangle. + * + * Return true if both rectangles have the same size and position. + */ +static inline bool v4l2_rect_equal(const struct v4l2_rect *r1, + const struct v4l2_rect *r2) +{ + return v4l2_rect_same_size(r1, r2) && v4l2_rect_same_position(r1, r2); +} + +/** * v4l2_rect_intersect() - calculate the intersection of two rects. * @r: intersection of @r1 and @r2. * @r1: rectangle. diff --git a/include/media/vsp1.h b/include/media/vsp1.h index 3093b9cb9067..1cf868360701 100644 --- a/include/media/vsp1.h +++ b/include/media/vsp1.h @@ -1,14 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * vsp1.h -- R-Car VSP1 API * * Copyright (C) 2015 Renesas Electronics Corporation * * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #ifndef __MEDIA_VSP1_H__ #define __MEDIA_VSP1_H__ @@ -46,7 +42,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int pipe_index, /** * struct vsp1_du_atomic_config - VSP atomic configuration parameters * @pixelformat: plane pixel format (V4L2 4CC) - * @pitch: line pitch in bytes, for all planes + * @pitch: line pitch in bytes for the first plane * @mem: DMA memory address for each plane of the frame buffer * @src: source rectangle in the frame buffer (integer coordinates) * @dst: destination rectangle on the display (integer coordinates) diff --git a/include/uapi/linux/cec.h b/include/uapi/linux/cec.h index 097fcd812471..3094af68b6e7 100644 --- a/include/uapi/linux/cec.h +++ b/include/uapi/linux/cec.h @@ -152,10 +152,13 @@ static inline void cec_msg_set_reply_to(struct cec_msg *msg, #define CEC_TX_STATUS_LOW_DRIVE (1 << 3) #define CEC_TX_STATUS_ERROR (1 << 4) #define CEC_TX_STATUS_MAX_RETRIES (1 << 5) +#define CEC_TX_STATUS_ABORTED (1 << 6) +#define CEC_TX_STATUS_TIMEOUT (1 << 7) #define CEC_RX_STATUS_OK (1 << 0) #define CEC_RX_STATUS_TIMEOUT (1 << 1) #define CEC_RX_STATUS_FEATURE_ABORT (1 << 2) +#define CEC_RX_STATUS_ABORTED (1 << 3) static inline int cec_msg_status_is_ok(const struct cec_msg *msg) { diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 5d1a3685bea9..29729d580452 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -225,8 +225,8 @@ enum v4l2_colorspace { /* For RGB colorspaces such as produces by most webcams. */ V4L2_COLORSPACE_SRGB = 8, - /* AdobeRGB colorspace */ - V4L2_COLORSPACE_ADOBERGB = 9, + /* opRGB colorspace */ + V4L2_COLORSPACE_OPRGB = 9, /* BT.2020 colorspace, used for UHDTV. */ V4L2_COLORSPACE_BT2020 = 10, @@ -258,7 +258,7 @@ enum v4l2_xfer_func { * * V4L2_COLORSPACE_SRGB, V4L2_COLORSPACE_JPEG: V4L2_XFER_FUNC_SRGB * - * V4L2_COLORSPACE_ADOBERGB: V4L2_XFER_FUNC_ADOBERGB + * V4L2_COLORSPACE_OPRGB: V4L2_XFER_FUNC_OPRGB * * V4L2_COLORSPACE_SMPTE240M: V4L2_XFER_FUNC_SMPTE240M * @@ -269,7 +269,7 @@ enum v4l2_xfer_func { V4L2_XFER_FUNC_DEFAULT = 0, V4L2_XFER_FUNC_709 = 1, V4L2_XFER_FUNC_SRGB = 2, - V4L2_XFER_FUNC_ADOBERGB = 3, + V4L2_XFER_FUNC_OPRGB = 3, V4L2_XFER_FUNC_SMPTE240M = 4, V4L2_XFER_FUNC_NONE = 5, V4L2_XFER_FUNC_DCI_P3 = 6, @@ -281,7 +281,7 @@ enum v4l2_xfer_func { * This depends on the colorspace. */ #define V4L2_MAP_XFER_FUNC_DEFAULT(colsp) \ - ((colsp) == V4L2_COLORSPACE_ADOBERGB ? V4L2_XFER_FUNC_ADOBERGB : \ + ((colsp) == V4L2_COLORSPACE_OPRGB ? V4L2_XFER_FUNC_OPRGB : \ ((colsp) == V4L2_COLORSPACE_SMPTE240M ? V4L2_XFER_FUNC_SMPTE240M : \ ((colsp) == V4L2_COLORSPACE_DCI_P3 ? V4L2_XFER_FUNC_DCI_P3 : \ ((colsp) == V4L2_COLORSPACE_RAW ? V4L2_XFER_FUNC_NONE : \ @@ -295,7 +295,7 @@ enum v4l2_ycbcr_encoding { * * V4L2_COLORSPACE_SMPTE170M, V4L2_COLORSPACE_470_SYSTEM_M, * V4L2_COLORSPACE_470_SYSTEM_BG, V4L2_COLORSPACE_SRGB, - * V4L2_COLORSPACE_ADOBERGB and V4L2_COLORSPACE_JPEG: V4L2_YCBCR_ENC_601 + * V4L2_COLORSPACE_OPRGB and V4L2_COLORSPACE_JPEG: V4L2_YCBCR_ENC_601 * * V4L2_COLORSPACE_REC709 and V4L2_COLORSPACE_DCI_P3: V4L2_YCBCR_ENC_709 * @@ -382,6 +382,17 @@ enum v4l2_quantization { (((is_rgb_or_hsv) || (colsp) == V4L2_COLORSPACE_JPEG) ? \ V4L2_QUANTIZATION_FULL_RANGE : V4L2_QUANTIZATION_LIM_RANGE)) +/* + * Deprecated names for opRGB colorspace (IEC 61966-2-5) + * + * WARNING: Please don't use these deprecated defines in your code, as + * there is a chance we have to remove them in the future. + */ +#ifndef __KERNEL__ +#define V4L2_COLORSPACE_ADOBERGB V4L2_COLORSPACE_OPRGB +#define V4L2_XFER_FUNC_ADOBERGB V4L2_XFER_FUNC_OPRGB +#endif + enum v4l2_priority { V4L2_PRIORITY_UNSET = 0, /* not initialized */ V4L2_PRIORITY_BACKGROUND = 1, @@ -703,6 +714,7 @@ struct v4l2_pix_format { #define V4L2_META_FMT_VSP1_HGO v4l2_fourcc('V', 'S', 'P', 'H') /* R-Car VSP1 1-D Histogram */ #define V4L2_META_FMT_VSP1_HGT v4l2_fourcc('V', 'S', 'P', 'T') /* R-Car VSP1 2-D Histogram */ #define V4L2_META_FMT_UVC v4l2_fourcc('U', 'V', 'C', 'H') /* UVC Payload Header metadata */ +#define V4L2_META_FMT_D4XX v4l2_fourcc('D', '4', 'X', 'X') /* D4XX Payload Header metadata */ /* priv field value to indicates that subsequent fields are valid. */ #define V4L2_PIX_FMT_PRIV_MAGIC 0xfeedcafe @@ -1400,6 +1412,13 @@ struct v4l2_bt_timings { * InfoFrame). */ #define V4L2_DV_FL_HAS_HDMI_VIC (1 << 8) +/* + * CEA-861 specific: only valid for video receivers. + * If set, then HW can detect the difference between regular FPS and + * 1000/1001 FPS. Note: This flag is only valid for HDMI VIC codes with + * the V4L2_DV_FL_CAN_REDUCE_FPS flag set. + */ +#define V4L2_DV_FL_CAN_DETECT_REDUCED_FPS (1 << 9) /* A few useful defines to calculate the total blanking and frame sizes */ #define V4L2_DV_BT_BLANKING_WIDTH(bt) \ |