diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-13 23:09:57 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-13 23:09:57 +0400 |
commit | 858655116bfc722837e3aec0909b8e9d08f96996 (patch) | |
tree | ef9171d51ffcd01e40d1131d62be32e5a7d371dc | |
parent | 239dab4636f7f5f971ac39b5ca84254cff112cac (diff) | |
parent | 1b2c14b44adcb7836528640bfdc40bf7499d987d (diff) | |
download | linux-858655116bfc722837e3aec0909b8e9d08f96996.tar.xz |
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab:
"This series contain:
- new i2c video drivers: ml86v7667 (video decoder),
ths8200 (video encoder)
- a new video driver for EasyCap cards based on Fushicai USBTV007
- Improved support for OF and embedded systems, with V4L2 async
initialization and a better support for clocks
- API cleanups on the ioctls used by the v4l2 debug tool
- Lots of cleanups
- As usual, several driver improvements and new cards additions
- Revert two changesets that change the minimal symbol rate for
stv0399, as request by Manu
- Update MAINTAINERS and other files to point to my new e-mail"
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (378 commits)
MAINTAINERS & ABI: Update to point to my new email
[media] stb0899: restore minimal rate to 5Mbauds
[media] exynos4-is: Correct colorspace handling at FIMC-LITE
[media] exynos4-is: Set valid initial format on FIMC.n subdevs
[media] exynos4-is: Set valid initial format on FIMC-IS-ISP subdev pads
[media] exynos4-is: Fix format propagation on FIMC-IS-ISP subdev
[media] exynos4-is: Set valid initial format at FIMC-LITE
[media] exynos4-is: Fix format propagation on FIMC-LITE.n subdevs
[media] MAINTAINERS: Update S5P/Exynos FIMC driver entry
[media] Documentation: Update driver's directory in video4linux/fimc.txt
[media] exynos4-is: Change fimc-is firmware file names
[media] exynos4-is: Add support for Exynos5250 MIPI-CSIS
[media] exynos4-is: Add Exynos5250 SoC support to fimc-lite driver
[media] exynos4-is: Drop drvdata handling in fimc-lite for non-dt platforms
[media] media: i2c: tvp514x: remove manual setting of subdev name
[media] media: i2c: tvp7002: remove manual setting of subdev name
[media] mem2mem: set missing v4l2_dev pointer
[media] wl128x: add missing struct v4l2_device
[media] tvp514x: Fix init seqeunce
[media] saa7134: Fix sparse warnings by adding __user annotation
...
359 files changed, 10887 insertions, 9847 deletions
diff --git a/Documentation/ABI/testing/sysfs-devices-edac b/Documentation/ABI/testing/sysfs-devices-edac index 30ee78aaed75..6568e0010e1a 100644 --- a/Documentation/ABI/testing/sysfs-devices-edac +++ b/Documentation/ABI/testing/sysfs-devices-edac @@ -77,7 +77,7 @@ Description: Read/Write attribute file that controls memory scrubbing. What: /sys/devices/system/edac/mc/mc*/max_location Date: April 2012 -Contact: Mauro Carvalho Chehab <mchehab@redhat.com> +Contact: Mauro Carvalho Chehab <m.chehab@samsung.com> linux-edac@vger.kernel.org Description: This attribute file displays the information about the last available memory slot in this memory controller. It is used by @@ -85,7 +85,7 @@ Description: This attribute file displays the information about the last What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/size Date: April 2012 -Contact: Mauro Carvalho Chehab <mchehab@redhat.com> +Contact: Mauro Carvalho Chehab <m.chehab@samsung.com> linux-edac@vger.kernel.org Description: This attribute file will display the size of dimm or rank. For dimm*/size, this is the size, in MB of the DIMM memory @@ -96,14 +96,14 @@ Description: This attribute file will display the size of dimm or rank. What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_dev_type Date: April 2012 -Contact: Mauro Carvalho Chehab <mchehab@redhat.com> +Contact: Mauro Carvalho Chehab <m.chehab@samsung.com> linux-edac@vger.kernel.org Description: This attribute file will display what type of DRAM device is being utilized on this DIMM (x1, x2, x4, x8, ...). What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_edac_mode Date: April 2012 -Contact: Mauro Carvalho Chehab <mchehab@redhat.com> +Contact: Mauro Carvalho Chehab <m.chehab@samsung.com> linux-edac@vger.kernel.org Description: This attribute file will display what type of Error detection and correction is being utilized. For example: S4ECD4ED would @@ -111,7 +111,7 @@ Description: This attribute file will display what type of Error detection What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_label Date: April 2012 -Contact: Mauro Carvalho Chehab <mchehab@redhat.com> +Contact: Mauro Carvalho Chehab <m.chehab@samsung.com> linux-edac@vger.kernel.org Description: This control file allows this DIMM to have a label assigned to it. With this label in the module, when errors occur @@ -126,14 +126,14 @@ Description: This control file allows this DIMM to have a label assigned What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_location Date: April 2012 -Contact: Mauro Carvalho Chehab <mchehab@redhat.com> +Contact: Mauro Carvalho Chehab <m.chehab@samsung.com> linux-edac@vger.kernel.org Description: This attribute file will display the location (csrow/channel, branch/channel/slot or channel/slot) of the dimm or rank. What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_mem_type Date: April 2012 -Contact: Mauro Carvalho Chehab <mchehab@redhat.com> +Contact: Mauro Carvalho Chehab <m.chehab@samsung.com> linux-edac@vger.kernel.org Description: This attribute file will display what type of memory is currently on this csrow. Normally, either buffered or diff --git a/Documentation/DocBook/media/v4l/compat.xml b/Documentation/DocBook/media/v4l/compat.xml index f43542ae2981..0c7195e3e093 100644 --- a/Documentation/DocBook/media/v4l/compat.xml +++ b/Documentation/DocBook/media/v4l/compat.xml @@ -2254,7 +2254,7 @@ video encoding.</para> <orderedlist> <listitem> <para>The <constant>VIDIOC_G_CHIP_IDENT</constant> ioctl was renamed -to <constant>VIDIOC_G_CHIP_IDENT_OLD</constant> and &VIDIOC-DBG-G-CHIP-IDENT; +to <constant>VIDIOC_G_CHIP_IDENT_OLD</constant> and <constant>VIDIOC_DBG_G_CHIP_IDENT</constant> was introduced in its place. The old struct <structname>v4l2_chip_ident</structname> was renamed to <structname id="v4l2-chip-ident-old">v4l2_chip_ident_old</structname>.</para> </listitem> @@ -2513,6 +2513,16 @@ that used it. It was originally scheduled for removal in 2.6.35. </orderedlist> </section> + <section> + <title>V4L2 in Linux 3.11</title> + <orderedlist> + <listitem> + <para>Remove obsolete <constant>VIDIOC_DBG_G_CHIP_IDENT</constant> ioctl. + </para> + </listitem> + </orderedlist> + </section> + <section id="other"> <title>Relation of V4L2 to other Linux multimedia APIs</title> @@ -2596,7 +2606,7 @@ and may change in the future.</para> ioctls.</para> </listitem> <listitem> - <para>&VIDIOC-DBG-G-CHIP-IDENT; ioctl.</para> + <para>&VIDIOC-DBG-G-CHIP-INFO; ioctl.</para> </listitem> <listitem> <para>&VIDIOC-ENUM-DV-TIMINGS;, &VIDIOC-QUERY-DV-TIMINGS; and diff --git a/Documentation/DocBook/media/v4l/v4l2.xml b/Documentation/DocBook/media/v4l/v4l2.xml index bfe823dd0f31..8469fe13945c 100644 --- a/Documentation/DocBook/media/v4l/v4l2.xml +++ b/Documentation/DocBook/media/v4l/v4l2.xml @@ -141,6 +141,14 @@ structs, ioctls) must be noted in more detail in the history chapter applications. --> <revision> + <revnumber>3.11</revnumber> + <date>2013-05-26</date> + <authorinitials>hv</authorinitials> + <revremark>Remove obsolete VIDIOC_DBG_G_CHIP_IDENT ioctl. + </revremark> + </revision> + + <revision> <revnumber>3.10</revnumber> <date>2013-03-25</date> <authorinitials>hv</authorinitials> @@ -493,7 +501,7 @@ and discussions on the V4L mailing list.</revremark> </partinfo> <title>Video for Linux Two API Specification</title> - <subtitle>Revision 3.10</subtitle> + <subtitle>Revision 3.11</subtitle> <chapter id="common"> &sub-common; @@ -547,7 +555,6 @@ and discussions on the V4L mailing list.</revremark> <!-- All ioctls go here. --> &sub-create-bufs; &sub-cropcap; - &sub-dbg-g-chip-ident; &sub-dbg-g-chip-info; &sub-dbg-g-register; &sub-decoder-cmd; diff --git a/Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-ident.xml b/Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-ident.xml deleted file mode 100644 index 921e18550d26..000000000000 --- a/Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-ident.xml +++ /dev/null @@ -1,271 +0,0 @@ -<refentry id="vidioc-dbg-g-chip-ident"> - <refmeta> - <refentrytitle>ioctl VIDIOC_DBG_G_CHIP_IDENT</refentrytitle> - &manvol; - </refmeta> - - <refnamediv> - <refname>VIDIOC_DBG_G_CHIP_IDENT</refname> - <refpurpose>Identify the chips on a TV card</refpurpose> - </refnamediv> - - <refsynopsisdiv> - <funcsynopsis> - <funcprototype> - <funcdef>int <function>ioctl</function></funcdef> - <paramdef>int <parameter>fd</parameter></paramdef> - <paramdef>int <parameter>request</parameter></paramdef> - <paramdef>struct v4l2_dbg_chip_ident -*<parameter>argp</parameter></paramdef> - </funcprototype> - </funcsynopsis> - </refsynopsisdiv> - - <refsect1> - <title>Arguments</title> - - <variablelist> - <varlistentry> - <term><parameter>fd</parameter></term> - <listitem> - <para>&fd;</para> - </listitem> - </varlistentry> - <varlistentry> - <term><parameter>request</parameter></term> - <listitem> - <para>VIDIOC_DBG_G_CHIP_IDENT</para> - </listitem> - </varlistentry> - <varlistentry> - <term><parameter>argp</parameter></term> - <listitem> - <para></para> - </listitem> - </varlistentry> - </variablelist> - </refsect1> - - <refsect1> - <title>Description</title> - - <note> - <title>Experimental</title> - - <para>This is an <link -linkend="experimental">experimental</link> interface and may change in -the future.</para> - </note> - - <para>For driver debugging purposes this ioctl allows test -applications to query the driver about the chips present on the TV -card. Regular applications must not use it. When you found a chip -specific bug, please contact the linux-media mailing list (&v4l-ml;) -so it can be fixed.</para> - - <para>To query the driver applications must initialize the -<structfield>match.type</structfield> and -<structfield>match.addr</structfield> or <structfield>match.name</structfield> -fields of a &v4l2-dbg-chip-ident; -and call <constant>VIDIOC_DBG_G_CHIP_IDENT</constant> with a pointer to -this structure. On success the driver stores information about the -selected chip in the <structfield>ident</structfield> and -<structfield>revision</structfield> fields. On failure the structure -remains unchanged.</para> - - <para>When <structfield>match.type</structfield> is -<constant>V4L2_CHIP_MATCH_HOST</constant>, -<structfield>match.addr</structfield> selects the nth non-&i2c; chip -on the TV card. You can enumerate all chips by starting at zero and -incrementing <structfield>match.addr</structfield> by one until -<constant>VIDIOC_DBG_G_CHIP_IDENT</constant> fails with an &EINVAL;. -The number zero always selects the host chip, ⪚ the chip connected -to the PCI or USB bus.</para> - - <para>When <structfield>match.type</structfield> is -<constant>V4L2_CHIP_MATCH_I2C_DRIVER</constant>, -<structfield>match.name</structfield> contains the I2C driver name. -For instance -<constant>"saa7127"</constant> will match any chip -supported by the saa7127 driver, regardless of its &i2c; bus address. -When multiple chips supported by the same driver are present, the -ioctl will return <constant>V4L2_IDENT_AMBIGUOUS</constant> in the -<structfield>ident</structfield> field.</para> - - <para>When <structfield>match.type</structfield> is -<constant>V4L2_CHIP_MATCH_I2C_ADDR</constant>, -<structfield>match.addr</structfield> selects a chip by its 7 bit -&i2c; bus address.</para> - - <para>When <structfield>match.type</structfield> is -<constant>V4L2_CHIP_MATCH_AC97</constant>, -<structfield>match.addr</structfield> selects the nth AC97 chip -on the TV card. You can enumerate all chips by starting at zero and -incrementing <structfield>match.addr</structfield> by one until -<constant>VIDIOC_DBG_G_CHIP_IDENT</constant> fails with an &EINVAL;.</para> - - <para>On success, the <structfield>ident</structfield> field will -contain a chip ID from the Linux -<filename>media/v4l2-chip-ident.h</filename> header file, and the -<structfield>revision</structfield> field will contain a driver -specific value, or zero if no particular revision is associated with -this chip.</para> - - <para>When the driver could not identify the selected chip, -<structfield>ident</structfield> will contain -<constant>V4L2_IDENT_UNKNOWN</constant>. When no chip matched -the ioctl will succeed but the -<structfield>ident</structfield> field will contain -<constant>V4L2_IDENT_NONE</constant>. If multiple chips matched, -<structfield>ident</structfield> will contain -<constant>V4L2_IDENT_AMBIGUOUS</constant>. In all these cases the -<structfield>revision</structfield> field remains unchanged.</para> - - <para>This ioctl is optional, not all drivers may support it. It -was introduced in Linux 2.6.21, but the API was changed to the -one described here in 2.6.29.</para> - - <para>We recommended the <application>v4l2-dbg</application> -utility over calling this ioctl directly. It is available from the -LinuxTV v4l-dvb repository; see <ulink -url="http://linuxtv.org/repo/">http://linuxtv.org/repo/</ulink> for -access instructions.</para> - - <!-- Note for convenience vidioc-dbg-g-register.sgml - contains a duplicate of this table. --> - <table pgwide="1" frame="none" id="ident-v4l2-dbg-match"> - <title>struct <structname>v4l2_dbg_match</structname></title> - <tgroup cols="4"> - &cs-ustr; - <tbody valign="top"> - <row> - <entry>__u32</entry> - <entry><structfield>type</structfield></entry> - <entry>See <xref linkend="ident-chip-match-types" /> for a list of -possible types.</entry> - </row> - <row> - <entry>union</entry> - <entry>(anonymous)</entry> - </row> - <row> - <entry></entry> - <entry>__u32</entry> - <entry><structfield>addr</structfield></entry> - <entry>Match a chip by this number, interpreted according -to the <structfield>type</structfield> field.</entry> - </row> - <row> - <entry></entry> - <entry>char</entry> - <entry><structfield>name[32]</structfield></entry> - <entry>Match a chip by this name, interpreted according -to the <structfield>type</structfield> field.</entry> - </row> - </tbody> - </tgroup> - </table> - - <table pgwide="1" frame="none" id="v4l2-dbg-chip-ident"> - <title>struct <structname>v4l2_dbg_chip_ident</structname></title> - <tgroup cols="3"> - &cs-str; - <tbody valign="top"> - <row> - <entry>struct v4l2_dbg_match</entry> - <entry><structfield>match</structfield></entry> - <entry>How to match the chip, see <xref linkend="ident-v4l2-dbg-match" />.</entry> - </row> - <row> - <entry>__u32</entry> - <entry><structfield>ident</structfield></entry> - <entry>A chip identifier as defined in the Linux -<filename>media/v4l2-chip-ident.h</filename> header file, or one of -the values from <xref linkend="chip-ids" />.</entry> - </row> - <row> - <entry>__u32</entry> - <entry><structfield>revision</structfield></entry> - <entry>A chip revision, chip and driver specific.</entry> - </row> - </tbody> - </tgroup> - </table> - - <!-- Note for convenience vidioc-dbg-g-register.sgml - contains a duplicate of this table. --> - <table pgwide="1" frame="none" id="ident-chip-match-types"> - <title>Chip Match Types</title> - <tgroup cols="3"> - &cs-def; - <tbody valign="top"> - <row> - <entry><constant>V4L2_CHIP_MATCH_BRIDGE</constant></entry> - <entry>0</entry> - <entry>Match the nth chip on the card, zero for the - bridge chip. Does not match sub-devices.</entry> - </row> - <row> - <entry><constant>V4L2_CHIP_MATCH_I2C_DRIVER</constant></entry> - <entry>1</entry> - <entry>Match an &i2c; chip by its driver name.</entry> - </row> - <row> - <entry><constant>V4L2_CHIP_MATCH_I2C_ADDR</constant></entry> - <entry>2</entry> - <entry>Match a chip by its 7 bit &i2c; bus address.</entry> - </row> - <row> - <entry><constant>V4L2_CHIP_MATCH_AC97</constant></entry> - <entry>3</entry> - <entry>Match the nth anciliary AC97 chip.</entry> - </row> - <row> - <entry><constant>V4L2_CHIP_MATCH_SUBDEV</constant></entry> - <entry>4</entry> - <entry>Match the nth sub-device. Can't be used with this ioctl.</entry> - </row> - </tbody> - </tgroup> - </table> - - <!-- This is an anonymous enum in media/v4l2-chip-ident.h. --> - <table pgwide="1" frame="none" id="chip-ids"> - <title>Chip Identifiers</title> - <tgroup cols="3"> - &cs-def; - <tbody valign="top"> - <row> - <entry><constant>V4L2_IDENT_NONE</constant></entry> - <entry>0</entry> - <entry>No chip matched.</entry> - </row> - <row> - <entry><constant>V4L2_IDENT_AMBIGUOUS</constant></entry> - <entry>1</entry> - <entry>Multiple chips matched.</entry> - </row> - <row> - <entry><constant>V4L2_IDENT_UNKNOWN</constant></entry> - <entry>2</entry> - <entry>A chip is present at this address, but the driver -could not identify it.</entry> - </row> - </tbody> - </tgroup> - </table> - </refsect1> - - <refsect1> - &return-value; - - <variablelist> - <varlistentry> - <term><errorcode>EINVAL</errorcode></term> - <listitem> - <para>The <structfield>match_type</structfield> is invalid.</para> - </listitem> - </varlistentry> - </variablelist> - </refsect1> -</refentry> diff --git a/Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-info.xml b/Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-info.xml index e1cece6c5de1..4c4603c135fe 100644 --- a/Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-info.xml +++ b/Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-info.xml @@ -73,8 +73,7 @@ fields of a &v4l2-dbg-chip-info; and call <constant>VIDIOC_DBG_G_CHIP_INFO</constant> with a pointer to this structure. On success the driver stores information about the selected chip in the <structfield>name</structfield> and -<structfield>flags</structfield> fields. On failure the structure -remains unchanged.</para> +<structfield>flags</structfield> fields.</para> <para>When <structfield>match.type</structfield> is <constant>V4L2_CHIP_MATCH_BRIDGE</constant>, @@ -132,7 +131,7 @@ to the <structfield>type</structfield> field.</entry> <entry>char</entry> <entry><structfield>name[32]</structfield></entry> <entry>Match a chip by this name, interpreted according -to the <structfield>type</structfield> field.</entry> +to the <structfield>type</structfield> field. Currently unused.</entry> </row> </tbody> </tgroup> @@ -183,21 +182,6 @@ is set, then the driver supports reading registers from the device. If bridge chip. Does not match sub-devices.</entry> </row> <row> - <entry><constant>V4L2_CHIP_MATCH_I2C_DRIVER</constant></entry> - <entry>1</entry> - <entry>Match an &i2c; chip by its driver name. Can't be used with this ioctl.</entry> - </row> - <row> - <entry><constant>V4L2_CHIP_MATCH_I2C_ADDR</constant></entry> - <entry>2</entry> - <entry>Match a chip by its 7 bit &i2c; bus address. Can't be used with this ioctl.</entry> - </row> - <row> - <entry><constant>V4L2_CHIP_MATCH_AC97</constant></entry> - <entry>3</entry> - <entry>Match the nth anciliary AC97 chip. Can't be used with this ioctl.</entry> - </row> - <row> <entry><constant>V4L2_CHIP_MATCH_SUBDEV</constant></entry> <entry>4</entry> <entry>Match the nth sub-device.</entry> diff --git a/Documentation/DocBook/media/v4l/vidioc-dbg-g-register.xml b/Documentation/DocBook/media/v4l/vidioc-dbg-g-register.xml index d13bac9e2445..3d038e75d12b 100644 --- a/Documentation/DocBook/media/v4l/vidioc-dbg-g-register.xml +++ b/Documentation/DocBook/media/v4l/vidioc-dbg-g-register.xml @@ -76,7 +76,7 @@ compiled with the <constant>CONFIG_VIDEO_ADV_DEBUG</constant> option to enable these ioctls.</para> <para>To write a register applications must initialize all fields -of a &v4l2-dbg-register; and call +of a &v4l2-dbg-register; except for <structfield>size</structfield> and call <constant>VIDIOC_DBG_S_REGISTER</constant> with a pointer to this structure. The <structfield>match.type</structfield> and <structfield>match.addr</structfield> or <structfield>match.name</structfield> @@ -91,8 +91,8 @@ written into the register.</para> <structfield>reg</structfield> fields, and call <constant>VIDIOC_DBG_G_REGISTER</constant> with a pointer to this structure. On success the driver stores the register value in the -<structfield>val</structfield> field. On failure the structure remains -unchanged.</para> +<structfield>val</structfield> field and the size (in bytes) of the +value in <structfield>size</structfield>.</para> <para>When <structfield>match.type</structfield> is <constant>V4L2_CHIP_MATCH_BRIDGE</constant>, @@ -102,39 +102,9 @@ chip connected to the PCI or USB bus. You can find out which chips are present with the &VIDIOC-DBG-G-CHIP-INFO; ioctl.</para> <para>When <structfield>match.type</structfield> is -<constant>V4L2_CHIP_MATCH_I2C_DRIVER</constant>, -<structfield>match.name</structfield> contains the I2C driver name. -For instance -<constant>"saa7127"</constant> will match any chip -supported by the saa7127 driver, regardless of its &i2c; bus address. -When multiple chips supported by the same driver are present, the -effect of these ioctls is undefined. Again with the -&VIDIOC-DBG-G-CHIP-INFO; ioctl you can find out which &i2c; chips are -present.</para> - - <para>When <structfield>match.type</structfield> is -<constant>V4L2_CHIP_MATCH_I2C_ADDR</constant>, -<structfield>match.addr</structfield> selects a chip by its 7 bit &i2c; -bus address.</para> - - <para>When <structfield>match.type</structfield> is -<constant>V4L2_CHIP_MATCH_AC97</constant>, -<structfield>match.addr</structfield> selects the nth AC97 chip -on the TV card.</para> - - <para>When <structfield>match.type</structfield> is <constant>V4L2_CHIP_MATCH_SUBDEV</constant>, <structfield>match.addr</structfield> selects the nth sub-device.</para> - <note> - <title>Success not guaranteed</title> - - <para>Due to a flaw in the Linux &i2c; bus driver these ioctls may -return successfully without actually reading or writing a register. To -catch the most likely failure we recommend a &VIDIOC-DBG-G-CHIP-INFO; -call confirming the presence of the selected &i2c; chip.</para> - </note> - <para>These ioctls are optional, not all drivers may support them. However when a driver supports these ioctls it must also support &VIDIOC-DBG-G-CHIP-INFO;. Conversely it may support @@ -150,7 +120,7 @@ LinuxTV v4l-dvb repository; see <ulink url="http://linuxtv.org/repo/">http://linuxtv.org/repo/</ulink> for access instructions.</para> - <!-- Note for convenience vidioc-dbg-g-chip-ident.sgml + <!-- Note for convenience vidioc-dbg-g-chip-info.sgml contains a duplicate of this table. --> <table pgwide="1" frame="none" id="v4l2-dbg-match"> <title>struct <structname>v4l2_dbg_match</structname></title> @@ -160,7 +130,7 @@ access instructions.</para> <row> <entry>__u32</entry> <entry><structfield>type</structfield></entry> - <entry>See <xref linkend="ident-chip-match-types" /> for a list of + <entry>See <xref linkend="chip-match-types" /> for a list of possible types.</entry> </row> <row> @@ -179,7 +149,7 @@ to the <structfield>type</structfield> field.</entry> <entry>char</entry> <entry><structfield>name[32]</structfield></entry> <entry>Match a chip by this name, interpreted according -to the <structfield>type</structfield> field.</entry> +to the <structfield>type</structfield> field. Currently unused.</entry> </row> </tbody> </tgroup> @@ -199,6 +169,11 @@ to the <structfield>type</structfield> field.</entry> <entry>How to match the chip, see <xref linkend="v4l2-dbg-match" />.</entry> </row> <row> + <entry>__u32</entry> + <entry><structfield>size</structfield></entry> + <entry>The register size in bytes.</entry> + </row> + <row> <entry>__u64</entry> <entry><structfield>reg</structfield></entry> <entry>A register number.</entry> @@ -213,7 +188,7 @@ register.</entry> </tgroup> </table> - <!-- Note for convenience vidioc-dbg-g-chip-ident.sgml + <!-- Note for convenience vidioc-dbg-g-chip-info.sgml contains a duplicate of this table. --> <table pgwide="1" frame="none" id="chip-match-types"> <title>Chip Match Types</title> @@ -227,21 +202,6 @@ register.</entry> bridge chip. Does not match sub-devices.</entry> </row> <row> - <entry><constant>V4L2_CHIP_MATCH_I2C_DRIVER</constant></entry> - <entry>1</entry> - <entry>Match an &i2c; chip by its driver name.</entry> - </row> - <row> - <entry><constant>V4L2_CHIP_MATCH_I2C_ADDR</constant></entry> - <entry>2</entry> - <entry>Match a chip by its 7 bit &i2c; bus address.</entry> - </row> - <row> - <entry><constant>V4L2_CHIP_MATCH_AC97</constant></entry> - <entry>3</entry> - <entry>Match the nth anciliary AC97 chip.</entry> - </row> - <row> <entry><constant>V4L2_CHIP_MATCH_SUBDEV</constant></entry> <entry>4</entry> <entry>Match the nth sub-device.</entry> diff --git a/Documentation/DocBook/media/v4l/vidioc-querystd.xml b/Documentation/DocBook/media/v4l/vidioc-querystd.xml index fe80a183d957..222348542182 100644 --- a/Documentation/DocBook/media/v4l/vidioc-querystd.xml +++ b/Documentation/DocBook/media/v4l/vidioc-querystd.xml @@ -54,7 +54,8 @@ standard automatically. To do so, applications call <constant> VIDIOC_QUERYSTD</constant> with a pointer to a &v4l2-std-id; type. The driver stores here a set of candidates, this can be a single flag or a set of supported standards if for example the hardware can only -distinguish between 50 and 60 Hz systems. When detection is not +distinguish between 50 and 60 Hz systems. If no signal was detected, +then the driver will return V4L2_STD_UNKNOWN. When detection is not possible or fails, the set must contain all standards supported by the current video input or output.</para> diff --git a/Documentation/devicetree/bindings/media/exynos-fimc-lite.txt b/Documentation/devicetree/bindings/media/exynos-fimc-lite.txt index de9f6b78ee51..0bf6fb7fbeab 100644 --- a/Documentation/devicetree/bindings/media/exynos-fimc-lite.txt +++ b/Documentation/devicetree/bindings/media/exynos-fimc-lite.txt @@ -2,8 +2,10 @@ Exynos4x12/Exynos5 SoC series camera host interface (FIMC-LITE) Required properties: -- compatible : should be "samsung,exynos4212-fimc-lite" for Exynos4212 and - Exynos4412 SoCs; +- compatible : should be one of: + "samsung,exynos4212-fimc-lite" for Exynos4212/4412 SoCs, + "samsung,exynos5250-fimc-lite" for Exynos5250 compatible + devices; - reg : physical base address and size of the device memory mapped registers; - interrupts : should contain FIMC-LITE interrupt; diff --git a/Documentation/devicetree/bindings/media/i2c/mt9p031.txt b/Documentation/devicetree/bindings/media/i2c/mt9p031.txt new file mode 100644 index 000000000000..cb60443ff78f --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/mt9p031.txt @@ -0,0 +1,40 @@ +* Aptina 1/2.5-Inch 5Mp CMOS Digital Image Sensor + +The Aptina MT9P031 is a 1/2.5-inch CMOS active pixel digital image sensor with +an active array size of 2592H x 1944V. It is programmable through a simple +two-wire serial interface. + +Required Properties: +- compatible: value should be either one among the following + (a) "aptina,mt9p031" for mt9p031 sensor + (b) "aptina,mt9p031m" for mt9p031m sensor + +- input-clock-frequency: Input clock frequency. + +- pixel-clock-frequency: Pixel clock frequency. + +Optional Properties: +- reset-gpios: Chip reset GPIO + +For further reading on port node refer to +Documentation/devicetree/bindings/media/video-interfaces.txt. + +Example: + + i2c0@1c22000 { + ... + ... + mt9p031@5d { + compatible = "aptina,mt9p031"; + reg = <0x5d>; + reset-gpios = <&gpio3 30 0>; + + port { + mt9p031_1: endpoint { + input-clock-frequency = <6000000>; + pixel-clock-frequency = <96000000>; + }; + }; + }; + ... + }; diff --git a/Documentation/devicetree/bindings/media/i2c/tvp514x.txt b/Documentation/devicetree/bindings/media/i2c/tvp514x.txt new file mode 100644 index 000000000000..46752cc71f2e --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/tvp514x.txt @@ -0,0 +1,44 @@ +* Texas Instruments TVP514x video decoder + +The TVP5146/TVP5146m2/TVP5147/TVP5147m1 device is high quality, single-chip +digital video decoder that digitizes and decodes all popular baseband analog +video formats into digital video component. The tvp514x decoder supports analog- +to-digital (A/D) conversion of component RGB and YPbPr signals as well as A/D +conversion and decoding of NTSC, PAL and SECAM composite and S-video into +component YCbCr. + +Required Properties : +- compatible : value should be either one among the following + (a) "ti,tvp5146" for tvp5146 decoder. + (b) "ti,tvp5146m2" for tvp5146m2 decoder. + (c) "ti,tvp5147" for tvp5147 decoder. + (d) "ti,tvp5147m1" for tvp5147m1 decoder. + +- hsync-active: HSYNC Polarity configuration for endpoint. + +- vsync-active: VSYNC Polarity configuration for endpoint. + +- pclk-sample: Clock polarity of the endpoint. + +For further reading on port node refer to Documentation/devicetree/bindings/ +media/video-interfaces.txt. + +Example: + + i2c0@1c22000 { + ... + ... + tvp514x@5c { + compatible = "ti,tvp5146"; + reg = <0x5c>; + + port { + tvp514x_1: endpoint { + hsync-active = <1>; + vsync-active = <1>; + pclk-sample = <0>; + }; + }; + }; + ... + }; diff --git a/Documentation/devicetree/bindings/media/samsung-fimc.txt b/Documentation/devicetree/bindings/media/samsung-fimc.txt index 51c776b7f7a3..96312f6c4c26 100644 --- a/Documentation/devicetree/bindings/media/samsung-fimc.txt +++ b/Documentation/devicetree/bindings/media/samsung-fimc.txt @@ -127,22 +127,22 @@ Example: }; }; }; - }; - /* MIPI CSI-2 bus IF sensor */ - s5c73m3: sensor@0x1a { - compatible = "samsung,s5c73m3"; - reg = <0x1a>; - vddio-supply = <...>; + /* MIPI CSI-2 bus IF sensor */ + s5c73m3: sensor@0x1a { + compatible = "samsung,s5c73m3"; + reg = <0x1a>; + vddio-supply = <...>; - clock-frequency = <24000000>; - clocks = <...>; - clock-names = "mclk"; + clock-frequency = <24000000>; + clocks = <...>; + clock-names = "mclk"; - port { - s5c73m3_1: endpoint { - data-lanes = <1 2 3 4>; - remote-endpoint = <&csis0_ep>; + port { + s5c73m3_1: endpoint { + data-lanes = <1 2 3 4>; + remote-endpoint = <&csis0_ep>; + }; }; }; }; diff --git a/Documentation/devicetree/bindings/media/samsung-mipi-csis.txt b/Documentation/devicetree/bindings/media/samsung-mipi-csis.txt index 5f8e28e2484f..be45f0b1a449 100644 --- a/Documentation/devicetree/bindings/media/samsung-mipi-csis.txt +++ b/Documentation/devicetree/bindings/media/samsung-mipi-csis.txt @@ -5,8 +5,8 @@ Required properties: - compatible : "samsung,s5pv210-csis" for S5PV210 (S5PC110), "samsung,exynos4210-csis" for Exynos4210 (S5PC210), - "samsung,exynos4212-csis" for Exynos4212/Exynos4412 - SoC series; + "samsung,exynos4212-csis" for Exynos4212/Exynos4412, + "samsung,exynos5250-csis" for Exynos5250; - reg : offset and length of the register set for the device; - interrupts : should contain MIPI CSIS interrupt; the format of the interrupt specifier depends on the interrupt controller; diff --git a/Documentation/devicetree/bindings/media/sh_mobile_ceu.txt b/Documentation/devicetree/bindings/media/sh_mobile_ceu.txt new file mode 100644 index 000000000000..1ce4e46bcbb7 --- /dev/null +++ b/Documentation/devicetree/bindings/media/sh_mobile_ceu.txt @@ -0,0 +1,18 @@ +Bindings, specific for the sh_mobile_ceu_camera.c driver: + - compatible: Should be "renesas,sh-mobile-ceu" + - reg: register base and size + - interrupts: the interrupt number + - interrupt-parent: the interrupt controller + - renesas,max-width: maximum image width, supported on this SoC + - renesas,max-height: maximum image height, supported on this SoC + +Example: + +ceu0: ceu@0xfe910000 { + compatible = "renesas,sh-mobile-ceu"; + reg = <0xfe910000 0xa0>; + interrupt-parent = <&intcs>; + interrupts = <0x880>; + renesas,max-width = <8188>; + renesas,max-height = <8188>; +}; diff --git a/Documentation/media-framework.txt b/Documentation/media-framework.txt index eeced24e56af..f552a75c0e70 100644 --- a/Documentation/media-framework.txt +++ b/Documentation/media-framework.txt @@ -265,7 +265,7 @@ connected to another pad through an enabled link media_entity_find_link(struct media_pad *source, struct media_pad *sink); - media_entity_remote_source(struct media_pad *pad); + media_entity_remote_pad(struct media_pad *pad); Refer to the kerneldoc documentation for more information. diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv index 581f666a76cf..f14475011fea 100644 --- a/Documentation/video4linux/CARDLIST.bttv +++ b/Documentation/video4linux/CARDLIST.bttv @@ -160,3 +160,6 @@ 159 -> ProVideo PV183 [1830:1540,1831:1540,1832:1540,1833:1540,1834:1540,1835:1540,1836:1540,1837:1540] 160 -> Tongwei Video Technology TD-3116 [f200:3116] 161 -> Aposonic W-DVR [0279:0228] +162 -> Adlink MPG24 +163 -> Bt848 Capture 14MHz +164 -> CyberVision CV06 (SV) diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index b3ad68309109..8df17d063499 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -190,3 +190,4 @@ 189 -> Kworld PC150-U [17de:a134] 190 -> Asus My Cinema PS3-100 [1043:48cd] 191 -> Hawell HW-9004V1 +192 -> AverMedia AverTV Satellite Hybrid+FM A706 [1461:2055] diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner index 5b83a3ff15c2..ac8862184962 100644 --- a/Documentation/video4linux/CARDLIST.tuner +++ b/Documentation/video4linux/CARDLIST.tuner @@ -86,6 +86,6 @@ tuner=85 - Philips FQ1236 MK5 tuner=86 - Tena TNF5337 MFD tuner=87 - Xceive 4000 tuner tuner=88 - Xceive 5000C tuner -tuner=89 - Sony PAL+SECAM (BTF-PG472Z) -tuner=90 - Sony NTSC-M-JP (BTF-PK467Z) -tuner=91 - Sony NTSC-M (BTF-PB463Z) +tuner=89 - Sony BTF-PG472Z PAL/SECAM +tuner=90 - Sony BTF-PK467Z NTSC-M-JP +tuner=91 - Sony BTF-PB463Z NTSC-M diff --git a/Documentation/video4linux/fimc.txt b/Documentation/video4linux/fimc.txt index 25f4d3402722..e51f1b5b7324 100644 --- a/Documentation/video4linux/fimc.txt +++ b/Documentation/video4linux/fimc.txt @@ -1,6 +1,6 @@ Samsung S5P/EXYNOS4 FIMC driver -Copyright (C) 2012 Samsung Electronics Co., Ltd. +Copyright (C) 2012 - 2013 Samsung Electronics Co., Ltd. --------------------------------------------------------------------------- The FIMC (Fully Interactive Mobile Camera) device available in Samsung @@ -10,7 +10,7 @@ data from LCD controller (FIMD) through the SoC internal writeback data path. There are multiple FIMC instances in the SoCs (up to 4), having slightly different capabilities, like pixel alignment constraints, rotator availability, LCD writeback support, etc. The driver is located at -drivers/media/platform/s5p-fimc directory. +drivers/media/platform/exynos4-is directory. 1. Supported SoCs ================= @@ -36,21 +36,21 @@ Not currently supported: ===================== - media device driver - drivers/media/platform/s5p-fimc/fimc-mdevice.[ch] + drivers/media/platform/exynos4-is/media-dev.[ch] - camera capture video device driver - drivers/media/platform/s5p-fimc/fimc-capture.c + drivers/media/platform/exynos4-is/fimc-capture.c - MIPI-CSI2 receiver subdev - drivers/media/platform/s5p-fimc/mipi-csis.[ch] + drivers/media/platform/exynos4-is/mipi-csis.[ch] - video post-processor (mem-to-mem) - drivers/media/platform/s5p-fimc/fimc-core.c + drivers/media/platform/exynos4-is/fimc-core.c - common files - drivers/media/platform/s5p-fimc/fimc-core.h - drivers/media/platform/s5p-fimc/fimc-reg.h - drivers/media/platform/s5p-fimc/regs-fimc.h + drivers/media/platform/exynos4-is/fimc-core.h + drivers/media/platform/exynos4-is/fimc-reg.h + drivers/media/platform/exynos4-is/regs-fimc.h 4. User space interfaces ======================== @@ -143,7 +143,8 @@ or retrieve the information from /dev/media? with help of the media-ctl tool: 6. Platform support =================== -The machine code (plat-s5p and arch/arm/mach-*) must select following options +The machine code (arch/arm/plat-samsung and arch/arm/mach-*) must select +following options: CONFIG_S5P_DEV_FIMC0 mandatory CONFIG_S5P_DEV_FIMC1 \ diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt index a300b283a1a0..6c4866b49eb5 100644 --- a/Documentation/video4linux/v4l2-framework.txt +++ b/Documentation/video4linux/v4l2-framework.txt @@ -246,7 +246,6 @@ may be NULL if the subdev driver does not support anything from that category. It looks like this: struct v4l2_subdev_core_ops { - int (*g_chip_ident)(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip); int (*log_status)(struct v4l2_subdev *sd); int (*init)(struct v4l2_subdev *sd, u32 val); ... @@ -326,8 +325,27 @@ that width, height and the media bus pixel code are equal on both source and sink of the link. Subdev drivers are also free to use this function to perform the checks mentioned above in addition to their own checks. -A device (bridge) driver needs to register the v4l2_subdev with the -v4l2_device: +There are currently two ways to register subdevices with the V4L2 core. The +first (traditional) possibility is to have subdevices registered by bridge +drivers. This can be done when the bridge driver has the complete information +about subdevices connected to it and knows exactly when to register them. This +is typically the case for internal subdevices, like video data processing units +within SoCs or complex PCI(e) boards, camera sensors in USB cameras or connected +to SoCs, which pass information about them to bridge drivers, usually in their +platform data. + +There are however also situations where subdevices have to be registered +asynchronously to bridge devices. An example of such a configuration is a Device +Tree based system where information about subdevices is made available to the +system independently from the bridge devices, e.g. when subdevices are defined +in DT as I2C device nodes. The API used in this second case is described further +below. + +Using one or the other registration method only affects the probing process, the +run-time bridge-subdevice interaction is in both cases the same. + +In the synchronous case a device (bridge) driver needs to register the +v4l2_subdev with the v4l2_device: int err = v4l2_device_register_subdev(v4l2_dev, sd); @@ -346,24 +364,24 @@ Afterwards the subdev module can be unloaded and sd->dev == NULL. You can call an ops function either directly: - err = sd->ops->core->g_chip_ident(sd, &chip); + err = sd->ops->core->g_std(sd, &norm); but it is better and easier to use this macro: - err = v4l2_subdev_call(sd, core, g_chip_ident, &chip); + err = v4l2_subdev_call(sd, core, g_std, &norm); The macro will to the right NULL pointer checks and returns -ENODEV if subdev -is NULL, -ENOIOCTLCMD if either subdev->core or subdev->core->g_chip_ident is -NULL, or the actual result of the subdev->ops->core->g_chip_ident ops. +is NULL, -ENOIOCTLCMD if either subdev->core or subdev->core->g_std is +NULL, or the actual result of the subdev->ops->core->g_std ops. It is also possible to call all or a subset of the sub-devices: - v4l2_device_call_all(v4l2_dev, 0, core, g_chip_ident, &chip); + v4l2_device_call_all(v4l2_dev, 0, core, g_std, &norm); Any subdev that does not support this ops is skipped and error results are ignored. If you want to check for errors use this: - err = v4l2_device_call_until_err(v4l2_dev, 0, core, g_chip_ident, &chip); + err = v4l2_device_call_until_err(v4l2_dev, 0, core, g_std, &norm); Any error except -ENOIOCTLCMD will exit the loop with that error. If no errors (except -ENOIOCTLCMD) occurred, then 0 is returned. @@ -394,6 +412,30 @@ controlled through GPIO pins. This distinction is only relevant when setting up the device, but once the subdev is registered it is completely transparent. +In the asynchronous case subdevice probing can be invoked independently of the +bridge driver availability. The subdevice driver then has to verify whether all +the requirements for a successful probing are satisfied. This can include a +check for a master clock availability. If any of the conditions aren't satisfied +the driver might decide to return -EPROBE_DEFER to request further reprobing +attempts. Once all conditions are met the subdevice shall be registered using +the v4l2_async_register_subdev() function. Unregistration is performed using +the 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 +performed using the v4l2_async_notifier_register() call. To unregister the +notifier the driver has to call v4l2_async_notifier_unregister(). The former of +the two functions takes two arguments: a pointer to struct v4l2_device and a +pointer to struct v4l2_async_notifier. The latter contains a pointer to an array +of pointers to subdevice descriptors of type struct 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. + + V4L2 sub-device userspace API ----------------------------- @@ -575,9 +617,13 @@ of the video device exits. The default video_device_release() callback just calls kfree to free the allocated memory. +There is also a video_device_release_empty() function that does nothing +(is empty) and can be used if the struct is embedded and there is nothing +to do when it is released. + You should also set these fields: -- v4l2_dev: set to the v4l2_device parent device. +- v4l2_dev: must be set to the v4l2_device parent device. - name: set to something descriptive and unique. @@ -614,15 +660,16 @@ You should also set these fields: If you want to have a separate priority state per (group of) device node(s), then you can point it to your own struct v4l2_prio_state. -- parent: you only set this if v4l2_device was registered with NULL as +- dev_parent: you only set this if v4l2_device was registered with NULL as the parent device struct. This only happens in cases where one hardware device has multiple PCI devices that all share the same v4l2_device core. The cx88 driver is an example of this: one core v4l2_device struct, but - it is used by both an raw video PCI device (cx8800) and a MPEG PCI device - (cx8802). Since the v4l2_device cannot be associated with a particular - PCI device it is setup without a parent device. But when the struct - video_device is setup you do know which parent PCI device to use. + it is used by both a raw video PCI device (cx8800) and a MPEG PCI device + (cx8802). Since the v4l2_device cannot be associated with two PCI devices + at the same time it is setup without a parent device. But when the struct + video_device is initialized you *do* know which parent PCI device to use and + so you set dev_device to the correct PCI device. - flags: optional. Set to V4L2_FL_USE_FH_PRIO if you want to let the framework handle the VIDIOC_G/S_PRIORITY ioctls. This requires that you use struct @@ -1061,3 +1108,29 @@ available event type is 'class base + 1'. An example on how the V4L2 events may be used can be found in the OMAP 3 ISP driver (drivers/media/platform/omap3isp). + + +V4L2 clocks +----------- + +Many subdevices, like camera sensors, TV decoders and encoders, need a clock +signal to be supplied by the system. Often this clock is supplied by the +respective bridge device. The Linux kernel provides a Common Clock Framework for +this purpose. However, it is not (yet) available on all architectures. Besides, +the nature of the multi-functional (clock, data + synchronisation, I2C control) +connection of subdevices to the system might impose special requirements on the +clock API usage. E.g. V4L2 has to support clock provider driver unregistration +while a subdevice driver is holding a reference to the clock. For these reasons +a V4L2 clock helper API has been developed and is provided to bridge and +subdevice drivers. + +The API consists of two parts: two functions to register and unregister a V4L2 +clock source: v4l2_clk_register() and v4l2_clk_unregister() and calls to control +a clock object, similar to the respective generic clock API calls: +v4l2_clk_get(), v4l2_clk_put(), v4l2_clk_enable(), v4l2_clk_disable(), +v4l2_clk_get_rate(), and v4l2_clk_set_rate(). Clock suppliers have to provide +clock operations that will be called when clock users invoke respective API +methods. + +It is expected that once the CCF becomes available on all relevant +architectures this API will be removed. diff --git a/Documentation/zh_CN/video4linux/v4l2-framework.txt b/Documentation/zh_CN/video4linux/v4l2-framework.txt index 44c1d934c4e3..0da95dbaef34 100644 --- a/Documentation/zh_CN/video4linux/v4l2-framework.txt +++ b/Documentation/zh_CN/video4linux/v4l2-framework.txt @@ -247,7 +247,6 @@ i2c_client 结构体,i2c_set_clientdata() 函数可用于保存一个 v4l2_sub 这些结构体定义如下: struct v4l2_subdev_core_ops { - int (*g_chip_ident)(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip); int (*log_status)(struct v4l2_subdev *sd); int (*init)(struct v4l2_subdev *sd, u32 val); ... @@ -337,24 +336,24 @@ subdev->dev 域就指向了 v4l2_device。 注册之设备后,可通过以下方式直接调用其操作函数: - err = sd->ops->core->g_chip_ident(sd, &chip); + err = sd->ops->core->g_std(sd, &norm); 但使用如下宏会比较容易且合适: - err = v4l2_subdev_call(sd, core, g_chip_ident, &chip); + err = v4l2_subdev_call(sd, core, g_std, &norm); 这个宏将会做 NULL 指针检查,如果 subdev 为 NULL,则返回-ENODEV;如果 -subdev->core 或 subdev->core->g_chip_ident 为 NULL,则返回 -ENOIOCTLCMD; -否则将返回 subdev->ops->core->g_chip_ident ops 调用的实际结果。 +subdev->core 或 subdev->core->g_std 为 NULL,则返回 -ENOIOCTLCMD; +否则将返回 subdev->ops->core->g_std ops 调用的实际结果。 有时也可能同时调用所有或一系列子设备的某个操作函数: - v4l2_device_call_all(v4l2_dev, 0, core, g_chip_ident, &chip); + v4l2_device_call_all(v4l2_dev, 0, core, g_std, &norm); 任何不支持此操作的子设备都会被跳过,并忽略错误返回值。但如果你需要 检查出错码,则可使用如下函数: - err = v4l2_device_call_until_err(v4l2_dev, 0, core, g_chip_ident, &chip); + err = v4l2_device_call_until_err(v4l2_dev, 0, core, g_std, &norm); 除 -ENOIOCTLCMD 外的任何错误都会跳出循环并返回错误值。如果(除 -ENOIOCTLCMD 外)没有错误发生,则返回 0。 diff --git a/MAINTAINERS b/MAINTAINERS index 9d771d9825cf..b41a9fce3211 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1165,15 +1165,6 @@ L: linux-media@vger.kernel.org S: Maintained F: drivers/media/platform/s5p-g2d/ -ARM/SAMSUNG S5P SERIES FIMC SUPPORT -M: Kyungmin Park <kyungmin.park@samsung.com> -M: Sylwester Nawrocki <s.nawrocki@samsung.com> -L: linux-arm-kernel@lists.infradead.org -L: linux-media@vger.kernel.org -S: Maintained -F: arch/arm/plat-samsung/include/plat/*fimc* -F: drivers/media/platform/s5p-fimc/ - ARM/SAMSUNG S5P SERIES Multi Format Codec (MFC) SUPPORT M: Kyungmin Park <kyungmin.park@samsung.com> M: Kamil Debski <k.debski@samsung.com> @@ -1595,7 +1586,7 @@ F: include/net/ax25.h F: net/ax25/ AZ6007 DVB DRIVER -M: Mauro Carvalho Chehab <mchehab@redhat.com> +M: Mauro Carvalho Chehab <m.chehab@samsung.com> L: linux-media@vger.kernel.org W: http://linuxtv.org T: git git://linuxtv.org/media_tree.git @@ -1880,7 +1871,7 @@ F: Documentation/filesystems/btrfs.txt F: fs/btrfs/ BTTV VIDEO4LINUX DRIVER -M: Mauro Carvalho Chehab <mchehab@redhat.com> +M: Mauro Carvalho Chehab <m.chehab@samsung.com> L: linux-media@vger.kernel.org W: http://linuxtv.org T: git git://linuxtv.org/media_tree.git @@ -2368,7 +2359,7 @@ F: drivers/media/common/cx2341x* F: include/media/cx2341x* CX88 VIDEO4LINUX DRIVER -M: Mauro Carvalho Chehab <mchehab@redhat.com> +M: Mauro Carvalho Chehab <m.chehab@samsung.com> L: linux-media@vger.kernel.org W: http://linuxtv.org T: git git://linuxtv.org/media_tree.git @@ -2990,7 +2981,7 @@ S: Maintained F: drivers/edac/e7xxx_edac.c EDAC-GHES -M: Mauro Carvalho Chehab <mchehab@redhat.com> +M: Mauro Carvalho Chehab <m.chehab@samsung.com> L: linux-edac@vger.kernel.org W: bluesmoke.sourceforge.net S: Maintained @@ -3018,21 +3009,21 @@ S: Maintained F: drivers/edac/i5000_edac.c EDAC-I5400 -M: Mauro Carvalho Chehab <mchehab@redhat.com> +M: Mauro Carvalho Chehab <m.chehab@samsung.com> L: linux-edac@vger.kernel.org W: bluesmoke.sourceforge.net S: Maintained F: drivers/edac/i5400_edac.c EDAC-I7300 -M: Mauro Carvalho Chehab <mchehab@redhat.com> +M: Mauro Carvalho Chehab <m.chehab@samsung.com> L: linux-edac@vger.kernel.org W: bluesmoke.sourceforge.net S: Maintained F: drivers/edac/i7300_edac.c EDAC-I7CORE -M: Mauro Carvalho Chehab <mchehab@redhat.com> +M: Mauro Carvalho Chehab <m.chehab@samsung.com> L: linux-edac@vger.kernel.org W: bluesmoke.sourceforge.net S: Maintained @@ -3061,7 +3052,7 @@ S: Maintained F: drivers/edac/r82600_edac.c EDAC-SBRIDGE -M: Mauro Carvalho Chehab <mchehab@redhat.com> +M: Mauro Carvalho Chehab <m.chehab@samsung.com> L: linux-edac@vger.kernel.org W: bluesmoke.sourceforge.net S: Maintained @@ -3121,7 +3112,7 @@ S: Maintained F: drivers/net/ethernet/ibm/ehea/ EM28XX VIDEO4LINUX DRIVER -M: Mauro Carvalho Chehab <mchehab@redhat.com> +M: Mauro Carvalho Chehab <m.chehab@samsung.com> L: linux-media@vger.kernel.org W: http://linuxtv.org T: git git://linuxtv.org/media_tree.git @@ -5317,7 +5308,7 @@ S: Maintained F: drivers/media/radio/radio-maxiradio* MEDIA INPUT INFRASTRUCTURE (V4L/DVB) -M: Mauro Carvalho Chehab <mchehab@redhat.com> +M: Mauro Carvalho Chehab <m.chehab@samsung.com> P: LinuxTV.org Project L: linux-media@vger.kernel.org W: http://linuxtv.org @@ -7013,7 +7004,7 @@ S: Odd Fixes F: drivers/media/i2c/saa6588* SAA7134 VIDEO4LINUX DRIVER -M: Mauro Carvalho Chehab <mchehab@redhat.com> +M: Mauro Carvalho Chehab <m.chehab@samsung.com> L: linux-media@vger.kernel.org W: http://linuxtv.org T: git git://linuxtv.org/media_tree.git @@ -7058,6 +7049,15 @@ F: drivers/regulator/s5m*.c F: drivers/rtc/rtc-sec.c F: include/linux/mfd/samsung/ +SAMSUNG S5P/EXYNOS4 SOC SERIES CAMERA SUBSYSTEM DRIVERS +M: Kyungmin Park <kyungmin.park@samsung.com> +M: Sylwester Nawrocki <s.nawrocki@samsung.com> +L: linux-media@vger.kernel.org +Q: https://patchwork.linuxtv.org/project/linux-media/list/ +S: Supported +F: drivers/media/platform/exynos4-is/ +F: include/media/s5p_fimc.h + SAMSUNG S3C24XX/S3C64XX SOC SERIES CAMIF DRIVER M: Sylwester Nawrocki <sylvester.nawrocki@gmail.com> L: linux-media@vger.kernel.org @@ -7375,7 +7375,7 @@ S: Odd Fixes F: drivers/media/radio/radio-si4713.h SIANO DVB DRIVER -M: Mauro Carvalho Chehab <mchehab@redhat.com> +M: Mauro Carvalho Chehab <m.chehab@samsung.com> L: linux-media@vger.kernel.org W: http://linuxtv.org T: git git://linuxtv.org/media_tree.git @@ -8080,7 +8080,7 @@ S: Maintained F: drivers/media/i2c/tda9840* TEA5761 TUNER DRIVER -M: Mauro Carvalho Chehab <mchehab@redhat.com> +M: Mauro Carvalho Chehab <m.chehab@samsung.com> L: linux-media@vger.kernel.org W: http://linuxtv.org T: git git://linuxtv.org/media_tree.git @@ -8088,7 +8088,7 @@ S: Odd fixes F: drivers/media/tuners/tea5761.* TEA5767 TUNER DRIVER -M: Mauro Carvalho Chehab <mchehab@redhat.com> +M: Mauro Carvalho Chehab <m.chehab@samsung.com> L: linux-media@vger.kernel.org W: http://linuxtv.org T: git git://linuxtv.org/media_tree.git @@ -8327,7 +8327,7 @@ F: include/linux/shmem_fs.h F: mm/shmem.c TM6000 VIDEO4LINUX DRIVER -M: Mauro Carvalho Chehab <mchehab@redhat.com> +M: Mauro Carvalho Chehab <m.chehab@samsung.com> L: linux-media@vger.kernel.org W: http://linuxtv.org T: git git://linuxtv.org/media_tree.git @@ -9184,7 +9184,7 @@ S: Maintained F: arch/x86/kernel/cpu/mcheck/* XC2028/3028 TUNER DRIVER -M: Mauro Carvalho Chehab <mchehab@redhat.com> +M: Mauro Carvalho Chehab <m.chehab@samsung.com> L: linux-media@vger.kernel.org W: http://linuxtv.org T: git git://linuxtv.org/media_tree.git diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c index fd38c8d22e3c..afbc439f11d4 100644 --- a/arch/arm/mach-davinci/board-dm365-evm.c +++ b/arch/arm/mach-davinci/board-dm365-evm.c @@ -509,7 +509,6 @@ struct ths7303_platform_data ths7303_pdata = { .ch_1 = 3, .ch_2 = 3, .ch_3 = 3, - .init_enable = 1, }; static struct amp_config_info vpbe_amp = { diff --git a/drivers/base/dma-buf.c b/drivers/base/dma-buf.c index 08fe897c0b4c..6687ba741879 100644 --- a/drivers/base/dma-buf.c +++ b/drivers/base/dma-buf.c @@ -680,10 +680,7 @@ int dma_buf_debugfs_create_file(const char *name, d = debugfs_create_file(name, S_IRUGO, dma_buf_debugfs_dir, write, &dma_buf_debug_fops); - if (IS_ERR(d)) - return PTR_ERR(d); - - return 0; + return PTR_RET(d); } #else static inline int dma_buf_init_debugfs(void) diff --git a/drivers/media/common/saa7146/saa7146_video.c b/drivers/media/common/saa7146/saa7146_video.c index fe907f2e8f59..30779498c173 100644 --- a/drivers/media/common/saa7146/saa7146_video.c +++ b/drivers/media/common/saa7146/saa7146_video.c @@ -1,7 +1,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <media/saa7146_vv.h> -#include <media/v4l2-chip-ident.h> #include <media/v4l2-event.h> #include <media/v4l2-ctrls.h> #include <linux/module.h> @@ -988,26 +987,6 @@ static int vidioc_streamoff(struct file *file, void *__fh, enum v4l2_buf_type ty return err; } -static int vidioc_g_chip_ident(struct file *file, void *__fh, - struct v4l2_dbg_chip_ident *chip) -{ - struct saa7146_fh *fh = __fh; - struct saa7146_dev *dev = fh->dev; - - chip->ident = V4L2_IDENT_NONE; - chip->revision = 0; - if (chip->match.type == V4L2_CHIP_MATCH_HOST) { - if (v4l2_chip_match_host(&chip->match)) - chip->ident = V4L2_IDENT_SAA7146; - return 0; - } - if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER && - chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR) - return -EINVAL; - return v4l2_device_call_until_err(&dev->v4l2_dev, 0, - core, g_chip_ident, chip); -} - const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = { .vidioc_querycap = vidioc_querycap, .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, @@ -1018,7 +997,6 @@ const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = { .vidioc_g_fmt_vid_overlay = vidioc_g_fmt_vid_overlay, .vidioc_try_fmt_vid_overlay = vidioc_try_fmt_vid_overlay, .vidioc_s_fmt_vid_overlay = vidioc_s_fmt_vid_overlay, - .vidioc_g_chip_ident = vidioc_g_chip_ident, .vidioc_overlay = vidioc_overlay, .vidioc_g_fbuf = vidioc_g_fbuf, @@ -1039,7 +1017,6 @@ const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = { const struct v4l2_ioctl_ops saa7146_vbi_ioctl_ops = { .vidioc_querycap = vidioc_querycap, .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, - .vidioc_g_chip_ident = vidioc_g_chip_ident, .vidioc_reqbufs = vidioc_reqbufs, .vidioc_querybuf = vidioc_querybuf, diff --git a/drivers/media/common/siano/smscoreapi.c b/drivers/media/common/siano/smscoreapi.c index 45ac9eea4882..a142f7942a01 100644 --- a/drivers/media/common/siano/smscoreapi.c +++ b/drivers/media/common/siano/smscoreapi.c @@ -1154,7 +1154,7 @@ static int smscore_load_firmware_from_file(struct smscore_device_t *coredev, char *fw_filename = smscore_get_fw_filename(coredev, mode); if (!fw_filename) { - sms_info("mode %d not supported on this device", mode); + sms_err("mode %d not supported on this device", mode); return -ENOENT; } sms_debug("Firmware name: %s", fw_filename); @@ -1165,23 +1165,24 @@ static int smscore_load_firmware_from_file(struct smscore_device_t *coredev, rc = request_firmware(&fw, fw_filename, coredev->device); if (rc < 0) { - sms_info("failed to open \"%s\"", fw_filename); + sms_err("failed to open firmware file \"%s\"", fw_filename); return rc; } sms_info("read fw %s, buffer size=0x%zx", fw_filename, fw->size); fw_buf = kmalloc(ALIGN(fw->size, SMS_ALLOC_ALIGNMENT), GFP_KERNEL | GFP_DMA); if (!fw_buf) { - sms_info("failed to allocate firmware buffer"); - return -ENOMEM; - } - memcpy(fw_buf, fw->data, fw->size); - fw_buf_size = fw->size; + sms_err("failed to allocate firmware buffer"); + rc = -ENOMEM; + } else { + memcpy(fw_buf, fw->data, fw->size); + fw_buf_size = fw->size; - rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ? - smscore_load_firmware_family2(coredev, fw_buf, fw_buf_size) - : loadfirmware_handler(coredev->context, fw_buf, - fw_buf_size); + rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ? + smscore_load_firmware_family2(coredev, fw_buf, fw_buf_size) + : loadfirmware_handler(coredev->context, fw_buf, + fw_buf_size); + } kfree(fw_buf); release_firmware(fw); diff --git a/drivers/media/common/siano/smsdvb-main.c b/drivers/media/common/siano/smsdvb-main.c index 297f1b2f9a32..086262252230 100644 --- a/drivers/media/common/siano/smsdvb-main.c +++ b/drivers/media/common/siano/smsdvb-main.c @@ -140,6 +140,7 @@ static void smsdvb_stats_not_ready(struct dvb_frontend *fe) case DEVICE_MODE_ISDBT: case DEVICE_MODE_ISDBT_BDA: n_layers = 4; + break; default: n_layers = 1; } diff --git a/drivers/media/common/tveeprom.c b/drivers/media/common/tveeprom.c index cc1e172dfece..c7dace671a9d 100644 --- a/drivers/media/common/tveeprom.c +++ b/drivers/media/common/tveeprom.c @@ -40,7 +40,6 @@ #include <media/tuner.h> #include <media/tveeprom.h> #include <media/v4l2-common.h> -#include <media/v4l2-chip-ident.h> MODULE_DESCRIPTION("i2c Hauppauge eeprom decoder driver"); MODULE_AUTHOR("John Klar"); @@ -67,13 +66,10 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); * The Hauppauge eeprom uses an 8bit field to determine which * tuner formats the tuner supports. */ -static struct HAUPPAUGE_TUNER_FMT -{ +static const struct { int id; - char *name; -} -hauppauge_tuner_fmt[] = -{ + const char * const name; +} hauppauge_tuner_fmt[] = { { V4L2_STD_UNKNOWN, " UNKNOWN" }, { V4L2_STD_UNKNOWN, " FM" }, { V4L2_STD_B|V4L2_STD_GH, " PAL(B/G)" }, @@ -88,13 +84,10 @@ hauppauge_tuner_fmt[] = supplying this information. Note that many tuners where only used for testing and never made it to the outside world. So you will only see a subset in actual produced cards. */ -static struct HAUPPAUGE_TUNER -{ +static const struct { int id; - char *name; -} -hauppauge_tuner[] = -{ + const char * const name; +} hauppauge_tuner[] = { /* 0-9 */ { TUNER_ABSENT, "None" }, { TUNER_ABSENT, "External" }, @@ -298,69 +291,66 @@ hauppauge_tuner[] = { TUNER_ABSENT, "NXP 18272S"}, }; -/* Use V4L2_IDENT_AMBIGUOUS for those audio 'chips' that are +/* Use TVEEPROM_AUDPROC_INTERNAL for those audio 'chips' that are * internal to a video chip, i.e. not a separate audio chip. */ -static struct HAUPPAUGE_AUDIOIC -{ +static const struct { u32 id; - char *name; -} -audioIC[] = -{ + const char * const name; +} audio_ic[] = { /* 0-4 */ - { V4L2_IDENT_NONE, "None" }, - { V4L2_IDENT_UNKNOWN, "TEA6300" }, - { V4L2_IDENT_UNKNOWN, "TEA6320" }, - { V4L2_IDENT_UNKNOWN, "TDA9850" }, - { V4L2_IDENT_MSPX4XX, "MSP3400C" }, + { TVEEPROM_AUDPROC_NONE, "None" }, + { TVEEPROM_AUDPROC_OTHER, "TEA6300" }, + { TVEEPROM_AUDPROC_OTHER, "TEA6320" }, + { TVEEPROM_AUDPROC_OTHER, "TDA9850" }, + { TVEEPROM_AUDPROC_MSP, "MSP3400C" }, /* 5-9 */ - { V4L2_IDENT_MSPX4XX, "MSP3410D" }, - { V4L2_IDENT_MSPX4XX, "MSP3415" }, - { V4L2_IDENT_MSPX4XX, "MSP3430" }, - { V4L2_IDENT_MSPX4XX, "MSP3438" }, - { V4L2_IDENT_UNKNOWN, "CS5331" }, + { TVEEPROM_AUDPROC_MSP, "MSP3410D" }, + { TVEEPROM_AUDPROC_MSP, "MSP3415" }, + { TVEEPROM_AUDPROC_MSP, "MSP3430" }, + { TVEEPROM_AUDPROC_MSP, "MSP3438" }, + { TVEEPROM_AUDPROC_OTHER, "CS5331" }, /* 10-14 */ - { V4L2_IDENT_MSPX4XX, "MSP3435" }, - { V4L2_IDENT_MSPX4XX, "MSP3440" }, - { V4L2_IDENT_MSPX4XX, "MSP3445" }, - { V4L2_IDENT_MSPX4XX, "MSP3411" }, - { V4L2_IDENT_MSPX4XX, "MSP3416" }, + { TVEEPROM_AUDPROC_MSP, "MSP3435" }, + { TVEEPROM_AUDPROC_MSP, "MSP3440" }, + { TVEEPROM_AUDPROC_MSP, "MSP3445" }, + { TVEEPROM_AUDPROC_MSP, "MSP3411" }, + { TVEEPROM_AUDPROC_MSP, "MSP3416" }, /* 15-19 */ - { V4L2_IDENT_MSPX4XX, "MSP3425" }, - { V4L2_IDENT_MSPX4XX, "MSP3451" }, - { V4L2_IDENT_MSPX4XX, "MSP3418" }, - { V4L2_IDENT_UNKNOWN, "Type 0x12" }, - { V4L2_IDENT_UNKNOWN, "OKI7716" }, + { TVEEPROM_AUDPROC_MSP, "MSP3425" }, + { TVEEPROM_AUDPROC_MSP, "MSP3451" }, + { TVEEPROM_AUDPROC_MSP, "MSP3418" }, + { TVEEPROM_AUDPROC_OTHER, "Type 0x12" }, + { TVEEPROM_AUDPROC_OTHER, "OKI7716" }, /* 20-24 */ - { V4L2_IDENT_MSPX4XX, "MSP4410" }, - { V4L2_IDENT_MSPX4XX, "MSP4420" }, - { V4L2_IDENT_MSPX4XX, "MSP4440" }, - { V4L2_IDENT_MSPX4XX, "MSP4450" }, - { V4L2_IDENT_MSPX4XX, "MSP4408" }, + { TVEEPROM_AUDPROC_MSP, "MSP4410" }, + { TVEEPROM_AUDPROC_MSP, "MSP4420" }, + { TVEEPROM_AUDPROC_MSP, "MSP4440" }, + { TVEEPROM_AUDPROC_MSP, "MSP4450" }, + { TVEEPROM_AUDPROC_MSP, "MSP4408" }, /* 25-29 */ - { V4L2_IDENT_MSPX4XX, "MSP4418" }, - { V4L2_IDENT_MSPX4XX, "MSP4428" }, - { V4L2_IDENT_MSPX4XX, "MSP4448" }, - { V4L2_IDENT_MSPX4XX, "MSP4458" }, - { V4L2_IDENT_MSPX4XX, "Type 0x1d" }, + { TVEEPROM_AUDPROC_MSP, "MSP4418" }, + { TVEEPROM_AUDPROC_MSP, "MSP4428" }, + { TVEEPROM_AUDPROC_MSP, "MSP4448" }, + { TVEEPROM_AUDPROC_MSP, "MSP4458" }, + { TVEEPROM_AUDPROC_MSP, "Type 0x1d" }, /* 30-34 */ - { V4L2_IDENT_AMBIGUOUS, "CX880" }, - { V4L2_IDENT_AMBIGUOUS, "CX881" }, - { V4L2_IDENT_AMBIGUOUS, "CX883" }, - { V4L2_IDENT_AMBIGUOUS, "CX882" }, - { V4L2_IDENT_AMBIGUOUS, "CX25840" }, + { TVEEPROM_AUDPROC_INTERNAL, "CX880" }, + { TVEEPROM_AUDPROC_INTERNAL, "CX881" }, + { TVEEPROM_AUDPROC_INTERNAL, "CX883" }, + { TVEEPROM_AUDPROC_INTERNAL, "CX882" }, + { TVEEPROM_AUDPROC_INTERNAL, "CX25840" }, /* 35-39 */ - { V4L2_IDENT_AMBIGUOUS, "CX25841" }, - { V4L2_IDENT_AMBIGUOUS, "CX25842" }, - { V4L2_IDENT_AMBIGUOUS, "CX25843" }, - { V4L2_IDENT_AMBIGUOUS, "CX23418" }, - { V4L2_IDENT_AMBIGUOUS, "CX23885" }, + { TVEEPROM_AUDPROC_INTERNAL, "CX25841" }, + { TVEEPROM_AUDPROC_INTERNAL, "CX25842" }, + { TVEEPROM_AUDPROC_INTERNAL, "CX25843" }, + { TVEEPROM_AUDPROC_INTERNAL, "CX23418" }, + { TVEEPROM_AUDPROC_INTERNAL, "CX23885" }, /* 40-44 */ - { V4L2_IDENT_AMBIGUOUS, "CX23888" }, - { V4L2_IDENT_AMBIGUOUS, "SAA7131" }, - { V4L2_IDENT_AMBIGUOUS, "CX23887" }, - { V4L2_IDENT_AMBIGUOUS, "SAA7164" }, - { V4L2_IDENT_AMBIGUOUS, "AU8522" }, + { TVEEPROM_AUDPROC_INTERNAL, "CX23888" }, + { TVEEPROM_AUDPROC_INTERNAL, "SAA7131" }, + { TVEEPROM_AUDPROC_INTERNAL, "CX23887" }, + { TVEEPROM_AUDPROC_INTERNAL, "SAA7164" }, + { TVEEPROM_AUDPROC_INTERNAL, "AU8522" }, }; /* This list is supplied by Hauppauge. Thanks! */ @@ -453,11 +443,11 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, int i, j, len, done, beenhere, tag, start; int tuner1 = 0, t_format1 = 0, audioic = -1; - char *t_name1 = NULL; + const char *t_name1 = NULL; const char *t_fmt_name1[8] = { " none", "", "", "", "", "", "", "" }; int tuner2 = 0, t_format2 = 0; - char *t_name2 = NULL; + const char *t_name2 = NULL; const char *t_fmt_name2[8] = { " none", "", "", "", "", "", "", "" }; memset(tvee, 0, sizeof(*tvee)); @@ -545,10 +535,10 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, to indicate 4052 mux was removed in favor of using MSP inputs directly. */ audioic = eeprom_data[i+2] & 0x7f; - if (audioic < ARRAY_SIZE(audioIC)) - tvee->audio_processor = audioIC[audioic].id; + if (audioic < ARRAY_SIZE(audio_ic)) + tvee->audio_processor = audio_ic[audioic].id; else - tvee->audio_processor = V4L2_IDENT_UNKNOWN; + tvee->audio_processor = TVEEPROM_AUDPROC_OTHER; break; /* case 0x03: tag 'EEInfo' */ @@ -578,10 +568,10 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, to indicate 4052 mux was removed in favor of using MSP inputs directly. */ audioic = eeprom_data[i+1] & 0x7f; - if (audioic < ARRAY_SIZE(audioIC)) - tvee->audio_processor = audioIC[audioic].id; + if (audioic < ARRAY_SIZE(audio_ic)) + tvee->audio_processor = audio_ic[audioic].id; else - tvee->audio_processor = V4L2_IDENT_UNKNOWN; + tvee->audio_processor = TVEEPROM_AUDPROC_OTHER; break; @@ -726,11 +716,11 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, t_fmt_name2[6], t_fmt_name2[7], t_format2); if (audioic < 0) { tveeprom_info("audio processor is unknown (no idx)\n"); - tvee->audio_processor = V4L2_IDENT_UNKNOWN; + tvee->audio_processor = TVEEPROM_AUDPROC_OTHER; } else { - if (audioic < ARRAY_SIZE(audioIC)) + if (audioic < ARRAY_SIZE(audio_ic)) tveeprom_info("audio processor is %s (idx %d)\n", - audioIC[audioic].name, audioic); + audio_ic[audioic].name, audioic); else tveeprom_info("audio processor is unknown (idx %d)\n", audioic); diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c index a1a3a5159d71..0b4616b87195 100644 --- a/drivers/media/dvb-core/dmxdev.c +++ b/drivers/media/dvb-core/dmxdev.c @@ -377,10 +377,8 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer2, buffer2_len); } - if (ret < 0) { - dvb_ringbuffer_flush(&dmxdevfilter->buffer); + if (ret < 0) dmxdevfilter->buffer.error = ret; - } if (dmxdevfilter->params.sec.flags & DMX_ONESHOT) dmxdevfilter->state = DMXDEV_STATE_DONE; spin_unlock(&dmxdevfilter->dev->lock); @@ -416,10 +414,8 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, ret = dvb_dmxdev_buffer_write(buffer, buffer1, buffer1_len); if (ret == buffer1_len) ret = dvb_dmxdev_buffer_write(buffer, buffer2, buffer2_len); - if (ret < 0) { - dvb_ringbuffer_flush(buffer); + if (ret < 0) buffer->error = ret; - } spin_unlock(&dmxdevfilter->dev->lock); wake_up(&buffer->queue); return 0; diff --git a/drivers/media/dvb-core/dvb-usb-ids.h b/drivers/media/dvb-core/dvb-usb-ids.h index 335a8f4695b4..886da16e14f2 100644 --- a/drivers/media/dvb-core/dvb-usb-ids.h +++ b/drivers/media/dvb-core/dvb-usb-ids.h @@ -367,4 +367,6 @@ #define USB_PID_TECHNISAT_USB2_HDCI_V2 0x0002 #define USB_PID_TECHNISAT_AIRSTAR_TELESTICK_2 0x0004 #define USB_PID_TECHNISAT_USB2_DVB_S2 0x0500 +#define USB_PID_CPYTO_REDI_PC50A 0xa803 +#define USB_PID_CTVDIGDUAL_V2 0xe410 #endif diff --git a/drivers/media/dvb-frontends/au8522_decoder.c b/drivers/media/dvb-frontends/au8522_decoder.c index 2099f21e374d..23a0d05ba426 100644 --- a/drivers/media/dvb-frontends/au8522_decoder.c +++ b/drivers/media/dvb-frontends/au8522_decoder.c @@ -35,7 +35,6 @@ #include <linux/i2c.h> #include <linux/delay.h> #include <media/v4l2-common.h> -#include <media/v4l2-chip-ident.h> #include <media/v4l2-device.h> #include "au8522.h" #include "au8522_priv.h" @@ -524,13 +523,8 @@ static int au8522_s_ctrl(struct v4l2_ctrl *ctrl) static int au8522_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); struct au8522_state *state = to_state(sd); - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; reg->val = au8522_readreg(state, reg->reg & 0xffff); return 0; } @@ -538,13 +532,8 @@ static int au8522_g_register(struct v4l2_subdev *sd, static int au8522_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); struct au8522_state *state = to_state(sd); - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; au8522_writereg(state, reg->reg, reg->val & 0xff); return 0; } @@ -636,20 +625,10 @@ static int au8522_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) return 0; } -static int au8522_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - struct au8522_state *state = to_state(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, state->id, state->rev); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops au8522_core_ops = { .log_status = v4l2_ctrl_subdev_log_status, - .g_chip_ident = au8522_g_chip_ident, .reset = au8522_reset, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = au8522_g_register, diff --git a/drivers/media/dvb-frontends/dib8000.c b/drivers/media/dvb-frontends/dib8000.c index a54182dd0e91..90536147bf04 100644 --- a/drivers/media/dvb-frontends/dib8000.c +++ b/drivers/media/dvb-frontends/dib8000.c @@ -3406,7 +3406,7 @@ static int dib8000_set_frontend(struct dvb_frontend *fe) { struct dib8000_state *state = fe->demodulator_priv; struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache; - int l, i, active, time, ret, time_slave = FE_CALLBACK_TIME_NEVER; + int l, i, active, time, time_slave = FE_CALLBACK_TIME_NEVER; u8 exit_condition, index_frontend; u32 delay, callback_time; @@ -3553,7 +3553,7 @@ static int dib8000_set_frontend(struct dvb_frontend *fe) } } - return ret; + return 0; } static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat) diff --git a/drivers/media/dvb-frontends/drxk.h b/drivers/media/dvb-frontends/drxk.h index e6667189ddce..f22eb9f13ad5 100644 --- a/drivers/media/dvb-frontends/drxk.h +++ b/drivers/media/dvb-frontends/drxk.h @@ -8,7 +8,7 @@ /** * struct drxk_config - Configure the initial parameters for DRX-K * - * @adr: I2C Address of the DRX-K + * @adr: I2C address of the DRX-K * @parallel_ts: True means that the device uses parallel TS, * Serial otherwise. * @dynamic_clk: True means that the clock will be dynamically diff --git a/drivers/media/dvb-frontends/drxk_hard.c b/drivers/media/dvb-frontends/drxk_hard.c index ec24d71e153d..082014de6875 100644 --- a/drivers/media/dvb-frontends/drxk_hard.c +++ b/drivers/media/dvb-frontends/drxk_hard.c @@ -21,6 +21,8 @@ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/kernel.h> #include <linux/module.h> #include <linux/moduleparam.h> @@ -34,35 +36,36 @@ #include "dvb_frontend.h" #include "drxk.h" #include "drxk_hard.h" - -static int PowerDownDVBT(struct drxk_state *state, bool setPowerMode); -static int PowerDownQAM(struct drxk_state *state); -static int SetDVBTStandard(struct drxk_state *state, - enum OperationMode oMode); -static int SetQAMStandard(struct drxk_state *state, - enum OperationMode oMode); -static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz, - s32 tunerFreqOffset); -static int SetDVBTStandard(struct drxk_state *state, - enum OperationMode oMode); -static int DVBTStart(struct drxk_state *state); -static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz, - s32 tunerFreqOffset); -static int GetQAMLockStatus(struct drxk_state *state, u32 *pLockStatus); -static int GetDVBTLockStatus(struct drxk_state *state, u32 *pLockStatus); -static int SwitchAntennaToQAM(struct drxk_state *state); -static int SwitchAntennaToDVBT(struct drxk_state *state); - -static bool IsDVBT(struct drxk_state *state) +#include "dvb_math.h" + +static int power_down_dvbt(struct drxk_state *state, bool set_power_mode); +static int power_down_qam(struct drxk_state *state); +static int set_dvbt_standard(struct drxk_state *state, + enum operation_mode o_mode); +static int set_qam_standard(struct drxk_state *state, + enum operation_mode o_mode); +static int set_qam(struct drxk_state *state, u16 intermediate_freqk_hz, + s32 tuner_freq_offset); +static int set_dvbt_standard(struct drxk_state *state, + enum operation_mode o_mode); +static int dvbt_start(struct drxk_state *state); +static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, + s32 tuner_freq_offset); +static int get_qam_lock_status(struct drxk_state *state, u32 *p_lock_status); +static int get_dvbt_lock_status(struct drxk_state *state, u32 *p_lock_status); +static int switch_antenna_to_qam(struct drxk_state *state); +static int switch_antenna_to_dvbt(struct drxk_state *state); + +static bool is_dvbt(struct drxk_state *state) { - return state->m_OperationMode == OM_DVBT; + return state->m_operation_mode == OM_DVBT; } -static bool IsQAM(struct drxk_state *state) +static bool is_qam(struct drxk_state *state) { - return state->m_OperationMode == OM_QAM_ITU_A || - state->m_OperationMode == OM_QAM_ITU_B || - state->m_OperationMode == OM_QAM_ITU_C; + return state->m_operation_mode == OM_QAM_ITU_A || + state->m_operation_mode == OM_QAM_ITU_B || + state->m_operation_mode == OM_QAM_ITU_C; } #define NOA1ROM 0 @@ -165,7 +168,7 @@ MODULE_PARM_DESC(debug, "enable debug messages"); #define dprintk(level, fmt, arg...) do { \ if (debug >= level) \ - printk(KERN_DEBUG "drxk: %s" fmt, __func__, ## arg); \ + pr_debug(fmt, ##arg); \ } while (0) @@ -186,8 +189,10 @@ static inline u32 Frac28a(u32 a, u32 c) u32 R0 = 0; R0 = (a % c) << 4; /* 32-28 == 4 shifts possible at max */ - Q1 = a / c; /* integer part, only the 4 least significant bits - will be visible in the result */ + Q1 = a / c; /* + * integer part, only the 4 least significant + * bits will be visible in the result + */ /* division using radix 16, 7 nibbles in the result */ for (i = 0; i < 7; i++) { @@ -201,98 +206,9 @@ static inline u32 Frac28a(u32 a, u32 c) return Q1; } -static u32 Log10Times100(u32 x) +static inline u32 log10times100(u32 value) { - static const u8 scale = 15; - static const u8 indexWidth = 5; - u8 i = 0; - u32 y = 0; - u32 d = 0; - u32 k = 0; - u32 r = 0; - /* - log2lut[n] = (1<<scale) * 200 * log2(1.0 + ((1.0/(1<<INDEXWIDTH)) * n)) - 0 <= n < ((1<<INDEXWIDTH)+1) - */ - - static const u32 log2lut[] = { - 0, /* 0.000000 */ - 290941, /* 290941.300628 */ - 573196, /* 573196.476418 */ - 847269, /* 847269.179851 */ - 1113620, /* 1113620.489452 */ - 1372674, /* 1372673.576986 */ - 1624818, /* 1624817.752104 */ - 1870412, /* 1870411.981536 */ - 2109788, /* 2109787.962654 */ - 2343253, /* 2343252.817465 */ - 2571091, /* 2571091.461923 */ - 2793569, /* 2793568.696416 */ - 3010931, /* 3010931.055901 */ - 3223408, /* 3223408.452106 */ - 3431216, /* 3431215.635215 */ - 3634553, /* 3634553.498355 */ - 3833610, /* 3833610.244726 */ - 4028562, /* 4028562.434393 */ - 4219576, /* 4219575.925308 */ - 4406807, /* 4406806.721144 */ - 4590402, /* 4590401.736809 */ - 4770499, /* 4770499.491025 */ - 4947231, /* 4947230.734179 */ - 5120719, /* 5120719.018555 */ - 5291081, /* 5291081.217197 */ - 5458428, /* 5458427.996830 */ - 5622864, /* 5622864.249668 */ - 5784489, /* 5784489.488298 */ - 5943398, /* 5943398.207380 */ - 6099680, /* 6099680.215452 */ - 6253421, /* 6253420.939751 */ - 6404702, /* 6404701.706649 */ - 6553600, /* 6553600.000000 */ - }; - - - if (x == 0) - return 0; - - /* Scale x (normalize) */ - /* computing y in log(x/y) = log(x) - log(y) */ - if ((x & ((0xffffffff) << (scale + 1))) == 0) { - for (k = scale; k > 0; k--) { - if (x & (((u32) 1) << scale)) - break; - x <<= 1; - } - } else { - for (k = scale; k < 31; k++) { - if ((x & (((u32) (-1)) << (scale + 1))) == 0) - break; - x >>= 1; - } - } - /* - Now x has binary point between bit[scale] and bit[scale-1] - and 1.0 <= x < 2.0 */ - - /* correction for divison: log(x) = log(x/y)+log(y) */ - y = k * ((((u32) 1) << scale) * 200); - - /* remove integer part */ - x &= ((((u32) 1) << scale) - 1); - /* get index */ - i = (u8) (x >> (scale - indexWidth)); - /* compute delta (x - a) */ - d = x & ((((u32) 1) << (scale - indexWidth)) - 1); - /* compute log, multiplication (d* (..)) must be within range ! */ - y += log2lut[i] + - ((d * (log2lut[i + 1] - log2lut[i])) >> (scale - indexWidth)); - /* Conver to log10() */ - y /= 108853; /* (log2(10) << scale) */ - r = (y >> 1); - /* rounding */ - if (y & ((u32) 1)) - r++; - return r; + return (100L * intlog10(value)) >> 24; } /****************************************************************************/ @@ -344,15 +260,15 @@ static int i2c_write(struct drxk_state *state, u8 adr, u8 *data, int len) if (debug > 2) { int i; for (i = 0; i < len; i++) - printk(KERN_CONT " %02x", data[i]); - printk(KERN_CONT "\n"); + pr_cont(" %02x", data[i]); + pr_cont("\n"); } status = drxk_i2c_transfer(state, &msg, 1); if (status >= 0 && status != 1) status = -EIO; if (status < 0) - printk(KERN_ERR "drxk: i2c write error at addr 0x%02x\n", adr); + pr_err("i2c write error at addr 0x%02x\n", adr); return status; } @@ -371,22 +287,22 @@ static int i2c_read(struct drxk_state *state, status = drxk_i2c_transfer(state, msgs, 2); if (status != 2) { if (debug > 2) - printk(KERN_CONT ": ERROR!\n"); + pr_cont(": ERROR!\n"); if (status >= 0) status = -EIO; - printk(KERN_ERR "drxk: i2c read error at addr 0x%02x\n", adr); + pr_err("i2c read error at addr 0x%02x\n", adr); return status; } if (debug > 2) { int i; dprintk(2, ": read from"); for (i = 0; i < len; i++) - printk(KERN_CONT " %02x", msg[i]); - printk(KERN_CONT ", value = "); + pr_cont(" %02x", msg[i]); + pr_cont(", value = "); for (i = 0; i < alen; i++) - printk(KERN_CONT " %02x", answ[i]); - printk(KERN_CONT "\n"); + pr_cont(" %02x", answ[i]); + pr_cont("\n"); } return 0; } @@ -520,55 +436,55 @@ static int write32(struct drxk_state *state, u32 reg, u32 data) return write32_flags(state, reg, data, 0); } -static int write_block(struct drxk_state *state, u32 Address, - const int BlockSize, const u8 pBlock[]) +static int write_block(struct drxk_state *state, u32 address, + const int block_size, const u8 p_block[]) { - int status = 0, BlkSize = BlockSize; - u8 Flags = 0; + int status = 0, blk_size = block_size; + u8 flags = 0; if (state->single_master) - Flags |= 0xC0; - - while (BlkSize > 0) { - int Chunk = BlkSize > state->m_ChunkSize ? - state->m_ChunkSize : BlkSize; - u8 *AdrBuf = &state->Chunk[0]; - u32 AdrLength = 0; - - if (DRXDAP_FASI_LONG_FORMAT(Address) || (Flags != 0)) { - AdrBuf[0] = (((Address << 1) & 0xFF) | 0x01); - AdrBuf[1] = ((Address >> 16) & 0xFF); - AdrBuf[2] = ((Address >> 24) & 0xFF); - AdrBuf[3] = ((Address >> 7) & 0xFF); - AdrBuf[2] |= Flags; - AdrLength = 4; - if (Chunk == state->m_ChunkSize) - Chunk -= 2; + flags |= 0xC0; + + while (blk_size > 0) { + int chunk = blk_size > state->m_chunk_size ? + state->m_chunk_size : blk_size; + u8 *adr_buf = &state->chunk[0]; + u32 adr_length = 0; + + if (DRXDAP_FASI_LONG_FORMAT(address) || (flags != 0)) { + adr_buf[0] = (((address << 1) & 0xFF) | 0x01); + adr_buf[1] = ((address >> 16) & 0xFF); + adr_buf[2] = ((address >> 24) & 0xFF); + adr_buf[3] = ((address >> 7) & 0xFF); + adr_buf[2] |= flags; + adr_length = 4; + if (chunk == state->m_chunk_size) + chunk -= 2; } else { - AdrBuf[0] = ((Address << 1) & 0xFF); - AdrBuf[1] = (((Address >> 16) & 0x0F) | - ((Address >> 18) & 0xF0)); - AdrLength = 2; + adr_buf[0] = ((address << 1) & 0xFF); + adr_buf[1] = (((address >> 16) & 0x0F) | + ((address >> 18) & 0xF0)); + adr_length = 2; } - memcpy(&state->Chunk[AdrLength], pBlock, Chunk); - dprintk(2, "(0x%08x, 0x%02x)\n", Address, Flags); + memcpy(&state->chunk[adr_length], p_block, chunk); + dprintk(2, "(0x%08x, 0x%02x)\n", address, flags); if (debug > 1) { int i; - if (pBlock) - for (i = 0; i < Chunk; i++) - printk(KERN_CONT " %02x", pBlock[i]); - printk(KERN_CONT "\n"); + if (p_block) + for (i = 0; i < chunk; i++) + pr_cont(" %02x", p_block[i]); + pr_cont("\n"); } status = i2c_write(state, state->demod_address, - &state->Chunk[0], Chunk + AdrLength); + &state->chunk[0], chunk + adr_length); if (status < 0) { - printk(KERN_ERR "drxk: %s: i2c write error at addr 0x%02x\n", - __func__, Address); + pr_err("%s: i2c write error at addr 0x%02x\n", + __func__, address); break; } - pBlock += Chunk; - Address += (Chunk >> 1); - BlkSize -= Chunk; + p_block += chunk; + address += (chunk >> 1); + blk_size -= chunk; } return status; } @@ -577,11 +493,11 @@ static int write_block(struct drxk_state *state, u32 Address, #define DRXK_MAX_RETRIES_POWERUP 20 #endif -static int PowerUpDevice(struct drxk_state *state) +static int power_up_device(struct drxk_state *state) { int status; u8 data = 0; - u16 retryCount = 0; + u16 retry_count = 0; dprintk(1, "\n"); @@ -591,15 +507,15 @@ static int PowerUpDevice(struct drxk_state *state) data = 0; status = i2c_write(state, state->demod_address, &data, 1); - msleep(10); - retryCount++; + usleep_range(10000, 11000); + retry_count++; if (status < 0) continue; status = i2c_read1(state, state->demod_address, &data); } while (status < 0 && - (retryCount < DRXK_MAX_RETRIES_POWERUP)); - if (status < 0 && retryCount >= DRXK_MAX_RETRIES_POWERUP) + (retry_count < DRXK_MAX_RETRIES_POWERUP)); + if (status < 0 && retry_count >= DRXK_MAX_RETRIES_POWERUP) goto error; } @@ -615,11 +531,11 @@ static int PowerUpDevice(struct drxk_state *state) if (status < 0) goto error; - state->m_currentPowerMode = DRX_POWER_UP; + state->m_current_power_mode = DRX_POWER_UP; error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -631,106 +547,106 @@ static int init_state(struct drxk_state *state) * FIXME: most (all?) of the values bellow should be moved into * struct drxk_config, as they are probably board-specific */ - u32 ulVSBIfAgcMode = DRXK_AGC_CTRL_AUTO; - u32 ulVSBIfAgcOutputLevel = 0; - u32 ulVSBIfAgcMinLevel = 0; - u32 ulVSBIfAgcMaxLevel = 0x7FFF; - u32 ulVSBIfAgcSpeed = 3; - - u32 ulVSBRfAgcMode = DRXK_AGC_CTRL_AUTO; - u32 ulVSBRfAgcOutputLevel = 0; - u32 ulVSBRfAgcMinLevel = 0; - u32 ulVSBRfAgcMaxLevel = 0x7FFF; - u32 ulVSBRfAgcSpeed = 3; - u32 ulVSBRfAgcTop = 9500; - u32 ulVSBRfAgcCutOffCurrent = 4000; - - u32 ulATVIfAgcMode = DRXK_AGC_CTRL_AUTO; - u32 ulATVIfAgcOutputLevel = 0; - u32 ulATVIfAgcMinLevel = 0; - u32 ulATVIfAgcMaxLevel = 0; - u32 ulATVIfAgcSpeed = 3; - - u32 ulATVRfAgcMode = DRXK_AGC_CTRL_OFF; - u32 ulATVRfAgcOutputLevel = 0; - u32 ulATVRfAgcMinLevel = 0; - u32 ulATVRfAgcMaxLevel = 0; - u32 ulATVRfAgcTop = 9500; - u32 ulATVRfAgcCutOffCurrent = 4000; - u32 ulATVRfAgcSpeed = 3; + u32 ul_vsb_if_agc_mode = DRXK_AGC_CTRL_AUTO; + u32 ul_vsb_if_agc_output_level = 0; + u32 ul_vsb_if_agc_min_level = 0; + u32 ul_vsb_if_agc_max_level = 0x7FFF; + u32 ul_vsb_if_agc_speed = 3; + + u32 ul_vsb_rf_agc_mode = DRXK_AGC_CTRL_AUTO; + u32 ul_vsb_rf_agc_output_level = 0; + u32 ul_vsb_rf_agc_min_level = 0; + u32 ul_vsb_rf_agc_max_level = 0x7FFF; + u32 ul_vsb_rf_agc_speed = 3; + u32 ul_vsb_rf_agc_top = 9500; + u32 ul_vsb_rf_agc_cut_off_current = 4000; + + u32 ul_atv_if_agc_mode = DRXK_AGC_CTRL_AUTO; + u32 ul_atv_if_agc_output_level = 0; + u32 ul_atv_if_agc_min_level = 0; + u32 ul_atv_if_agc_max_level = 0; + u32 ul_atv_if_agc_speed = 3; + + u32 ul_atv_rf_agc_mode = DRXK_AGC_CTRL_OFF; + u32 ul_atv_rf_agc_output_level = 0; + u32 ul_atv_rf_agc_min_level = 0; + u32 ul_atv_rf_agc_max_level = 0; + u32 ul_atv_rf_agc_top = 9500; + u32 ul_atv_rf_agc_cut_off_current = 4000; + u32 ul_atv_rf_agc_speed = 3; u32 ulQual83 = DEFAULT_MER_83; u32 ulQual93 = DEFAULT_MER_93; - u32 ulMpegLockTimeOut = DEFAULT_DRXK_MPEG_LOCK_TIMEOUT; - u32 ulDemodLockTimeOut = DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT; + u32 ul_mpeg_lock_time_out = DEFAULT_DRXK_MPEG_LOCK_TIMEOUT; + u32 ul_demod_lock_time_out = DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT; /* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */ /* io_pad_cfg_mode output mode is drive always */ /* io_pad_cfg_drive is set to power 2 (23 mA) */ - u32 ulGPIOCfg = 0x0113; - u32 ulInvertTSClock = 0; - u32 ulTSDataStrength = DRXK_MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH; - u32 ulDVBTBitrate = 50000000; - u32 ulDVBCBitrate = DRXK_QAM_SYMBOLRATE_MAX * 8; + u32 ul_gpio_cfg = 0x0113; + u32 ul_invert_ts_clock = 0; + u32 ul_ts_data_strength = DRXK_MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH; + u32 ul_dvbt_bitrate = 50000000; + u32 ul_dvbc_bitrate = DRXK_QAM_SYMBOLRATE_MAX * 8; - u32 ulInsertRSByte = 0; + u32 ul_insert_rs_byte = 0; - u32 ulRfMirror = 1; - u32 ulPowerDown = 0; + u32 ul_rf_mirror = 1; + u32 ul_power_down = 0; dprintk(1, "\n"); - state->m_hasLNA = false; - state->m_hasDVBT = false; - state->m_hasDVBC = false; - state->m_hasATV = false; - state->m_hasOOB = false; - state->m_hasAudio = false; + state->m_has_lna = false; + state->m_has_dvbt = false; + state->m_has_dvbc = false; + state->m_has_atv = false; + state->m_has_oob = false; + state->m_has_audio = false; - if (!state->m_ChunkSize) - state->m_ChunkSize = 124; + if (!state->m_chunk_size) + state->m_chunk_size = 124; - state->m_oscClockFreq = 0; - state->m_smartAntInverted = false; - state->m_bPDownOpenBridge = false; + state->m_osc_clock_freq = 0; + state->m_smart_ant_inverted = false; + state->m_b_p_down_open_bridge = false; /* real system clock frequency in kHz */ - state->m_sysClockFreq = 151875; + state->m_sys_clock_freq = 151875; /* Timing div, 250ns/Psys */ /* Timing div, = (delay (nano seconds) * sysclk (kHz))/ 1000 */ - state->m_HICfgTimingDiv = ((state->m_sysClockFreq / 1000) * + state->m_hi_cfg_timing_div = ((state->m_sys_clock_freq / 1000) * HI_I2C_DELAY) / 1000; /* Clipping */ - if (state->m_HICfgTimingDiv > SIO_HI_RA_RAM_PAR_2_CFG_DIV__M) - state->m_HICfgTimingDiv = SIO_HI_RA_RAM_PAR_2_CFG_DIV__M; - state->m_HICfgWakeUpKey = (state->demod_address << 1); + if (state->m_hi_cfg_timing_div > SIO_HI_RA_RAM_PAR_2_CFG_DIV__M) + state->m_hi_cfg_timing_div = SIO_HI_RA_RAM_PAR_2_CFG_DIV__M; + state->m_hi_cfg_wake_up_key = (state->demod_address << 1); /* port/bridge/power down ctrl */ - state->m_HICfgCtrl = SIO_HI_RA_RAM_PAR_5_CFG_SLV0_SLAVE; + state->m_hi_cfg_ctrl = SIO_HI_RA_RAM_PAR_5_CFG_SLV0_SLAVE; - state->m_bPowerDown = (ulPowerDown != 0); + state->m_b_power_down = (ul_power_down != 0); - state->m_DRXK_A3_PATCH_CODE = false; + state->m_drxk_a3_patch_code = false; /* Init AGC and PGA parameters */ /* VSB IF */ - state->m_vsbIfAgcCfg.ctrlMode = (ulVSBIfAgcMode); - state->m_vsbIfAgcCfg.outputLevel = (ulVSBIfAgcOutputLevel); - state->m_vsbIfAgcCfg.minOutputLevel = (ulVSBIfAgcMinLevel); - state->m_vsbIfAgcCfg.maxOutputLevel = (ulVSBIfAgcMaxLevel); - state->m_vsbIfAgcCfg.speed = (ulVSBIfAgcSpeed); - state->m_vsbPgaCfg = 140; + state->m_vsb_if_agc_cfg.ctrl_mode = ul_vsb_if_agc_mode; + state->m_vsb_if_agc_cfg.output_level = ul_vsb_if_agc_output_level; + state->m_vsb_if_agc_cfg.min_output_level = ul_vsb_if_agc_min_level; + state->m_vsb_if_agc_cfg.max_output_level = ul_vsb_if_agc_max_level; + state->m_vsb_if_agc_cfg.speed = ul_vsb_if_agc_speed; + state->m_vsb_pga_cfg = 140; /* VSB RF */ - state->m_vsbRfAgcCfg.ctrlMode = (ulVSBRfAgcMode); - state->m_vsbRfAgcCfg.outputLevel = (ulVSBRfAgcOutputLevel); - state->m_vsbRfAgcCfg.minOutputLevel = (ulVSBRfAgcMinLevel); - state->m_vsbRfAgcCfg.maxOutputLevel = (ulVSBRfAgcMaxLevel); - state->m_vsbRfAgcCfg.speed = (ulVSBRfAgcSpeed); - state->m_vsbRfAgcCfg.top = (ulVSBRfAgcTop); - state->m_vsbRfAgcCfg.cutOffCurrent = (ulVSBRfAgcCutOffCurrent); - state->m_vsbPreSawCfg.reference = 0x07; - state->m_vsbPreSawCfg.usePreSaw = true; + state->m_vsb_rf_agc_cfg.ctrl_mode = ul_vsb_rf_agc_mode; + state->m_vsb_rf_agc_cfg.output_level = ul_vsb_rf_agc_output_level; + state->m_vsb_rf_agc_cfg.min_output_level = ul_vsb_rf_agc_min_level; + state->m_vsb_rf_agc_cfg.max_output_level = ul_vsb_rf_agc_max_level; + state->m_vsb_rf_agc_cfg.speed = ul_vsb_rf_agc_speed; + state->m_vsb_rf_agc_cfg.top = ul_vsb_rf_agc_top; + state->m_vsb_rf_agc_cfg.cut_off_current = ul_vsb_rf_agc_cut_off_current; + state->m_vsb_pre_saw_cfg.reference = 0x07; + state->m_vsb_pre_saw_cfg.use_pre_saw = true; state->m_Quality83percent = DEFAULT_MER_83; state->m_Quality93percent = DEFAULT_MER_93; @@ -740,127 +656,127 @@ static int init_state(struct drxk_state *state) } /* ATV IF */ - state->m_atvIfAgcCfg.ctrlMode = (ulATVIfAgcMode); - state->m_atvIfAgcCfg.outputLevel = (ulATVIfAgcOutputLevel); - state->m_atvIfAgcCfg.minOutputLevel = (ulATVIfAgcMinLevel); - state->m_atvIfAgcCfg.maxOutputLevel = (ulATVIfAgcMaxLevel); - state->m_atvIfAgcCfg.speed = (ulATVIfAgcSpeed); + state->m_atv_if_agc_cfg.ctrl_mode = ul_atv_if_agc_mode; + state->m_atv_if_agc_cfg.output_level = ul_atv_if_agc_output_level; + state->m_atv_if_agc_cfg.min_output_level = ul_atv_if_agc_min_level; + state->m_atv_if_agc_cfg.max_output_level = ul_atv_if_agc_max_level; + state->m_atv_if_agc_cfg.speed = ul_atv_if_agc_speed; /* ATV RF */ - state->m_atvRfAgcCfg.ctrlMode = (ulATVRfAgcMode); - state->m_atvRfAgcCfg.outputLevel = (ulATVRfAgcOutputLevel); - state->m_atvRfAgcCfg.minOutputLevel = (ulATVRfAgcMinLevel); - state->m_atvRfAgcCfg.maxOutputLevel = (ulATVRfAgcMaxLevel); - state->m_atvRfAgcCfg.speed = (ulATVRfAgcSpeed); - state->m_atvRfAgcCfg.top = (ulATVRfAgcTop); - state->m_atvRfAgcCfg.cutOffCurrent = (ulATVRfAgcCutOffCurrent); - state->m_atvPreSawCfg.reference = 0x04; - state->m_atvPreSawCfg.usePreSaw = true; + state->m_atv_rf_agc_cfg.ctrl_mode = ul_atv_rf_agc_mode; + state->m_atv_rf_agc_cfg.output_level = ul_atv_rf_agc_output_level; + state->m_atv_rf_agc_cfg.min_output_level = ul_atv_rf_agc_min_level; + state->m_atv_rf_agc_cfg.max_output_level = ul_atv_rf_agc_max_level; + state->m_atv_rf_agc_cfg.speed = ul_atv_rf_agc_speed; + state->m_atv_rf_agc_cfg.top = ul_atv_rf_agc_top; + state->m_atv_rf_agc_cfg.cut_off_current = ul_atv_rf_agc_cut_off_current; + state->m_atv_pre_saw_cfg.reference = 0x04; + state->m_atv_pre_saw_cfg.use_pre_saw = true; /* DVBT RF */ - state->m_dvbtRfAgcCfg.ctrlMode = DRXK_AGC_CTRL_OFF; - state->m_dvbtRfAgcCfg.outputLevel = 0; - state->m_dvbtRfAgcCfg.minOutputLevel = 0; - state->m_dvbtRfAgcCfg.maxOutputLevel = 0xFFFF; - state->m_dvbtRfAgcCfg.top = 0x2100; - state->m_dvbtRfAgcCfg.cutOffCurrent = 4000; - state->m_dvbtRfAgcCfg.speed = 1; + state->m_dvbt_rf_agc_cfg.ctrl_mode = DRXK_AGC_CTRL_OFF; + state->m_dvbt_rf_agc_cfg.output_level = 0; + state->m_dvbt_rf_agc_cfg.min_output_level = 0; + state->m_dvbt_rf_agc_cfg.max_output_level = 0xFFFF; + state->m_dvbt_rf_agc_cfg.top = 0x2100; + state->m_dvbt_rf_agc_cfg.cut_off_current = 4000; + state->m_dvbt_rf_agc_cfg.speed = 1; /* DVBT IF */ - state->m_dvbtIfAgcCfg.ctrlMode = DRXK_AGC_CTRL_AUTO; - state->m_dvbtIfAgcCfg.outputLevel = 0; - state->m_dvbtIfAgcCfg.minOutputLevel = 0; - state->m_dvbtIfAgcCfg.maxOutputLevel = 9000; - state->m_dvbtIfAgcCfg.top = 13424; - state->m_dvbtIfAgcCfg.cutOffCurrent = 0; - state->m_dvbtIfAgcCfg.speed = 3; - state->m_dvbtIfAgcCfg.FastClipCtrlDelay = 30; - state->m_dvbtIfAgcCfg.IngainTgtMax = 30000; + state->m_dvbt_if_agc_cfg.ctrl_mode = DRXK_AGC_CTRL_AUTO; + state->m_dvbt_if_agc_cfg.output_level = 0; + state->m_dvbt_if_agc_cfg.min_output_level = 0; + state->m_dvbt_if_agc_cfg.max_output_level = 9000; + state->m_dvbt_if_agc_cfg.top = 13424; + state->m_dvbt_if_agc_cfg.cut_off_current = 0; + state->m_dvbt_if_agc_cfg.speed = 3; + state->m_dvbt_if_agc_cfg.fast_clip_ctrl_delay = 30; + state->m_dvbt_if_agc_cfg.ingain_tgt_max = 30000; /* state->m_dvbtPgaCfg = 140; */ - state->m_dvbtPreSawCfg.reference = 4; - state->m_dvbtPreSawCfg.usePreSaw = false; + state->m_dvbt_pre_saw_cfg.reference = 4; + state->m_dvbt_pre_saw_cfg.use_pre_saw = false; /* QAM RF */ - state->m_qamRfAgcCfg.ctrlMode = DRXK_AGC_CTRL_OFF; - state->m_qamRfAgcCfg.outputLevel = 0; - state->m_qamRfAgcCfg.minOutputLevel = 6023; - state->m_qamRfAgcCfg.maxOutputLevel = 27000; - state->m_qamRfAgcCfg.top = 0x2380; - state->m_qamRfAgcCfg.cutOffCurrent = 4000; - state->m_qamRfAgcCfg.speed = 3; + state->m_qam_rf_agc_cfg.ctrl_mode = DRXK_AGC_CTRL_OFF; + state->m_qam_rf_agc_cfg.output_level = 0; + state->m_qam_rf_agc_cfg.min_output_level = 6023; + state->m_qam_rf_agc_cfg.max_output_level = 27000; + state->m_qam_rf_agc_cfg.top = 0x2380; + state->m_qam_rf_agc_cfg.cut_off_current = 4000; + state->m_qam_rf_agc_cfg.speed = 3; /* QAM IF */ - state->m_qamIfAgcCfg.ctrlMode = DRXK_AGC_CTRL_AUTO; - state->m_qamIfAgcCfg.outputLevel = 0; - state->m_qamIfAgcCfg.minOutputLevel = 0; - state->m_qamIfAgcCfg.maxOutputLevel = 9000; - state->m_qamIfAgcCfg.top = 0x0511; - state->m_qamIfAgcCfg.cutOffCurrent = 0; - state->m_qamIfAgcCfg.speed = 3; - state->m_qamIfAgcCfg.IngainTgtMax = 5119; - state->m_qamIfAgcCfg.FastClipCtrlDelay = 50; - - state->m_qamPgaCfg = 140; - state->m_qamPreSawCfg.reference = 4; - state->m_qamPreSawCfg.usePreSaw = false; - - state->m_OperationMode = OM_NONE; - state->m_DrxkState = DRXK_UNINITIALIZED; + state->m_qam_if_agc_cfg.ctrl_mode = DRXK_AGC_CTRL_AUTO; + state->m_qam_if_agc_cfg.output_level = 0; + state->m_qam_if_agc_cfg.min_output_level = 0; + state->m_qam_if_agc_cfg.max_output_level = 9000; + state->m_qam_if_agc_cfg.top = 0x0511; + state->m_qam_if_agc_cfg.cut_off_current = 0; + state->m_qam_if_agc_cfg.speed = 3; + state->m_qam_if_agc_cfg.ingain_tgt_max = 5119; + state->m_qam_if_agc_cfg.fast_clip_ctrl_delay = 50; + + state->m_qam_pga_cfg = 140; + state->m_qam_pre_saw_cfg.reference = 4; + state->m_qam_pre_saw_cfg.use_pre_saw = false; + + state->m_operation_mode = OM_NONE; + state->m_drxk_state = DRXK_UNINITIALIZED; /* MPEG output configuration */ - state->m_enableMPEGOutput = true; /* If TRUE; enable MPEG ouput */ - state->m_insertRSByte = false; /* If TRUE; insert RS byte */ - state->m_invertDATA = false; /* If TRUE; invert DATA signals */ - state->m_invertERR = false; /* If TRUE; invert ERR signal */ - state->m_invertSTR = false; /* If TRUE; invert STR signals */ - state->m_invertVAL = false; /* If TRUE; invert VAL signals */ - state->m_invertCLK = (ulInvertTSClock != 0); /* If TRUE; invert CLK signals */ + state->m_enable_mpeg_output = true; /* If TRUE; enable MPEG ouput */ + state->m_insert_rs_byte = false; /* If TRUE; insert RS byte */ + state->m_invert_data = false; /* If TRUE; invert DATA signals */ + state->m_invert_err = false; /* If TRUE; invert ERR signal */ + state->m_invert_str = false; /* If TRUE; invert STR signals */ + state->m_invert_val = false; /* If TRUE; invert VAL signals */ + state->m_invert_clk = (ul_invert_ts_clock != 0); /* If TRUE; invert CLK signals */ /* If TRUE; static MPEG clockrate will be used; otherwise clockrate will adapt to the bitrate of the TS */ - state->m_DVBTBitrate = ulDVBTBitrate; - state->m_DVBCBitrate = ulDVBCBitrate; + state->m_dvbt_bitrate = ul_dvbt_bitrate; + state->m_dvbc_bitrate = ul_dvbc_bitrate; - state->m_TSDataStrength = (ulTSDataStrength & 0x07); + state->m_ts_data_strength = (ul_ts_data_strength & 0x07); /* Maximum bitrate in b/s in case static clockrate is selected */ - state->m_mpegTsStaticBitrate = 19392658; - state->m_disableTEIhandling = false; + state->m_mpeg_ts_static_bitrate = 19392658; + state->m_disable_te_ihandling = false; - if (ulInsertRSByte) - state->m_insertRSByte = true; + if (ul_insert_rs_byte) + state->m_insert_rs_byte = true; - state->m_MpegLockTimeOut = DEFAULT_DRXK_MPEG_LOCK_TIMEOUT; - if (ulMpegLockTimeOut < 10000) - state->m_MpegLockTimeOut = ulMpegLockTimeOut; - state->m_DemodLockTimeOut = DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT; - if (ulDemodLockTimeOut < 10000) - state->m_DemodLockTimeOut = ulDemodLockTimeOut; + state->m_mpeg_lock_time_out = DEFAULT_DRXK_MPEG_LOCK_TIMEOUT; + if (ul_mpeg_lock_time_out < 10000) + state->m_mpeg_lock_time_out = ul_mpeg_lock_time_out; + state->m_demod_lock_time_out = DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT; + if (ul_demod_lock_time_out < 10000) + state->m_demod_lock_time_out = ul_demod_lock_time_out; /* QAM defaults */ - state->m_Constellation = DRX_CONSTELLATION_AUTO; - state->m_qamInterleaveMode = DRXK_QAM_I12_J17; - state->m_fecRsPlen = 204 * 8; /* fecRsPlen annex A */ - state->m_fecRsPrescale = 1; + state->m_constellation = DRX_CONSTELLATION_AUTO; + state->m_qam_interleave_mode = DRXK_QAM_I12_J17; + state->m_fec_rs_plen = 204 * 8; /* fecRsPlen annex A */ + state->m_fec_rs_prescale = 1; - state->m_sqiSpeed = DRXK_DVBT_SQI_SPEED_MEDIUM; - state->m_agcFastClipCtrlDelay = 0; + state->m_sqi_speed = DRXK_DVBT_SQI_SPEED_MEDIUM; + state->m_agcfast_clip_ctrl_delay = 0; - state->m_GPIOCfg = (ulGPIOCfg); + state->m_gpio_cfg = ul_gpio_cfg; - state->m_bPowerDown = false; - state->m_currentPowerMode = DRX_POWER_DOWN; + state->m_b_power_down = false; + state->m_current_power_mode = DRX_POWER_DOWN; - state->m_rfmirror = (ulRfMirror == 0); - state->m_IfAgcPol = false; + state->m_rfmirror = (ul_rf_mirror == 0); + state->m_if_agc_pol = false; return 0; } -static int DRXX_Open(struct drxk_state *state) +static int drxx_open(struct drxk_state *state) { int status = 0; u32 jtag = 0; @@ -869,7 +785,8 @@ static int DRXX_Open(struct drxk_state *state) dprintk(1, "\n"); /* stop lock indicator process */ - status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); + status = write16(state, SCU_RAM_GPIO__A, + SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); if (status < 0) goto error; /* Check device id */ @@ -888,14 +805,14 @@ static int DRXX_Open(struct drxk_state *state) status = write16(state, SIO_TOP_COMM_KEY__A, key); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } -static int GetDeviceCapabilities(struct drxk_state *state) +static int get_device_capabilities(struct drxk_state *state) { - u16 sioPdrOhwCfg = 0; - u32 sioTopJtagidLo = 0; + u16 sio_pdr_ohw_cfg = 0; + u32 sio_top_jtagid_lo = 0; int status; const char *spin = ""; @@ -903,197 +820,196 @@ static int GetDeviceCapabilities(struct drxk_state *state) /* driver 0.9.0 */ /* stop lock indicator process */ - status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); + status = write16(state, SCU_RAM_GPIO__A, + SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); if (status < 0) goto error; status = write16(state, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY); if (status < 0) goto error; - status = read16(state, SIO_PDR_OHW_CFG__A, &sioPdrOhwCfg); + status = read16(state, SIO_PDR_OHW_CFG__A, &sio_pdr_ohw_cfg); if (status < 0) goto error; status = write16(state, SIO_TOP_COMM_KEY__A, 0x0000); if (status < 0) goto error; - switch ((sioPdrOhwCfg & SIO_PDR_OHW_CFG_FREF_SEL__M)) { + switch ((sio_pdr_ohw_cfg & SIO_PDR_OHW_CFG_FREF_SEL__M)) { case 0: /* ignore (bypass ?) */ break; case 1: /* 27 MHz */ - state->m_oscClockFreq = 27000; + state->m_osc_clock_freq = 27000; break; case 2: /* 20.25 MHz */ - state->m_oscClockFreq = 20250; + state->m_osc_clock_freq = 20250; break; case 3: /* 4 MHz */ - state->m_oscClockFreq = 20250; + state->m_osc_clock_freq = 20250; break; default: - printk(KERN_ERR "drxk: Clock Frequency is unknown\n"); + pr_err("Clock Frequency is unknown\n"); return -EINVAL; } /* Determine device capabilities Based on pinning v14 */ - status = read32(state, SIO_TOP_JTAGID_LO__A, &sioTopJtagidLo); + status = read32(state, SIO_TOP_JTAGID_LO__A, &sio_top_jtagid_lo); if (status < 0) goto error; - printk(KERN_INFO "drxk: status = 0x%08x\n", sioTopJtagidLo); + pr_info("status = 0x%08x\n", sio_top_jtagid_lo); /* driver 0.9.0 */ - switch ((sioTopJtagidLo >> 29) & 0xF) { + switch ((sio_top_jtagid_lo >> 29) & 0xF) { case 0: - state->m_deviceSpin = DRXK_SPIN_A1; + state->m_device_spin = DRXK_SPIN_A1; spin = "A1"; break; case 2: - state->m_deviceSpin = DRXK_SPIN_A2; + state->m_device_spin = DRXK_SPIN_A2; spin = "A2"; break; case 3: - state->m_deviceSpin = DRXK_SPIN_A3; + state->m_device_spin = DRXK_SPIN_A3; spin = "A3"; break; default: - state->m_deviceSpin = DRXK_SPIN_UNKNOWN; + state->m_device_spin = DRXK_SPIN_UNKNOWN; status = -EINVAL; - printk(KERN_ERR "drxk: Spin %d unknown\n", - (sioTopJtagidLo >> 29) & 0xF); + pr_err("Spin %d unknown\n", (sio_top_jtagid_lo >> 29) & 0xF); goto error2; } - switch ((sioTopJtagidLo >> 12) & 0xFF) { + switch ((sio_top_jtagid_lo >> 12) & 0xFF) { case 0x13: /* typeId = DRX3913K_TYPE_ID */ - state->m_hasLNA = false; - state->m_hasOOB = false; - state->m_hasATV = false; - state->m_hasAudio = false; - state->m_hasDVBT = true; - state->m_hasDVBC = true; - state->m_hasSAWSW = true; - state->m_hasGPIO2 = false; - state->m_hasGPIO1 = false; - state->m_hasIRQN = false; + state->m_has_lna = false; + state->m_has_oob = false; + state->m_has_atv = false; + state->m_has_audio = false; + state->m_has_dvbt = true; + state->m_has_dvbc = true; + state->m_has_sawsw = true; + state->m_has_gpio2 = false; + state->m_has_gpio1 = false; + state->m_has_irqn = false; break; case 0x15: /* typeId = DRX3915K_TYPE_ID */ - state->m_hasLNA = false; - state->m_hasOOB = false; - state->m_hasATV = true; - state->m_hasAudio = false; - state->m_hasDVBT = true; - state->m_hasDVBC = false; - state->m_hasSAWSW = true; - state->m_hasGPIO2 = true; - state->m_hasGPIO1 = true; - state->m_hasIRQN = false; + state->m_has_lna = false; + state->m_has_oob = false; + state->m_has_atv = true; + state->m_has_audio = false; + state->m_has_dvbt = true; + state->m_has_dvbc = false; + state->m_has_sawsw = true; + state->m_has_gpio2 = true; + state->m_has_gpio1 = true; + state->m_has_irqn = false; break; case 0x16: /* typeId = DRX3916K_TYPE_ID */ - state->m_hasLNA = false; - state->m_hasOOB = false; - state->m_hasATV = true; - state->m_hasAudio = false; - state->m_hasDVBT = true; - state->m_hasDVBC = false; - state->m_hasSAWSW = true; - state->m_hasGPIO2 = true; - state->m_hasGPIO1 = true; - state->m_hasIRQN = false; + state->m_has_lna = false; + state->m_has_oob = false; + state->m_has_atv = true; + state->m_has_audio = false; + state->m_has_dvbt = true; + state->m_has_dvbc = false; + state->m_has_sawsw = true; + state->m_has_gpio2 = true; + state->m_has_gpio1 = true; + state->m_has_irqn = false; break; case 0x18: /* typeId = DRX3918K_TYPE_ID */ - state->m_hasLNA = false; - state->m_hasOOB = false; - state->m_hasATV = true; - state->m_hasAudio = true; - state->m_hasDVBT = true; - state->m_hasDVBC = false; - state->m_hasSAWSW = true; - state->m_hasGPIO2 = true; - state->m_hasGPIO1 = true; - state->m_hasIRQN = false; + state->m_has_lna = false; + state->m_has_oob = false; + state->m_has_atv = true; + state->m_has_audio = true; + state->m_has_dvbt = true; + state->m_has_dvbc = false; + state->m_has_sawsw = true; + state->m_has_gpio2 = true; + state->m_has_gpio1 = true; + state->m_has_irqn = false; break; case 0x21: /* typeId = DRX3921K_TYPE_ID */ - state->m_hasLNA = false; - state->m_hasOOB = false; - state->m_hasATV = true; - state->m_hasAudio = true; - state->m_hasDVBT = true; - state->m_hasDVBC = true; - state->m_hasSAWSW = true; - state->m_hasGPIO2 = true; - state->m_hasGPIO1 = true; - state->m_hasIRQN = false; + state->m_has_lna = false; + state->m_has_oob = false; + state->m_has_atv = true; + state->m_has_audio = true; + state->m_has_dvbt = true; + state->m_has_dvbc = true; + state->m_has_sawsw = true; + state->m_has_gpio2 = true; + state->m_has_gpio1 = true; + state->m_has_irqn = false; break; case 0x23: /* typeId = DRX3923K_TYPE_ID */ - state->m_hasLNA = false; - state->m_hasOOB = false; - state->m_hasATV = true; - state->m_hasAudio = true; - state->m_hasDVBT = true; - state->m_hasDVBC = true; - state->m_hasSAWSW = true; - state->m_hasGPIO2 = true; - state->m_hasGPIO1 = true; - state->m_hasIRQN = false; + state->m_has_lna = false; + state->m_has_oob = false; + state->m_has_atv = true; + state->m_has_audio = true; + state->m_has_dvbt = true; + state->m_has_dvbc = true; + state->m_has_sawsw = true; + state->m_has_gpio2 = true; + state->m_has_gpio1 = true; + state->m_has_irqn = false; break; case 0x25: /* typeId = DRX3925K_TYPE_ID */ - state->m_hasLNA = false; - state->m_hasOOB = false; - state->m_hasATV = true; - state->m_hasAudio = true; - state->m_hasDVBT = true; - state->m_hasDVBC = true; - state->m_hasSAWSW = true; - state->m_hasGPIO2 = true; - state->m_hasGPIO1 = true; - state->m_hasIRQN = false; + state->m_has_lna = false; + state->m_has_oob = false; + state->m_has_atv = true; + state->m_has_audio = true; + state->m_has_dvbt = true; + state->m_has_dvbc = true; + state->m_has_sawsw = true; + state->m_has_gpio2 = true; + state->m_has_gpio1 = true; + state->m_has_irqn = false; break; case 0x26: /* typeId = DRX3926K_TYPE_ID */ - state->m_hasLNA = false; - state->m_hasOOB = false; - state->m_hasATV = true; - state->m_hasAudio = false; - state->m_hasDVBT = true; - state->m_hasDVBC = true; - state->m_hasSAWSW = true; - state->m_hasGPIO2 = true; - state->m_hasGPIO1 = true; - state->m_hasIRQN = false; + state->m_has_lna = false; + state->m_has_oob = false; + state->m_has_atv = true; + state->m_has_audio = false; + state->m_has_dvbt = true; + state->m_has_dvbc = true; + state->m_has_sawsw = true; + state->m_has_gpio2 = true; + state->m_has_gpio1 = true; + state->m_has_irqn = false; break; default: - printk(KERN_ERR "drxk: DeviceID 0x%02x not supported\n", - ((sioTopJtagidLo >> 12) & 0xFF)); + pr_err("DeviceID 0x%02x not supported\n", + ((sio_top_jtagid_lo >> 12) & 0xFF)); status = -EINVAL; goto error2; } - printk(KERN_INFO - "drxk: detected a drx-39%02xk, spin %s, xtal %d.%03d MHz\n", - ((sioTopJtagidLo >> 12) & 0xFF), spin, - state->m_oscClockFreq / 1000, - state->m_oscClockFreq % 1000); + pr_info("detected a drx-39%02xk, spin %s, xtal %d.%03d MHz\n", + ((sio_top_jtagid_lo >> 12) & 0xFF), spin, + state->m_osc_clock_freq / 1000, + state->m_osc_clock_freq % 1000); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); error2: return status; } -static int HI_Command(struct drxk_state *state, u16 cmd, u16 *pResult) +static int hi_command(struct drxk_state *state, u16 cmd, u16 *p_result) { int status; bool powerdown_cmd; @@ -1105,37 +1021,37 @@ static int HI_Command(struct drxk_state *state, u16 cmd, u16 *pResult) if (status < 0) goto error; if (cmd == SIO_HI_RA_RAM_CMD_RESET) - msleep(1); + usleep_range(1000, 2000); powerdown_cmd = (bool) ((cmd == SIO_HI_RA_RAM_CMD_CONFIG) && - ((state->m_HICfgCtrl) & + ((state->m_hi_cfg_ctrl) & SIO_HI_RA_RAM_PAR_5_CFG_SLEEP__M) == SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ); if (powerdown_cmd == false) { /* Wait until command rdy */ - u32 retryCount = 0; - u16 waitCmd; + u32 retry_count = 0; + u16 wait_cmd; do { - msleep(1); - retryCount += 1; + usleep_range(1000, 2000); + retry_count += 1; status = read16(state, SIO_HI_RA_RAM_CMD__A, - &waitCmd); - } while ((status < 0) && (retryCount < DRXK_MAX_RETRIES) - && (waitCmd != 0)); + &wait_cmd); + } while ((status < 0) && (retry_count < DRXK_MAX_RETRIES) + && (wait_cmd != 0)); if (status < 0) goto error; - status = read16(state, SIO_HI_RA_RAM_RES__A, pResult); + status = read16(state, SIO_HI_RA_RAM_RES__A, p_result); } error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } -static int HI_CfgCommand(struct drxk_state *state) +static int hi_cfg_command(struct drxk_state *state) { int status; @@ -1143,61 +1059,68 @@ static int HI_CfgCommand(struct drxk_state *state) mutex_lock(&state->mutex); - status = write16(state, SIO_HI_RA_RAM_PAR_6__A, state->m_HICfgTimeout); + status = write16(state, SIO_HI_RA_RAM_PAR_6__A, + state->m_hi_cfg_timeout); if (status < 0) goto error; - status = write16(state, SIO_HI_RA_RAM_PAR_5__A, state->m_HICfgCtrl); + status = write16(state, SIO_HI_RA_RAM_PAR_5__A, + state->m_hi_cfg_ctrl); if (status < 0) goto error; - status = write16(state, SIO_HI_RA_RAM_PAR_4__A, state->m_HICfgWakeUpKey); + status = write16(state, SIO_HI_RA_RAM_PAR_4__A, + state->m_hi_cfg_wake_up_key); if (status < 0) goto error; - status = write16(state, SIO_HI_RA_RAM_PAR_3__A, state->m_HICfgBridgeDelay); + status = write16(state, SIO_HI_RA_RAM_PAR_3__A, + state->m_hi_cfg_bridge_delay); if (status < 0) goto error; - status = write16(state, SIO_HI_RA_RAM_PAR_2__A, state->m_HICfgTimingDiv); + status = write16(state, SIO_HI_RA_RAM_PAR_2__A, + state->m_hi_cfg_timing_div); if (status < 0) goto error; - status = write16(state, SIO_HI_RA_RAM_PAR_1__A, SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY); + status = write16(state, SIO_HI_RA_RAM_PAR_1__A, + SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY); if (status < 0) goto error; - status = HI_Command(state, SIO_HI_RA_RAM_CMD_CONFIG, 0); + status = hi_command(state, SIO_HI_RA_RAM_CMD_CONFIG, 0); if (status < 0) goto error; - state->m_HICfgCtrl &= ~SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ; + state->m_hi_cfg_ctrl &= ~SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ; error: mutex_unlock(&state->mutex); if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } -static int InitHI(struct drxk_state *state) +static int init_hi(struct drxk_state *state) { dprintk(1, "\n"); - state->m_HICfgWakeUpKey = (state->demod_address << 1); - state->m_HICfgTimeout = 0x96FF; + state->m_hi_cfg_wake_up_key = (state->demod_address << 1); + state->m_hi_cfg_timeout = 0x96FF; /* port/bridge/power down ctrl */ - state->m_HICfgCtrl = SIO_HI_RA_RAM_PAR_5_CFG_SLV0_SLAVE; + state->m_hi_cfg_ctrl = SIO_HI_RA_RAM_PAR_5_CFG_SLV0_SLAVE; - return HI_CfgCommand(state); + return hi_cfg_command(state); } -static int MPEGTSConfigurePins(struct drxk_state *state, bool mpegEnable) +static int mpegts_configure_pins(struct drxk_state *state, bool mpeg_enable) { int status = -1; - u16 sioPdrMclkCfg = 0; - u16 sioPdrMdxCfg = 0; + u16 sio_pdr_mclk_cfg = 0; + u16 sio_pdr_mdx_cfg = 0; u16 err_cfg = 0; dprintk(1, ": mpeg %s, %s mode\n", - mpegEnable ? "enable" : "disable", - state->m_enableParallel ? "parallel" : "serial"); + mpeg_enable ? "enable" : "disable", + state->m_enable_parallel ? "parallel" : "serial"); /* stop lock indicator process */ - status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); + status = write16(state, SCU_RAM_GPIO__A, + SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); if (status < 0) goto error; @@ -1206,7 +1129,7 @@ static int MPEGTSConfigurePins(struct drxk_state *state, bool mpegEnable) if (status < 0) goto error; - if (mpegEnable == false) { + if (mpeg_enable == false) { /* Set MPEG TS pads to inputmode */ status = write16(state, SIO_PDR_MSTRT_CFG__A, 0x0000); if (status < 0) @@ -1246,19 +1169,19 @@ static int MPEGTSConfigurePins(struct drxk_state *state, bool mpegEnable) goto error; } else { /* Enable MPEG output */ - sioPdrMdxCfg = - ((state->m_TSDataStrength << + sio_pdr_mdx_cfg = + ((state->m_ts_data_strength << SIO_PDR_MD0_CFG_DRIVE__B) | 0x0003); - sioPdrMclkCfg = ((state->m_TSClockkStrength << + sio_pdr_mclk_cfg = ((state->m_ts_clockk_strength << SIO_PDR_MCLK_CFG_DRIVE__B) | 0x0003); - status = write16(state, SIO_PDR_MSTRT_CFG__A, sioPdrMdxCfg); + status = write16(state, SIO_PDR_MSTRT_CFG__A, sio_pdr_mdx_cfg); if (status < 0) goto error; if (state->enable_merr_cfg) - err_cfg = sioPdrMdxCfg; + err_cfg = sio_pdr_mdx_cfg; status = write16(state, SIO_PDR_MERR_CFG__A, err_cfg); if (status < 0) @@ -1267,31 +1190,38 @@ static int MPEGTSConfigurePins(struct drxk_state *state, bool mpegEnable) if (status < 0) goto error; - if (state->m_enableParallel == true) { + if (state->m_enable_parallel == true) { /* paralel -> enable MD1 to MD7 */ - status = write16(state, SIO_PDR_MD1_CFG__A, sioPdrMdxCfg); + status = write16(state, SIO_PDR_MD1_CFG__A, + sio_pdr_mdx_cfg); if (status < 0) goto error; - status = write16(state, SIO_PDR_MD2_CFG__A, sioPdrMdxCfg); + status = write16(state, SIO_PDR_MD2_CFG__A, + sio_pdr_mdx_cfg); if (status < 0) goto error; - status = write16(state, SIO_PDR_MD3_CFG__A, sioPdrMdxCfg); + status = write16(state, SIO_PDR_MD3_CFG__A, + sio_pdr_mdx_cfg); if (status < 0) goto error; - status = write16(state, SIO_PDR_MD4_CFG__A, sioPdrMdxCfg); + status = write16(state, SIO_PDR_MD4_CFG__A, + sio_pdr_mdx_cfg); if (status < 0) goto error; - status = write16(state, SIO_PDR_MD5_CFG__A, sioPdrMdxCfg); + status = write16(state, SIO_PDR_MD5_CFG__A, + sio_pdr_mdx_cfg); if (status < 0) goto error; - status = write16(state, SIO_PDR_MD6_CFG__A, sioPdrMdxCfg); + status = write16(state, SIO_PDR_MD6_CFG__A, + sio_pdr_mdx_cfg); if (status < 0) goto error; - status = write16(state, SIO_PDR_MD7_CFG__A, sioPdrMdxCfg); + status = write16(state, SIO_PDR_MD7_CFG__A, + sio_pdr_mdx_cfg); if (status < 0) goto error; } else { - sioPdrMdxCfg = ((state->m_TSDataStrength << + sio_pdr_mdx_cfg = ((state->m_ts_data_strength << SIO_PDR_MD0_CFG_DRIVE__B) | 0x0003); /* serial -> disable MD1 to MD7 */ @@ -1317,10 +1247,10 @@ static int MPEGTSConfigurePins(struct drxk_state *state, bool mpegEnable) if (status < 0) goto error; } - status = write16(state, SIO_PDR_MCLK_CFG__A, sioPdrMclkCfg); + status = write16(state, SIO_PDR_MCLK_CFG__A, sio_pdr_mclk_cfg); if (status < 0) goto error; - status = write16(state, SIO_PDR_MD0_CFG__A, sioPdrMdxCfg); + status = write16(state, SIO_PDR_MD0_CFG__A, sio_pdr_mdx_cfg); if (status < 0) goto error; } @@ -1332,21 +1262,21 @@ static int MPEGTSConfigurePins(struct drxk_state *state, bool mpegEnable) status = write16(state, SIO_TOP_COMM_KEY__A, 0x0000); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } -static int MPEGTSDisable(struct drxk_state *state) +static int mpegts_disable(struct drxk_state *state) { dprintk(1, "\n"); - return MPEGTSConfigurePins(state, false); + return mpegts_configure_pins(state, false); } -static int BLChainCmd(struct drxk_state *state, - u16 romOffset, u16 nrOfElements, u32 timeOut) +static int bl_chain_cmd(struct drxk_state *state, + u16 rom_offset, u16 nr_of_elements, u32 time_out) { - u16 blStatus = 0; + u16 bl_status = 0; int status; unsigned long end; @@ -1355,46 +1285,46 @@ static int BLChainCmd(struct drxk_state *state, status = write16(state, SIO_BL_MODE__A, SIO_BL_MODE_CHAIN); if (status < 0) goto error; - status = write16(state, SIO_BL_CHAIN_ADDR__A, romOffset); + status = write16(state, SIO_BL_CHAIN_ADDR__A, rom_offset); if (status < 0) goto error; - status = write16(state, SIO_BL_CHAIN_LEN__A, nrOfElements); + status = write16(state, SIO_BL_CHAIN_LEN__A, nr_of_elements); if (status < 0) goto error; status = write16(state, SIO_BL_ENABLE__A, SIO_BL_ENABLE_ON); if (status < 0) goto error; - end = jiffies + msecs_to_jiffies(timeOut); + end = jiffies + msecs_to_jiffies(time_out); do { - msleep(1); - status = read16(state, SIO_BL_STATUS__A, &blStatus); + usleep_range(1000, 2000); + status = read16(state, SIO_BL_STATUS__A, &bl_status); if (status < 0) goto error; - } while ((blStatus == 0x1) && + } while ((bl_status == 0x1) && ((time_is_after_jiffies(end)))); - if (blStatus == 0x1) { - printk(KERN_ERR "drxk: SIO not ready\n"); + if (bl_status == 0x1) { + pr_err("SIO not ready\n"); status = -EINVAL; goto error2; } error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); error2: mutex_unlock(&state->mutex); return status; } -static int DownloadMicrocode(struct drxk_state *state, - const u8 pMCImage[], u32 Length) +static int download_microcode(struct drxk_state *state, + const u8 p_mc_image[], u32 length) { - const u8 *pSrc = pMCImage; - u32 Address; - u16 nBlocks; - u16 BlockSize; + const u8 *p_src = p_mc_image; + u32 address; + u16 n_blocks; + u16 block_size; u32 offset = 0; u32 i; int status = 0; @@ -1404,130 +1334,131 @@ static int DownloadMicrocode(struct drxk_state *state, /* down the drain (we don't care about MAGIC_WORD) */ #if 0 /* For future reference */ - Drain = (pSrc[0] << 8) | pSrc[1]; + drain = (p_src[0] << 8) | p_src[1]; #endif - pSrc += sizeof(u16); + p_src += sizeof(u16); offset += sizeof(u16); - nBlocks = (pSrc[0] << 8) | pSrc[1]; - pSrc += sizeof(u16); + n_blocks = (p_src[0] << 8) | p_src[1]; + p_src += sizeof(u16); offset += sizeof(u16); - for (i = 0; i < nBlocks; i += 1) { - Address = (pSrc[0] << 24) | (pSrc[1] << 16) | - (pSrc[2] << 8) | pSrc[3]; - pSrc += sizeof(u32); + for (i = 0; i < n_blocks; i += 1) { + address = (p_src[0] << 24) | (p_src[1] << 16) | + (p_src[2] << 8) | p_src[3]; + p_src += sizeof(u32); offset += sizeof(u32); - BlockSize = ((pSrc[0] << 8) | pSrc[1]) * sizeof(u16); - pSrc += sizeof(u16); + block_size = ((p_src[0] << 8) | p_src[1]) * sizeof(u16); + p_src += sizeof(u16); offset += sizeof(u16); #if 0 /* For future reference */ - Flags = (pSrc[0] << 8) | pSrc[1]; + flags = (p_src[0] << 8) | p_src[1]; #endif - pSrc += sizeof(u16); + p_src += sizeof(u16); offset += sizeof(u16); #if 0 /* For future reference */ - BlockCRC = (pSrc[0] << 8) | pSrc[1]; + block_crc = (p_src[0] << 8) | p_src[1]; #endif - pSrc += sizeof(u16); + p_src += sizeof(u16); offset += sizeof(u16); - if (offset + BlockSize > Length) { - printk(KERN_ERR "drxk: Firmware is corrupted.\n"); + if (offset + block_size > length) { + pr_err("Firmware is corrupted.\n"); return -EINVAL; } - status = write_block(state, Address, BlockSize, pSrc); + status = write_block(state, address, block_size, p_src); if (status < 0) { - printk(KERN_ERR "drxk: Error %d while loading firmware\n", status); + pr_err("Error %d while loading firmware\n", status); break; } - pSrc += BlockSize; - offset += BlockSize; + p_src += block_size; + offset += block_size; } return status; } -static int DVBTEnableOFDMTokenRing(struct drxk_state *state, bool enable) +static int dvbt_enable_ofdm_token_ring(struct drxk_state *state, bool enable) { int status; u16 data = 0; - u16 desiredCtrl = SIO_OFDM_SH_OFDM_RING_ENABLE_ON; - u16 desiredStatus = SIO_OFDM_SH_OFDM_RING_STATUS_ENABLED; + u16 desired_ctrl = SIO_OFDM_SH_OFDM_RING_ENABLE_ON; + u16 desired_status = SIO_OFDM_SH_OFDM_RING_STATUS_ENABLED; unsigned long end; dprintk(1, "\n"); if (enable == false) { - desiredCtrl = SIO_OFDM_SH_OFDM_RING_ENABLE_OFF; - desiredStatus = SIO_OFDM_SH_OFDM_RING_STATUS_DOWN; + desired_ctrl = SIO_OFDM_SH_OFDM_RING_ENABLE_OFF; + desired_status = SIO_OFDM_SH_OFDM_RING_STATUS_DOWN; } status = read16(state, SIO_OFDM_SH_OFDM_RING_STATUS__A, &data); - if (status >= 0 && data == desiredStatus) { + if (status >= 0 && data == desired_status) { /* tokenring already has correct status */ return status; } /* Disable/enable dvbt tokenring bridge */ - status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, desiredCtrl); + status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, desired_ctrl); end = jiffies + msecs_to_jiffies(DRXK_OFDM_TR_SHUTDOWN_TIMEOUT); do { status = read16(state, SIO_OFDM_SH_OFDM_RING_STATUS__A, &data); - if ((status >= 0 && data == desiredStatus) || time_is_after_jiffies(end)) + if ((status >= 0 && data == desired_status) + || time_is_after_jiffies(end)) break; - msleep(1); + usleep_range(1000, 2000); } while (1); - if (data != desiredStatus) { - printk(KERN_ERR "drxk: SIO not ready\n"); + if (data != desired_status) { + pr_err("SIO not ready\n"); return -EINVAL; } return status; } -static int MPEGTSStop(struct drxk_state *state) +static int mpegts_stop(struct drxk_state *state) { int status = 0; - u16 fecOcSncMode = 0; - u16 fecOcIprMode = 0; + u16 fec_oc_snc_mode = 0; + u16 fec_oc_ipr_mode = 0; dprintk(1, "\n"); /* Gracefull shutdown (byte boundaries) */ - status = read16(state, FEC_OC_SNC_MODE__A, &fecOcSncMode); + status = read16(state, FEC_OC_SNC_MODE__A, &fec_oc_snc_mode); if (status < 0) goto error; - fecOcSncMode |= FEC_OC_SNC_MODE_SHUTDOWN__M; - status = write16(state, FEC_OC_SNC_MODE__A, fecOcSncMode); + fec_oc_snc_mode |= FEC_OC_SNC_MODE_SHUTDOWN__M; + status = write16(state, FEC_OC_SNC_MODE__A, fec_oc_snc_mode); if (status < 0) goto error; /* Suppress MCLK during absence of data */ - status = read16(state, FEC_OC_IPR_MODE__A, &fecOcIprMode); + status = read16(state, FEC_OC_IPR_MODE__A, &fec_oc_ipr_mode); if (status < 0) goto error; - fecOcIprMode |= FEC_OC_IPR_MODE_MCLK_DIS_DAT_ABS__M; - status = write16(state, FEC_OC_IPR_MODE__A, fecOcIprMode); + fec_oc_ipr_mode |= FEC_OC_IPR_MODE_MCLK_DIS_DAT_ABS__M; + status = write16(state, FEC_OC_IPR_MODE__A, fec_oc_ipr_mode); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } static int scu_command(struct drxk_state *state, - u16 cmd, u8 parameterLen, - u16 *parameter, u8 resultLen, u16 *result) + u16 cmd, u8 parameter_len, + u16 *parameter, u8 result_len, u16 *result) { #if (SCU_RAM_PARAM_0__A - SCU_RAM_PARAM_15__A) != 15 #error DRXK register mapping no longer compatible with this routine! #endif - u16 curCmd = 0; + u16 cur_cmd = 0; int status = -EINVAL; unsigned long end; u8 buffer[34]; @@ -1537,9 +1468,9 @@ static int scu_command(struct drxk_state *state, dprintk(1, "\n"); - if ((cmd == 0) || ((parameterLen > 0) && (parameter == NULL)) || - ((resultLen > 0) && (result == NULL))) { - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + if ((cmd == 0) || ((parameter_len > 0) && (parameter == NULL)) || + ((result_len > 0) && (result == NULL))) { + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -1547,7 +1478,7 @@ static int scu_command(struct drxk_state *state, /* assume that the command register is ready since it is checked afterwards */ - for (ii = parameterLen - 1; ii >= 0; ii -= 1) { + for (ii = parameter_len - 1; ii >= 0; ii -= 1) { buffer[cnt++] = (parameter[ii] & 0xFF); buffer[cnt++] = ((parameter[ii] >> 8) & 0xFF); } @@ -1555,27 +1486,28 @@ static int scu_command(struct drxk_state *state, buffer[cnt++] = ((cmd >> 8) & 0xFF); write_block(state, SCU_RAM_PARAM_0__A - - (parameterLen - 1), cnt, buffer); + (parameter_len - 1), cnt, buffer); /* Wait until SCU has processed command */ end = jiffies + msecs_to_jiffies(DRXK_MAX_WAITTIME); do { - msleep(1); - status = read16(state, SCU_RAM_COMMAND__A, &curCmd); + usleep_range(1000, 2000); + status = read16(state, SCU_RAM_COMMAND__A, &cur_cmd); if (status < 0) goto error; - } while (!(curCmd == DRX_SCU_READY) && (time_is_after_jiffies(end))); - if (curCmd != DRX_SCU_READY) { - printk(KERN_ERR "drxk: SCU not ready\n"); + } while (!(cur_cmd == DRX_SCU_READY) && (time_is_after_jiffies(end))); + if (cur_cmd != DRX_SCU_READY) { + pr_err("SCU not ready\n"); status = -EIO; goto error2; } /* read results */ - if ((resultLen > 0) && (result != NULL)) { + if ((result_len > 0) && (result != NULL)) { s16 err; int ii; - for (ii = resultLen - 1; ii >= 0; ii -= 1) { - status = read16(state, SCU_RAM_PARAM_0__A - ii, &result[ii]); + for (ii = result_len - 1; ii >= 0; ii -= 1) { + status = read16(state, SCU_RAM_PARAM_0__A - ii, + &result[ii]); if (status < 0) goto error; } @@ -1603,7 +1535,7 @@ static int scu_command(struct drxk_state *state, sprintf(errname, "ERROR: %d\n", err); p = errname; } - printk(KERN_ERR "drxk: %s while sending cmd 0x%04x with params:", p, cmd); + pr_err("%s while sending cmd 0x%04x with params:", p, cmd); print_hex_dump_bytes("drxk: ", DUMP_PREFIX_NONE, buffer, cnt); status = -EINVAL; goto error2; @@ -1611,13 +1543,13 @@ static int scu_command(struct drxk_state *state, error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); error2: mutex_unlock(&state->mutex); return status; } -static int SetIqmAf(struct drxk_state *state, bool active) +static int set_iqm_af(struct drxk_state *state, bool active) { u16 data = 0; int status; @@ -1647,14 +1579,14 @@ static int SetIqmAf(struct drxk_state *state, bool active) error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } -static int CtrlPowerMode(struct drxk_state *state, enum DRXPowerMode *mode) +static int ctrl_power_mode(struct drxk_state *state, enum drx_power_mode *mode) { int status = 0; - u16 sioCcPwdMode = 0; + u16 sio_cc_pwd_mode = 0; dprintk(1, "\n"); @@ -1664,19 +1596,19 @@ static int CtrlPowerMode(struct drxk_state *state, enum DRXPowerMode *mode) switch (*mode) { case DRX_POWER_UP: - sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_NONE; + sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_NONE; break; case DRXK_POWER_DOWN_OFDM: - sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_OFDM; + sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_OFDM; break; case DRXK_POWER_DOWN_CORE: - sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_CLOCK; + sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_CLOCK; break; case DRXK_POWER_DOWN_PLL: - sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_PLL; + sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_PLL; break; case DRX_POWER_DOWN: - sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_OSC; + sio_cc_pwd_mode = SIO_CC_PWD_MODE_LEVEL_OSC; break; default: /* Unknow sleep mode */ @@ -1684,15 +1616,15 @@ static int CtrlPowerMode(struct drxk_state *state, enum DRXPowerMode *mode) } /* If already in requested power mode, do nothing */ - if (state->m_currentPowerMode == *mode) + if (state->m_current_power_mode == *mode) return 0; /* For next steps make sure to start from DRX_POWER_UP mode */ - if (state->m_currentPowerMode != DRX_POWER_UP) { - status = PowerUpDevice(state); + if (state->m_current_power_mode != DRX_POWER_UP) { + status = power_up_device(state); if (status < 0) goto error; - status = DVBTEnableOFDMTokenRing(state, true); + status = dvbt_enable_ofdm_token_ring(state, true); if (status < 0) goto error; } @@ -1709,31 +1641,31 @@ static int CtrlPowerMode(struct drxk_state *state, enum DRXPowerMode *mode) /* Power down device */ /* stop all comm_exec */ /* Stop and power down previous standard */ - switch (state->m_OperationMode) { + switch (state->m_operation_mode) { case OM_DVBT: - status = MPEGTSStop(state); + status = mpegts_stop(state); if (status < 0) goto error; - status = PowerDownDVBT(state, false); + status = power_down_dvbt(state, false); if (status < 0) goto error; break; case OM_QAM_ITU_A: case OM_QAM_ITU_C: - status = MPEGTSStop(state); + status = mpegts_stop(state); if (status < 0) goto error; - status = PowerDownQAM(state); + status = power_down_qam(state); if (status < 0) goto error; break; default: break; } - status = DVBTEnableOFDMTokenRing(state, false); + status = dvbt_enable_ofdm_token_ring(state, false); if (status < 0) goto error; - status = write16(state, SIO_CC_PWD_MODE__A, sioCcPwdMode); + status = write16(state, SIO_CC_PWD_MODE__A, sio_cc_pwd_mode); if (status < 0) goto error; status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY); @@ -1741,26 +1673,26 @@ static int CtrlPowerMode(struct drxk_state *state, enum DRXPowerMode *mode) goto error; if (*mode != DRXK_POWER_DOWN_OFDM) { - state->m_HICfgCtrl |= + state->m_hi_cfg_ctrl |= SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ; - status = HI_CfgCommand(state); + status = hi_cfg_command(state); if (status < 0) goto error; } } - state->m_currentPowerMode = *mode; + state->m_current_power_mode = *mode; error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } -static int PowerDownDVBT(struct drxk_state *state, bool setPowerMode) +static int power_down_dvbt(struct drxk_state *state, bool set_power_mode) { - enum DRXPowerMode powerMode = DRXK_POWER_DOWN_OFDM; - u16 cmdResult = 0; + enum drx_power_mode power_mode = DRXK_POWER_DOWN_OFDM; + u16 cmd_result = 0; u16 data = 0; int status; @@ -1771,11 +1703,17 @@ static int PowerDownDVBT(struct drxk_state *state, bool setPowerMode) goto error; if (data == SCU_COMM_EXEC_ACTIVE) { /* Send OFDM stop command */ - status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_STOP, 0, NULL, 1, &cmdResult); + status = scu_command(state, + SCU_RAM_COMMAND_STANDARD_OFDM + | SCU_RAM_COMMAND_CMD_DEMOD_STOP, + 0, NULL, 1, &cmd_result); if (status < 0) goto error; /* Send OFDM reset command */ - status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_RESET, 0, NULL, 1, &cmdResult); + status = scu_command(state, + SCU_RAM_COMMAND_STANDARD_OFDM + | SCU_RAM_COMMAND_CMD_DEMOD_RESET, + 0, NULL, 1, &cmd_result); if (status < 0) goto error; } @@ -1792,24 +1730,24 @@ static int PowerDownDVBT(struct drxk_state *state, bool setPowerMode) goto error; /* powerdown AFE */ - status = SetIqmAf(state, false); + status = set_iqm_af(state, false); if (status < 0) goto error; /* powerdown to OFDM mode */ - if (setPowerMode) { - status = CtrlPowerMode(state, &powerMode); + if (set_power_mode) { + status = ctrl_power_mode(state, &power_mode); if (status < 0) goto error; } error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } -static int SetOperationMode(struct drxk_state *state, - enum OperationMode oMode) +static int setoperation_mode(struct drxk_state *state, + enum operation_mode o_mode) { int status = 0; @@ -1821,36 +1759,37 @@ static int SetOperationMode(struct drxk_state *state, */ /* disable HW lock indicator */ - status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); + status = write16(state, SCU_RAM_GPIO__A, + SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); if (status < 0) goto error; /* Device is already at the required mode */ - if (state->m_OperationMode == oMode) + if (state->m_operation_mode == o_mode) return 0; - switch (state->m_OperationMode) { + switch (state->m_operation_mode) { /* OM_NONE was added for start up */ case OM_NONE: break; case OM_DVBT: - status = MPEGTSStop(state); + status = mpegts_stop(state); if (status < 0) goto error; - status = PowerDownDVBT(state, true); + status = power_down_dvbt(state, true); if (status < 0) goto error; - state->m_OperationMode = OM_NONE; + state->m_operation_mode = OM_NONE; break; case OM_QAM_ITU_A: /* fallthrough */ case OM_QAM_ITU_C: - status = MPEGTSStop(state); + status = mpegts_stop(state); if (status < 0) goto error; - status = PowerDownQAM(state); + status = power_down_qam(state); if (status < 0) goto error; - state->m_OperationMode = OM_NONE; + state->m_operation_mode = OM_NONE; break; case OM_QAM_ITU_B: default: @@ -1861,20 +1800,20 @@ static int SetOperationMode(struct drxk_state *state, /* Power up new standard */ - switch (oMode) { + switch (o_mode) { case OM_DVBT: dprintk(1, ": DVB-T\n"); - state->m_OperationMode = oMode; - status = SetDVBTStandard(state, oMode); + state->m_operation_mode = o_mode; + status = set_dvbt_standard(state, o_mode); if (status < 0) goto error; break; case OM_QAM_ITU_A: /* fallthrough */ case OM_QAM_ITU_C: dprintk(1, ": DVB-C Annex %c\n", - (state->m_OperationMode == OM_QAM_ITU_A) ? 'A' : 'C'); - state->m_OperationMode = oMode; - status = SetQAMStandard(state, oMode); + (state->m_operation_mode == OM_QAM_ITU_A) ? 'A' : 'C'); + state->m_operation_mode = o_mode; + status = set_qam_standard(state, o_mode); if (status < 0) goto error; break; @@ -1884,121 +1823,121 @@ static int SetOperationMode(struct drxk_state *state, } error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } -static int Start(struct drxk_state *state, s32 offsetFreq, - s32 IntermediateFrequency) +static int start(struct drxk_state *state, s32 offset_freq, + s32 intermediate_frequency) { int status = -EINVAL; - u16 IFreqkHz; - s32 OffsetkHz = offsetFreq / 1000; + u16 i_freqk_hz; + s32 offsetk_hz = offset_freq / 1000; dprintk(1, "\n"); - if (state->m_DrxkState != DRXK_STOPPED && - state->m_DrxkState != DRXK_DTV_STARTED) + if (state->m_drxk_state != DRXK_STOPPED && + state->m_drxk_state != DRXK_DTV_STARTED) goto error; - state->m_bMirrorFreqSpect = (state->props.inversion == INVERSION_ON); + state->m_b_mirror_freq_spect = (state->props.inversion == INVERSION_ON); - if (IntermediateFrequency < 0) { - state->m_bMirrorFreqSpect = !state->m_bMirrorFreqSpect; - IntermediateFrequency = -IntermediateFrequency; + if (intermediate_frequency < 0) { + state->m_b_mirror_freq_spect = !state->m_b_mirror_freq_spect; + intermediate_frequency = -intermediate_frequency; } - switch (state->m_OperationMode) { + switch (state->m_operation_mode) { case OM_QAM_ITU_A: case OM_QAM_ITU_C: - IFreqkHz = (IntermediateFrequency / 1000); - status = SetQAM(state, IFreqkHz, OffsetkHz); + i_freqk_hz = (intermediate_frequency / 1000); + status = set_qam(state, i_freqk_hz, offsetk_hz); if (status < 0) goto error; - state->m_DrxkState = DRXK_DTV_STARTED; + state->m_drxk_state = DRXK_DTV_STARTED; break; case OM_DVBT: - IFreqkHz = (IntermediateFrequency / 1000); - status = MPEGTSStop(state); + i_freqk_hz = (intermediate_frequency / 1000); + status = mpegts_stop(state); if (status < 0) goto error; - status = SetDVBT(state, IFreqkHz, OffsetkHz); + status = set_dvbt(state, i_freqk_hz, offsetk_hz); if (status < 0) goto error; - status = DVBTStart(state); + status = dvbt_start(state); if (status < 0) goto error; - state->m_DrxkState = DRXK_DTV_STARTED; + state->m_drxk_state = DRXK_DTV_STARTED; break; default: break; } error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } -static int ShutDown(struct drxk_state *state) +static int shut_down(struct drxk_state *state) { dprintk(1, "\n"); - MPEGTSStop(state); + mpegts_stop(state); return 0; } -static int GetLockStatus(struct drxk_state *state, u32 *pLockStatus) +static int get_lock_status(struct drxk_state *state, u32 *p_lock_status) { int status = -EINVAL; dprintk(1, "\n"); - if (pLockStatus == NULL) + if (p_lock_status == NULL) goto error; - *pLockStatus = NOT_LOCKED; + *p_lock_status = NOT_LOCKED; /* define the SCU command code */ - switch (state->m_OperationMode) { + switch (state->m_operation_mode) { case OM_QAM_ITU_A: case OM_QAM_ITU_B: case OM_QAM_ITU_C: - status = GetQAMLockStatus(state, pLockStatus); + status = get_qam_lock_status(state, p_lock_status); break; case OM_DVBT: - status = GetDVBTLockStatus(state, pLockStatus); + status = get_dvbt_lock_status(state, p_lock_status); break; default: break; } error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } -static int MPEGTSStart(struct drxk_state *state) +static int mpegts_start(struct drxk_state *state) { int status; - u16 fecOcSncMode = 0; + u16 fec_oc_snc_mode = 0; /* Allow OC to sync again */ - status = read16(state, FEC_OC_SNC_MODE__A, &fecOcSncMode); + status = read16(state, FEC_OC_SNC_MODE__A, &fec_oc_snc_mode); if (status < 0) goto error; - fecOcSncMode &= ~FEC_OC_SNC_MODE_SHUTDOWN__M; - status = write16(state, FEC_OC_SNC_MODE__A, fecOcSncMode); + fec_oc_snc_mode &= ~FEC_OC_SNC_MODE_SHUTDOWN__M; + status = write16(state, FEC_OC_SNC_MODE__A, fec_oc_snc_mode); if (status < 0) goto error; status = write16(state, FEC_OC_SNC_UNLOCK__A, 1); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } -static int MPEGTSDtoInit(struct drxk_state *state) +static int mpegts_dto_init(struct drxk_state *state) { int status; @@ -2040,68 +1979,68 @@ static int MPEGTSDtoInit(struct drxk_state *state) status = write16(state, FEC_OC_SNC_HWM__A, 12); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } -static int MPEGTSDtoSetup(struct drxk_state *state, - enum OperationMode oMode) +static int mpegts_dto_setup(struct drxk_state *state, + enum operation_mode o_mode) { int status; - u16 fecOcRegMode = 0; /* FEC_OC_MODE register value */ - u16 fecOcRegIprMode = 0; /* FEC_OC_IPR_MODE register value */ - u16 fecOcDtoMode = 0; /* FEC_OC_IPR_INVERT register value */ - u16 fecOcFctMode = 0; /* FEC_OC_IPR_INVERT register value */ - u16 fecOcDtoPeriod = 2; /* FEC_OC_IPR_INVERT register value */ - u16 fecOcDtoBurstLen = 188; /* FEC_OC_IPR_INVERT register value */ - u32 fecOcRcnCtlRate = 0; /* FEC_OC_IPR_INVERT register value */ - u16 fecOcTmdMode = 0; - u16 fecOcTmdIntUpdRate = 0; - u32 maxBitRate = 0; - bool staticCLK = false; + u16 fec_oc_reg_mode = 0; /* FEC_OC_MODE register value */ + u16 fec_oc_reg_ipr_mode = 0; /* FEC_OC_IPR_MODE register value */ + u16 fec_oc_dto_mode = 0; /* FEC_OC_IPR_INVERT register value */ + u16 fec_oc_fct_mode = 0; /* FEC_OC_IPR_INVERT register value */ + u16 fec_oc_dto_period = 2; /* FEC_OC_IPR_INVERT register value */ + u16 fec_oc_dto_burst_len = 188; /* FEC_OC_IPR_INVERT register value */ + u32 fec_oc_rcn_ctl_rate = 0; /* FEC_OC_IPR_INVERT register value */ + u16 fec_oc_tmd_mode = 0; + u16 fec_oc_tmd_int_upd_rate = 0; + u32 max_bit_rate = 0; + bool static_clk = false; dprintk(1, "\n"); /* Check insertion of the Reed-Solomon parity bytes */ - status = read16(state, FEC_OC_MODE__A, &fecOcRegMode); + status = read16(state, FEC_OC_MODE__A, &fec_oc_reg_mode); if (status < 0) goto error; - status = read16(state, FEC_OC_IPR_MODE__A, &fecOcRegIprMode); + status = read16(state, FEC_OC_IPR_MODE__A, &fec_oc_reg_ipr_mode); if (status < 0) goto error; - fecOcRegMode &= (~FEC_OC_MODE_PARITY__M); - fecOcRegIprMode &= (~FEC_OC_IPR_MODE_MVAL_DIS_PAR__M); - if (state->m_insertRSByte == true) { + fec_oc_reg_mode &= (~FEC_OC_MODE_PARITY__M); + fec_oc_reg_ipr_mode &= (~FEC_OC_IPR_MODE_MVAL_DIS_PAR__M); + if (state->m_insert_rs_byte == true) { /* enable parity symbol forward */ - fecOcRegMode |= FEC_OC_MODE_PARITY__M; + fec_oc_reg_mode |= FEC_OC_MODE_PARITY__M; /* MVAL disable during parity bytes */ - fecOcRegIprMode |= FEC_OC_IPR_MODE_MVAL_DIS_PAR__M; + fec_oc_reg_ipr_mode |= FEC_OC_IPR_MODE_MVAL_DIS_PAR__M; /* TS burst length to 204 */ - fecOcDtoBurstLen = 204; + fec_oc_dto_burst_len = 204; } /* Check serial or parrallel output */ - fecOcRegIprMode &= (~(FEC_OC_IPR_MODE_SERIAL__M)); - if (state->m_enableParallel == false) { + fec_oc_reg_ipr_mode &= (~(FEC_OC_IPR_MODE_SERIAL__M)); + if (state->m_enable_parallel == false) { /* MPEG data output is serial -> set ipr_mode[0] */ - fecOcRegIprMode |= FEC_OC_IPR_MODE_SERIAL__M; + fec_oc_reg_ipr_mode |= FEC_OC_IPR_MODE_SERIAL__M; } - switch (oMode) { + switch (o_mode) { case OM_DVBT: - maxBitRate = state->m_DVBTBitrate; - fecOcTmdMode = 3; - fecOcRcnCtlRate = 0xC00000; - staticCLK = state->m_DVBTStaticCLK; + max_bit_rate = state->m_dvbt_bitrate; + fec_oc_tmd_mode = 3; + fec_oc_rcn_ctl_rate = 0xC00000; + static_clk = state->m_dvbt_static_clk; break; case OM_QAM_ITU_A: /* fallthrough */ case OM_QAM_ITU_C: - fecOcTmdMode = 0x0004; - fecOcRcnCtlRate = 0xD2B4EE; /* good for >63 Mb/s */ - maxBitRate = state->m_DVBCBitrate; - staticCLK = state->m_DVBCStaticCLK; + fec_oc_tmd_mode = 0x0004; + fec_oc_rcn_ctl_rate = 0xD2B4EE; /* good for >63 Mb/s */ + max_bit_rate = state->m_dvbc_bitrate; + static_clk = state->m_dvbc_static_clk; break; default: status = -EINVAL; @@ -2110,83 +2049,84 @@ static int MPEGTSDtoSetup(struct drxk_state *state, goto error; /* Configure DTO's */ - if (staticCLK) { - u32 bitRate = 0; + if (static_clk) { + u32 bit_rate = 0; /* Rational DTO for MCLK source (static MCLK rate), Dynamic DTO for optimal grouping (avoid intra-packet gaps), DTO offset enable to sync TS burst with MSTRT */ - fecOcDtoMode = (FEC_OC_DTO_MODE_DYNAMIC__M | + fec_oc_dto_mode = (FEC_OC_DTO_MODE_DYNAMIC__M | FEC_OC_DTO_MODE_OFFSET_ENABLE__M); - fecOcFctMode = (FEC_OC_FCT_MODE_RAT_ENA__M | + fec_oc_fct_mode = (FEC_OC_FCT_MODE_RAT_ENA__M | FEC_OC_FCT_MODE_VIRT_ENA__M); /* Check user defined bitrate */ - bitRate = maxBitRate; - if (bitRate > 75900000UL) { /* max is 75.9 Mb/s */ - bitRate = 75900000UL; + bit_rate = max_bit_rate; + if (bit_rate > 75900000UL) { /* max is 75.9 Mb/s */ + bit_rate = 75900000UL; } /* Rational DTO period: dto_period = (Fsys / bitrate) - 2 - Result should be floored, + result should be floored, to make sure >= requested bitrate */ - fecOcDtoPeriod = (u16) (((state->m_sysClockFreq) - * 1000) / bitRate); - if (fecOcDtoPeriod <= 2) - fecOcDtoPeriod = 0; + fec_oc_dto_period = (u16) (((state->m_sys_clock_freq) + * 1000) / bit_rate); + if (fec_oc_dto_period <= 2) + fec_oc_dto_period = 0; else - fecOcDtoPeriod -= 2; - fecOcTmdIntUpdRate = 8; + fec_oc_dto_period -= 2; + fec_oc_tmd_int_upd_rate = 8; } else { - /* (commonAttr->staticCLK == false) => dynamic mode */ - fecOcDtoMode = FEC_OC_DTO_MODE_DYNAMIC__M; - fecOcFctMode = FEC_OC_FCT_MODE__PRE; - fecOcTmdIntUpdRate = 5; + /* (commonAttr->static_clk == false) => dynamic mode */ + fec_oc_dto_mode = FEC_OC_DTO_MODE_DYNAMIC__M; + fec_oc_fct_mode = FEC_OC_FCT_MODE__PRE; + fec_oc_tmd_int_upd_rate = 5; } /* Write appropriate registers with requested configuration */ - status = write16(state, FEC_OC_DTO_BURST_LEN__A, fecOcDtoBurstLen); + status = write16(state, FEC_OC_DTO_BURST_LEN__A, fec_oc_dto_burst_len); if (status < 0) goto error; - status = write16(state, FEC_OC_DTO_PERIOD__A, fecOcDtoPeriod); + status = write16(state, FEC_OC_DTO_PERIOD__A, fec_oc_dto_period); if (status < 0) goto error; - status = write16(state, FEC_OC_DTO_MODE__A, fecOcDtoMode); + status = write16(state, FEC_OC_DTO_MODE__A, fec_oc_dto_mode); if (status < 0) goto error; - status = write16(state, FEC_OC_FCT_MODE__A, fecOcFctMode); + status = write16(state, FEC_OC_FCT_MODE__A, fec_oc_fct_mode); if (status < 0) goto error; - status = write16(state, FEC_OC_MODE__A, fecOcRegMode); + status = write16(state, FEC_OC_MODE__A, fec_oc_reg_mode); if (status < 0) goto error; - status = write16(state, FEC_OC_IPR_MODE__A, fecOcRegIprMode); + status = write16(state, FEC_OC_IPR_MODE__A, fec_oc_reg_ipr_mode); if (status < 0) goto error; /* Rate integration settings */ - status = write32(state, FEC_OC_RCN_CTL_RATE_LO__A, fecOcRcnCtlRate); + status = write32(state, FEC_OC_RCN_CTL_RATE_LO__A, fec_oc_rcn_ctl_rate); if (status < 0) goto error; - status = write16(state, FEC_OC_TMD_INT_UPD_RATE__A, fecOcTmdIntUpdRate); + status = write16(state, FEC_OC_TMD_INT_UPD_RATE__A, + fec_oc_tmd_int_upd_rate); if (status < 0) goto error; - status = write16(state, FEC_OC_TMD_MODE__A, fecOcTmdMode); + status = write16(state, FEC_OC_TMD_MODE__A, fec_oc_tmd_mode); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } -static int MPEGTSConfigurePolarity(struct drxk_state *state) +static int mpegts_configure_polarity(struct drxk_state *state) { - u16 fecOcRegIprInvert = 0; + u16 fec_oc_reg_ipr_invert = 0; /* Data mask for the output data byte */ - u16 InvertDataMask = + u16 invert_data_mask = FEC_OC_IPR_INVERT_MD7__M | FEC_OC_IPR_INVERT_MD6__M | FEC_OC_IPR_INVERT_MD5__M | FEC_OC_IPR_INVERT_MD4__M | FEC_OC_IPR_INVERT_MD3__M | FEC_OC_IPR_INVERT_MD2__M | @@ -2195,40 +2135,40 @@ static int MPEGTSConfigurePolarity(struct drxk_state *state) dprintk(1, "\n"); /* Control selective inversion of output bits */ - fecOcRegIprInvert &= (~(InvertDataMask)); - if (state->m_invertDATA == true) - fecOcRegIprInvert |= InvertDataMask; - fecOcRegIprInvert &= (~(FEC_OC_IPR_INVERT_MERR__M)); - if (state->m_invertERR == true) - fecOcRegIprInvert |= FEC_OC_IPR_INVERT_MERR__M; - fecOcRegIprInvert &= (~(FEC_OC_IPR_INVERT_MSTRT__M)); - if (state->m_invertSTR == true) - fecOcRegIprInvert |= FEC_OC_IPR_INVERT_MSTRT__M; - fecOcRegIprInvert &= (~(FEC_OC_IPR_INVERT_MVAL__M)); - if (state->m_invertVAL == true) - fecOcRegIprInvert |= FEC_OC_IPR_INVERT_MVAL__M; - fecOcRegIprInvert &= (~(FEC_OC_IPR_INVERT_MCLK__M)); - if (state->m_invertCLK == true) - fecOcRegIprInvert |= FEC_OC_IPR_INVERT_MCLK__M; - - return write16(state, FEC_OC_IPR_INVERT__A, fecOcRegIprInvert); + fec_oc_reg_ipr_invert &= (~(invert_data_mask)); + if (state->m_invert_data == true) + fec_oc_reg_ipr_invert |= invert_data_mask; + fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MERR__M)); + if (state->m_invert_err == true) + fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MERR__M; + fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MSTRT__M)); + if (state->m_invert_str == true) + fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MSTRT__M; + fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MVAL__M)); + if (state->m_invert_val == true) + fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MVAL__M; + fec_oc_reg_ipr_invert &= (~(FEC_OC_IPR_INVERT_MCLK__M)); + if (state->m_invert_clk == true) + fec_oc_reg_ipr_invert |= FEC_OC_IPR_INVERT_MCLK__M; + + return write16(state, FEC_OC_IPR_INVERT__A, fec_oc_reg_ipr_invert); } #define SCU_RAM_AGC_KI_INV_RF_POL__M 0x4000 -static int SetAgcRf(struct drxk_state *state, - struct SCfgAgc *pAgcCfg, bool isDTV) +static int set_agc_rf(struct drxk_state *state, + struct s_cfg_agc *p_agc_cfg, bool is_dtv) { int status = -EINVAL; u16 data = 0; - struct SCfgAgc *pIfAgcSettings; + struct s_cfg_agc *p_if_agc_settings; dprintk(1, "\n"); - if (pAgcCfg == NULL) + if (p_agc_cfg == NULL) goto error; - switch (pAgcCfg->ctrlMode) { + switch (p_agc_cfg->ctrl_mode) { case DRXK_AGC_CTRL_AUTO: /* Enable RF AGC DAC */ status = read16(state, IQM_AF_STDBY__A, &data); @@ -2246,7 +2186,7 @@ static int SetAgcRf(struct drxk_state *state, data &= ~SCU_RAM_AGC_CONFIG_DISABLE_RF_AGC__M; /* Polarity */ - if (state->m_RfAgcPol) + if (state->m_rf_agc_pol) data |= SCU_RAM_AGC_CONFIG_INV_RF_POL__M; else data &= ~SCU_RAM_AGC_CONFIG_INV_RF_POL__M; @@ -2260,7 +2200,7 @@ static int SetAgcRf(struct drxk_state *state, goto error; data &= ~SCU_RAM_AGC_KI_RED_RAGC_RED__M; - data |= (~(pAgcCfg->speed << + data |= (~(p_agc_cfg->speed << SCU_RAM_AGC_KI_RED_RAGC_RED__B) & SCU_RAM_AGC_KI_RED_RAGC_RED__M); @@ -2268,30 +2208,34 @@ static int SetAgcRf(struct drxk_state *state, if (status < 0) goto error; - if (IsDVBT(state)) - pIfAgcSettings = &state->m_dvbtIfAgcCfg; - else if (IsQAM(state)) - pIfAgcSettings = &state->m_qamIfAgcCfg; + if (is_dvbt(state)) + p_if_agc_settings = &state->m_dvbt_if_agc_cfg; + else if (is_qam(state)) + p_if_agc_settings = &state->m_qam_if_agc_cfg; else - pIfAgcSettings = &state->m_atvIfAgcCfg; - if (pIfAgcSettings == NULL) { + p_if_agc_settings = &state->m_atv_if_agc_cfg; + if (p_if_agc_settings == NULL) { status = -EINVAL; goto error; } /* Set TOP, only if IF-AGC is in AUTO mode */ - if (pIfAgcSettings->ctrlMode == DRXK_AGC_CTRL_AUTO) - status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, pAgcCfg->top); + if (p_if_agc_settings->ctrl_mode == DRXK_AGC_CTRL_AUTO) + status = write16(state, + SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, + p_agc_cfg->top); if (status < 0) goto error; /* Cut-Off current */ - status = write16(state, SCU_RAM_AGC_RF_IACCU_HI_CO__A, pAgcCfg->cutOffCurrent); + status = write16(state, SCU_RAM_AGC_RF_IACCU_HI_CO__A, + p_agc_cfg->cut_off_current); if (status < 0) goto error; /* Max. output level */ - status = write16(state, SCU_RAM_AGC_RF_MAX__A, pAgcCfg->maxOutputLevel); + status = write16(state, SCU_RAM_AGC_RF_MAX__A, + p_agc_cfg->max_output_level); if (status < 0) goto error; @@ -2312,7 +2256,7 @@ static int SetAgcRf(struct drxk_state *state, if (status < 0) goto error; data |= SCU_RAM_AGC_CONFIG_DISABLE_RF_AGC__M; - if (state->m_RfAgcPol) + if (state->m_rf_agc_pol) data |= SCU_RAM_AGC_CONFIG_INV_RF_POL__M; else data &= ~SCU_RAM_AGC_CONFIG_INV_RF_POL__M; @@ -2326,7 +2270,8 @@ static int SetAgcRf(struct drxk_state *state, goto error; /* Write value to output pin */ - status = write16(state, SCU_RAM_AGC_RF_IACCU_HI__A, pAgcCfg->outputLevel); + status = write16(state, SCU_RAM_AGC_RF_IACCU_HI__A, + p_agc_cfg->output_level); if (status < 0) goto error; break; @@ -2357,22 +2302,22 @@ static int SetAgcRf(struct drxk_state *state, } error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } #define SCU_RAM_AGC_KI_INV_IF_POL__M 0x2000 -static int SetAgcIf(struct drxk_state *state, - struct SCfgAgc *pAgcCfg, bool isDTV) +static int set_agc_if(struct drxk_state *state, + struct s_cfg_agc *p_agc_cfg, bool is_dtv) { u16 data = 0; int status = 0; - struct SCfgAgc *pRfAgcSettings; + struct s_cfg_agc *p_rf_agc_settings; dprintk(1, "\n"); - switch (pAgcCfg->ctrlMode) { + switch (p_agc_cfg->ctrl_mode) { case DRXK_AGC_CTRL_AUTO: /* Enable IF AGC DAC */ @@ -2392,7 +2337,7 @@ static int SetAgcIf(struct drxk_state *state, data &= ~SCU_RAM_AGC_CONFIG_DISABLE_IF_AGC__M; /* Polarity */ - if (state->m_IfAgcPol) + if (state->m_if_agc_pol) data |= SCU_RAM_AGC_CONFIG_INV_IF_POL__M; else data &= ~SCU_RAM_AGC_CONFIG_INV_IF_POL__M; @@ -2405,7 +2350,7 @@ static int SetAgcIf(struct drxk_state *state, if (status < 0) goto error; data &= ~SCU_RAM_AGC_KI_RED_IAGC_RED__M; - data |= (~(pAgcCfg->speed << + data |= (~(p_agc_cfg->speed << SCU_RAM_AGC_KI_RED_IAGC_RED__B) & SCU_RAM_AGC_KI_RED_IAGC_RED__M); @@ -2413,14 +2358,15 @@ static int SetAgcIf(struct drxk_state *state, if (status < 0) goto error; - if (IsQAM(state)) - pRfAgcSettings = &state->m_qamRfAgcCfg; + if (is_qam(state)) + p_rf_agc_settings = &state->m_qam_rf_agc_cfg; else - pRfAgcSettings = &state->m_atvRfAgcCfg; - if (pRfAgcSettings == NULL) + p_rf_agc_settings = &state->m_atv_rf_agc_cfg; + if (p_rf_agc_settings == NULL) return -1; /* Restore TOP */ - status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, pRfAgcSettings->top); + status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, + p_rf_agc_settings->top); if (status < 0) goto error; break; @@ -2444,7 +2390,7 @@ static int SetAgcIf(struct drxk_state *state, data |= SCU_RAM_AGC_CONFIG_DISABLE_IF_AGC__M; /* Polarity */ - if (state->m_IfAgcPol) + if (state->m_if_agc_pol) data |= SCU_RAM_AGC_CONFIG_INV_IF_POL__M; else data &= ~SCU_RAM_AGC_CONFIG_INV_IF_POL__M; @@ -2453,7 +2399,8 @@ static int SetAgcIf(struct drxk_state *state, goto error; /* Write value to output pin */ - status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, pAgcCfg->outputLevel); + status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, + p_agc_cfg->output_level); if (status < 0) goto error; break; @@ -2478,176 +2425,181 @@ static int SetAgcIf(struct drxk_state *state, if (status < 0) goto error; break; - } /* switch (agcSettingsIf->ctrlMode) */ + } /* switch (agcSettingsIf->ctrl_mode) */ /* always set the top to support configurations without if-loop */ - status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A, pAgcCfg->top); + status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A, p_agc_cfg->top); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } -static int GetQAMSignalToNoise(struct drxk_state *state, - s32 *pSignalToNoise) +static int get_qam_signal_to_noise(struct drxk_state *state, + s32 *p_signal_to_noise) { int status = 0; - u16 qamSlErrPower = 0; /* accum. error between + u16 qam_sl_err_power = 0; /* accum. error between raw and sliced symbols */ - u32 qamSlSigPower = 0; /* used for MER, depends of + u32 qam_sl_sig_power = 0; /* used for MER, depends of QAM modulation */ - u32 qamSlMer = 0; /* QAM MER */ + u32 qam_sl_mer = 0; /* QAM MER */ dprintk(1, "\n"); /* MER calculation */ /* get the register value needed for MER */ - status = read16(state, QAM_SL_ERR_POWER__A, &qamSlErrPower); + status = read16(state, QAM_SL_ERR_POWER__A, &qam_sl_err_power); if (status < 0) { - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return -EINVAL; } switch (state->props.modulation) { case QAM_16: - qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM16 << 2; + qam_sl_sig_power = DRXK_QAM_SL_SIG_POWER_QAM16 << 2; break; case QAM_32: - qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM32 << 2; + qam_sl_sig_power = DRXK_QAM_SL_SIG_POWER_QAM32 << 2; break; case QAM_64: - qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM64 << 2; + qam_sl_sig_power = DRXK_QAM_SL_SIG_POWER_QAM64 << 2; break; case QAM_128: - qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM128 << 2; + qam_sl_sig_power = DRXK_QAM_SL_SIG_POWER_QAM128 << 2; break; default: case QAM_256: - qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM256 << 2; + qam_sl_sig_power = DRXK_QAM_SL_SIG_POWER_QAM256 << 2; break; } - if (qamSlErrPower > 0) { - qamSlMer = Log10Times100(qamSlSigPower) - - Log10Times100((u32) qamSlErrPower); + if (qam_sl_err_power > 0) { + qam_sl_mer = log10times100(qam_sl_sig_power) - + log10times100((u32) qam_sl_err_power); } - *pSignalToNoise = qamSlMer; + *p_signal_to_noise = qam_sl_mer; return status; } -static int GetDVBTSignalToNoise(struct drxk_state *state, - s32 *pSignalToNoise) +static int get_dvbt_signal_to_noise(struct drxk_state *state, + s32 *p_signal_to_noise) { int status; - u16 regData = 0; - u32 EqRegTdSqrErrI = 0; - u32 EqRegTdSqrErrQ = 0; - u16 EqRegTdSqrErrExp = 0; - u16 EqRegTdTpsPwrOfs = 0; - u16 EqRegTdReqSmbCnt = 0; - u32 tpsCnt = 0; - u32 SqrErrIQ = 0; + u16 reg_data = 0; + u32 eq_reg_td_sqr_err_i = 0; + u32 eq_reg_td_sqr_err_q = 0; + u16 eq_reg_td_sqr_err_exp = 0; + u16 eq_reg_td_tps_pwr_ofs = 0; + u16 eq_reg_td_req_smb_cnt = 0; + u32 tps_cnt = 0; + u32 sqr_err_iq = 0; u32 a = 0; u32 b = 0; u32 c = 0; - u32 iMER = 0; - u16 transmissionParams = 0; + u32 i_mer = 0; + u16 transmission_params = 0; dprintk(1, "\n"); - status = read16(state, OFDM_EQ_TOP_TD_TPS_PWR_OFS__A, &EqRegTdTpsPwrOfs); + status = read16(state, OFDM_EQ_TOP_TD_TPS_PWR_OFS__A, + &eq_reg_td_tps_pwr_ofs); if (status < 0) goto error; - status = read16(state, OFDM_EQ_TOP_TD_REQ_SMB_CNT__A, &EqRegTdReqSmbCnt); + status = read16(state, OFDM_EQ_TOP_TD_REQ_SMB_CNT__A, + &eq_reg_td_req_smb_cnt); if (status < 0) goto error; - status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_EXP__A, &EqRegTdSqrErrExp); + status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_EXP__A, + &eq_reg_td_sqr_err_exp); if (status < 0) goto error; - status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_I__A, ®Data); + status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_I__A, + ®_data); if (status < 0) goto error; /* Extend SQR_ERR_I operational range */ - EqRegTdSqrErrI = (u32) regData; - if ((EqRegTdSqrErrExp > 11) && - (EqRegTdSqrErrI < 0x00000FFFUL)) { - EqRegTdSqrErrI += 0x00010000UL; + eq_reg_td_sqr_err_i = (u32) reg_data; + if ((eq_reg_td_sqr_err_exp > 11) && + (eq_reg_td_sqr_err_i < 0x00000FFFUL)) { + eq_reg_td_sqr_err_i += 0x00010000UL; } - status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_Q__A, ®Data); + status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_Q__A, ®_data); if (status < 0) goto error; /* Extend SQR_ERR_Q operational range */ - EqRegTdSqrErrQ = (u32) regData; - if ((EqRegTdSqrErrExp > 11) && - (EqRegTdSqrErrQ < 0x00000FFFUL)) - EqRegTdSqrErrQ += 0x00010000UL; + eq_reg_td_sqr_err_q = (u32) reg_data; + if ((eq_reg_td_sqr_err_exp > 11) && + (eq_reg_td_sqr_err_q < 0x00000FFFUL)) + eq_reg_td_sqr_err_q += 0x00010000UL; - status = read16(state, OFDM_SC_RA_RAM_OP_PARAM__A, &transmissionParams); + status = read16(state, OFDM_SC_RA_RAM_OP_PARAM__A, + &transmission_params); if (status < 0) goto error; /* Check input data for MER */ /* MER calculation (in 0.1 dB) without math.h */ - if ((EqRegTdTpsPwrOfs == 0) || (EqRegTdReqSmbCnt == 0)) - iMER = 0; - else if ((EqRegTdSqrErrI + EqRegTdSqrErrQ) == 0) { + if ((eq_reg_td_tps_pwr_ofs == 0) || (eq_reg_td_req_smb_cnt == 0)) + i_mer = 0; + else if ((eq_reg_td_sqr_err_i + eq_reg_td_sqr_err_q) == 0) { /* No error at all, this must be the HW reset value * Apparently no first measurement yet * Set MER to 0.0 */ - iMER = 0; + i_mer = 0; } else { - SqrErrIQ = (EqRegTdSqrErrI + EqRegTdSqrErrQ) << - EqRegTdSqrErrExp; - if ((transmissionParams & + sqr_err_iq = (eq_reg_td_sqr_err_i + eq_reg_td_sqr_err_q) << + eq_reg_td_sqr_err_exp; + if ((transmission_params & OFDM_SC_RA_RAM_OP_PARAM_MODE__M) == OFDM_SC_RA_RAM_OP_PARAM_MODE_2K) - tpsCnt = 17; + tps_cnt = 17; else - tpsCnt = 68; + tps_cnt = 68; /* IMER = 100 * log10 (x) - where x = (EqRegTdTpsPwrOfs^2 * - EqRegTdReqSmbCnt * tpsCnt)/SqrErrIQ + where x = (eq_reg_td_tps_pwr_ofs^2 * + eq_reg_td_req_smb_cnt * tps_cnt)/sqr_err_iq => IMER = a + b -c - where a = 100 * log10 (EqRegTdTpsPwrOfs^2) - b = 100 * log10 (EqRegTdReqSmbCnt * tpsCnt) - c = 100 * log10 (SqrErrIQ) + where a = 100 * log10 (eq_reg_td_tps_pwr_ofs^2) + b = 100 * log10 (eq_reg_td_req_smb_cnt * tps_cnt) + c = 100 * log10 (sqr_err_iq) */ /* log(x) x = 9bits * 9bits->18 bits */ - a = Log10Times100(EqRegTdTpsPwrOfs * - EqRegTdTpsPwrOfs); + a = log10times100(eq_reg_td_tps_pwr_ofs * + eq_reg_td_tps_pwr_ofs); /* log(x) x = 16bits * 7bits->23 bits */ - b = Log10Times100(EqRegTdReqSmbCnt * tpsCnt); + b = log10times100(eq_reg_td_req_smb_cnt * tps_cnt); /* log(x) x = (16bits + 16bits) << 15 ->32 bits */ - c = Log10Times100(SqrErrIQ); + c = log10times100(sqr_err_iq); - iMER = a + b - c; + i_mer = a + b - c; } - *pSignalToNoise = iMER; + *p_signal_to_noise = i_mer; error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } -static int GetSignalToNoise(struct drxk_state *state, s32 *pSignalToNoise) +static int get_signal_to_noise(struct drxk_state *state, s32 *p_signal_to_noise) { dprintk(1, "\n"); - *pSignalToNoise = 0; - switch (state->m_OperationMode) { + *p_signal_to_noise = 0; + switch (state->m_operation_mode) { case OM_DVBT: - return GetDVBTSignalToNoise(state, pSignalToNoise); + return get_dvbt_signal_to_noise(state, p_signal_to_noise); case OM_QAM_ITU_A: case OM_QAM_ITU_C: - return GetQAMSignalToNoise(state, pSignalToNoise); + return get_qam_signal_to_noise(state, p_signal_to_noise); default: break; } @@ -2655,7 +2607,7 @@ static int GetSignalToNoise(struct drxk_state *state, s32 *pSignalToNoise) } #if 0 -static int GetDVBTQuality(struct drxk_state *state, s32 *pQuality) +static int get_dvbt_quality(struct drxk_state *state, s32 *p_quality) { /* SNR Values for quasi errorfree reception rom Nordig 2.2 */ int status = 0; @@ -2680,102 +2632,104 @@ static int GetDVBTQuality(struct drxk_state *state, s32 *pQuality) 225, /* 64-QAM 7/8 */ }; - *pQuality = 0; + *p_quality = 0; do { - s32 SignalToNoise = 0; - u16 Constellation = 0; - u16 CodeRate = 0; - u32 SignalToNoiseRel; - u32 BERQuality; + s32 signal_to_noise = 0; + u16 constellation = 0; + u16 code_rate = 0; + u32 signal_to_noise_rel; + u32 ber_quality; - status = GetDVBTSignalToNoise(state, &SignalToNoise); + status = get_dvbt_signal_to_noise(state, &signal_to_noise); if (status < 0) break; - status = read16(state, OFDM_EQ_TOP_TD_TPS_CONST__A, &Constellation); + status = read16(state, OFDM_EQ_TOP_TD_TPS_CONST__A, + &constellation); if (status < 0) break; - Constellation &= OFDM_EQ_TOP_TD_TPS_CONST__M; + constellation &= OFDM_EQ_TOP_TD_TPS_CONST__M; - status = read16(state, OFDM_EQ_TOP_TD_TPS_CODE_HP__A, &CodeRate); + status = read16(state, OFDM_EQ_TOP_TD_TPS_CODE_HP__A, + &code_rate); if (status < 0) break; - CodeRate &= OFDM_EQ_TOP_TD_TPS_CODE_HP__M; + code_rate &= OFDM_EQ_TOP_TD_TPS_CODE_HP__M; - if (Constellation > OFDM_EQ_TOP_TD_TPS_CONST_64QAM || - CodeRate > OFDM_EQ_TOP_TD_TPS_CODE_LP_7_8) + if (constellation > OFDM_EQ_TOP_TD_TPS_CONST_64QAM || + code_rate > OFDM_EQ_TOP_TD_TPS_CODE_LP_7_8) break; - SignalToNoiseRel = SignalToNoise - - QE_SN[Constellation * 5 + CodeRate]; - BERQuality = 100; - - if (SignalToNoiseRel < -70) - *pQuality = 0; - else if (SignalToNoiseRel < 30) - *pQuality = ((SignalToNoiseRel + 70) * - BERQuality) / 100; + signal_to_noise_rel = signal_to_noise - + QE_SN[constellation * 5 + code_rate]; + ber_quality = 100; + + if (signal_to_noise_rel < -70) + *p_quality = 0; + else if (signal_to_noise_rel < 30) + *p_quality = ((signal_to_noise_rel + 70) * + ber_quality) / 100; else - *pQuality = BERQuality; + *p_quality = ber_quality; } while (0); return 0; }; -static int GetDVBCQuality(struct drxk_state *state, s32 *pQuality) +static int get_dvbc_quality(struct drxk_state *state, s32 *p_quality) { int status = 0; - *pQuality = 0; + *p_quality = 0; dprintk(1, "\n"); do { - u32 SignalToNoise = 0; - u32 BERQuality = 100; - u32 SignalToNoiseRel = 0; + u32 signal_to_noise = 0; + u32 ber_quality = 100; + u32 signal_to_noise_rel = 0; - status = GetQAMSignalToNoise(state, &SignalToNoise); + status = get_qam_signal_to_noise(state, &signal_to_noise); if (status < 0) break; switch (state->props.modulation) { case QAM_16: - SignalToNoiseRel = SignalToNoise - 200; + signal_to_noise_rel = signal_to_noise - 200; break; case QAM_32: - SignalToNoiseRel = SignalToNoise - 230; + signal_to_noise_rel = signal_to_noise - 230; break; /* Not in NorDig */ case QAM_64: - SignalToNoiseRel = SignalToNoise - 260; + signal_to_noise_rel = signal_to_noise - 260; break; case QAM_128: - SignalToNoiseRel = SignalToNoise - 290; + signal_to_noise_rel = signal_to_noise - 290; break; default: case QAM_256: - SignalToNoiseRel = SignalToNoise - 320; + signal_to_noise_rel = signal_to_noise - 320; break; } - if (SignalToNoiseRel < -70) - *pQuality = 0; - else if (SignalToNoiseRel < 30) - *pQuality = ((SignalToNoiseRel + 70) * - BERQuality) / 100; + if (signal_to_noise_rel < -70) + *p_quality = 0; + else if (signal_to_noise_rel < 30) + *p_quality = ((signal_to_noise_rel + 70) * + ber_quality) / 100; else - *pQuality = BERQuality; + *p_quality = ber_quality; } while (0); return status; } -static int GetQuality(struct drxk_state *state, s32 *pQuality) +static int get_quality(struct drxk_state *state, s32 *p_quality) { dprintk(1, "\n"); - switch (state->m_OperationMode) { + switch (state->m_operation_mode) { case OM_DVBT: - return GetDVBTQuality(state, pQuality); + return get_dvbt_quality(state, p_quality); case OM_QAM_ITU_A: - return GetDVBCQuality(state, pQuality); + return get_dvbc_quality(state, p_quality); default: break; } @@ -2797,65 +2751,68 @@ static int GetQuality(struct drxk_state *state, s32 *pQuality) #define DRXDAP_FASI_ADDR2BANK(addr) (((addr) >> 16) & 0x3F) #define DRXDAP_FASI_ADDR2OFFSET(addr) ((addr) & 0x7FFF) -static int ConfigureI2CBridge(struct drxk_state *state, bool bEnableBridge) +static int ConfigureI2CBridge(struct drxk_state *state, bool b_enable_bridge) { int status = -EINVAL; dprintk(1, "\n"); - if (state->m_DrxkState == DRXK_UNINITIALIZED) + if (state->m_drxk_state == DRXK_UNINITIALIZED) return 0; - if (state->m_DrxkState == DRXK_POWERED_DOWN) + if (state->m_drxk_state == DRXK_POWERED_DOWN) goto error; if (state->no_i2c_bridge) return 0; - status = write16(state, SIO_HI_RA_RAM_PAR_1__A, SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY); + status = write16(state, SIO_HI_RA_RAM_PAR_1__A, + SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY); if (status < 0) goto error; - if (bEnableBridge) { - status = write16(state, SIO_HI_RA_RAM_PAR_2__A, SIO_HI_RA_RAM_PAR_2_BRD_CFG_CLOSED); + if (b_enable_bridge) { + status = write16(state, SIO_HI_RA_RAM_PAR_2__A, + SIO_HI_RA_RAM_PAR_2_BRD_CFG_CLOSED); if (status < 0) goto error; } else { - status = write16(state, SIO_HI_RA_RAM_PAR_2__A, SIO_HI_RA_RAM_PAR_2_BRD_CFG_OPEN); + status = write16(state, SIO_HI_RA_RAM_PAR_2__A, + SIO_HI_RA_RAM_PAR_2_BRD_CFG_OPEN); if (status < 0) goto error; } - status = HI_Command(state, SIO_HI_RA_RAM_CMD_BRDCTRL, 0); + status = hi_command(state, SIO_HI_RA_RAM_CMD_BRDCTRL, 0); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } -static int SetPreSaw(struct drxk_state *state, - struct SCfgPreSaw *pPreSawCfg) +static int set_pre_saw(struct drxk_state *state, + struct s_cfg_pre_saw *p_pre_saw_cfg) { int status = -EINVAL; dprintk(1, "\n"); - if ((pPreSawCfg == NULL) - || (pPreSawCfg->reference > IQM_AF_PDREF__M)) + if ((p_pre_saw_cfg == NULL) + || (p_pre_saw_cfg->reference > IQM_AF_PDREF__M)) goto error; - status = write16(state, IQM_AF_PDREF__A, pPreSawCfg->reference); + status = write16(state, IQM_AF_PDREF__A, p_pre_saw_cfg->reference); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } -static int BLDirectCmd(struct drxk_state *state, u32 targetAddr, - u16 romOffset, u16 nrOfElements, u32 timeOut) +static int bl_direct_cmd(struct drxk_state *state, u32 target_addr, + u16 rom_offset, u16 nr_of_elements, u32 time_out) { - u16 blStatus = 0; - u16 offset = (u16) ((targetAddr >> 0) & 0x00FFFF); - u16 blockbank = (u16) ((targetAddr >> 16) & 0x000FFF); + u16 bl_status = 0; + u16 offset = (u16) ((target_addr >> 0) & 0x00FFFF); + u16 blockbank = (u16) ((target_addr >> 16) & 0x000FFF); int status; unsigned long end; @@ -2871,44 +2828,44 @@ static int BLDirectCmd(struct drxk_state *state, u32 targetAddr, status = write16(state, SIO_BL_TGT_ADDR__A, offset); if (status < 0) goto error; - status = write16(state, SIO_BL_SRC_ADDR__A, romOffset); + status = write16(state, SIO_BL_SRC_ADDR__A, rom_offset); if (status < 0) goto error; - status = write16(state, SIO_BL_SRC_LEN__A, nrOfElements); + status = write16(state, SIO_BL_SRC_LEN__A, nr_of_elements); if (status < 0) goto error; status = write16(state, SIO_BL_ENABLE__A, SIO_BL_ENABLE_ON); if (status < 0) goto error; - end = jiffies + msecs_to_jiffies(timeOut); + end = jiffies + msecs_to_jiffies(time_out); do { - status = read16(state, SIO_BL_STATUS__A, &blStatus); + status = read16(state, SIO_BL_STATUS__A, &bl_status); if (status < 0) goto error; - } while ((blStatus == 0x1) && time_is_after_jiffies(end)); - if (blStatus == 0x1) { - printk(KERN_ERR "drxk: SIO not ready\n"); + } while ((bl_status == 0x1) && time_is_after_jiffies(end)); + if (bl_status == 0x1) { + pr_err("SIO not ready\n"); status = -EINVAL; goto error2; } error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); error2: mutex_unlock(&state->mutex); return status; } -static int ADCSyncMeasurement(struct drxk_state *state, u16 *count) +static int adc_sync_measurement(struct drxk_state *state, u16 *count) { u16 data = 0; int status; dprintk(1, "\n"); - /* Start measurement */ + /* start measurement */ status = write16(state, IQM_AF_COMM_EXEC__A, IQM_AF_COMM_EXEC_ACTIVE); if (status < 0) goto error; @@ -2935,42 +2892,42 @@ static int ADCSyncMeasurement(struct drxk_state *state, u16 *count) error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } -static int ADCSynchronization(struct drxk_state *state) +static int adc_synchronization(struct drxk_state *state) { u16 count = 0; int status; dprintk(1, "\n"); - status = ADCSyncMeasurement(state, &count); + status = adc_sync_measurement(state, &count); if (status < 0) goto error; if (count == 1) { /* Try sampling on a diffrent edge */ - u16 clkNeg = 0; + u16 clk_neg = 0; - status = read16(state, IQM_AF_CLKNEG__A, &clkNeg); + status = read16(state, IQM_AF_CLKNEG__A, &clk_neg); if (status < 0) goto error; - if ((clkNeg & IQM_AF_CLKNEG_CLKNEGDATA__M) == + if ((clk_neg & IQM_AF_CLKNEG_CLKNEGDATA__M) == IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_POS) { - clkNeg &= (~(IQM_AF_CLKNEG_CLKNEGDATA__M)); - clkNeg |= + clk_neg &= (~(IQM_AF_CLKNEG_CLKNEGDATA__M)); + clk_neg |= IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_NEG; } else { - clkNeg &= (~(IQM_AF_CLKNEG_CLKNEGDATA__M)); - clkNeg |= + clk_neg &= (~(IQM_AF_CLKNEG_CLKNEGDATA__M)); + clk_neg |= IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_POS; } - status = write16(state, IQM_AF_CLKNEG__A, clkNeg); + status = write16(state, IQM_AF_CLKNEG__A, clk_neg); if (status < 0) goto error; - status = ADCSyncMeasurement(state, &count); + status = adc_sync_measurement(state, &count); if (status < 0) goto error; } @@ -2979,25 +2936,25 @@ static int ADCSynchronization(struct drxk_state *state) status = -EINVAL; error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } -static int SetFrequencyShifter(struct drxk_state *state, - u16 intermediateFreqkHz, - s32 tunerFreqOffset, bool isDTV) +static int set_frequency_shifter(struct drxk_state *state, + u16 intermediate_freqk_hz, + s32 tuner_freq_offset, bool is_dtv) { - bool selectPosImage = false; - u32 rfFreqResidual = tunerFreqOffset; - u32 fmFrequencyShift = 0; - bool tunerMirror = !state->m_bMirrorFreqSpect; - u32 adcFreq; - bool adcFlip; + bool select_pos_image = false; + u32 rf_freq_residual = tuner_freq_offset; + u32 fm_frequency_shift = 0; + bool tuner_mirror = !state->m_b_mirror_freq_spect; + u32 adc_freq; + bool adc_flip; int status; - u32 ifFreqActual; - u32 samplingFrequency = (u32) (state->m_sysClockFreq / 3); - u32 frequencyShift; - bool imageToSelect; + u32 if_freq_actual; + u32 sampling_frequency = (u32) (state->m_sys_clock_freq / 3); + u32 frequency_shift; + bool image_to_select; dprintk(1, "\n"); @@ -3005,121 +2962,125 @@ static int SetFrequencyShifter(struct drxk_state *state, Program frequency shifter No need to account for mirroring on RF */ - if (isDTV) { - if ((state->m_OperationMode == OM_QAM_ITU_A) || - (state->m_OperationMode == OM_QAM_ITU_C) || - (state->m_OperationMode == OM_DVBT)) - selectPosImage = true; + if (is_dtv) { + if ((state->m_operation_mode == OM_QAM_ITU_A) || + (state->m_operation_mode == OM_QAM_ITU_C) || + (state->m_operation_mode == OM_DVBT)) + select_pos_image = true; else - selectPosImage = false; + select_pos_image = false; } - if (tunerMirror) + if (tuner_mirror) /* tuner doesn't mirror */ - ifFreqActual = intermediateFreqkHz + - rfFreqResidual + fmFrequencyShift; + if_freq_actual = intermediate_freqk_hz + + rf_freq_residual + fm_frequency_shift; else /* tuner mirrors */ - ifFreqActual = intermediateFreqkHz - - rfFreqResidual - fmFrequencyShift; - if (ifFreqActual > samplingFrequency / 2) { + if_freq_actual = intermediate_freqk_hz - + rf_freq_residual - fm_frequency_shift; + if (if_freq_actual > sampling_frequency / 2) { /* adc mirrors */ - adcFreq = samplingFrequency - ifFreqActual; - adcFlip = true; + adc_freq = sampling_frequency - if_freq_actual; + adc_flip = true; } else { /* adc doesn't mirror */ - adcFreq = ifFreqActual; - adcFlip = false; + adc_freq = if_freq_actual; + adc_flip = false; } - frequencyShift = adcFreq; - imageToSelect = state->m_rfmirror ^ tunerMirror ^ - adcFlip ^ selectPosImage; - state->m_IqmFsRateOfs = - Frac28a((frequencyShift), samplingFrequency); + frequency_shift = adc_freq; + image_to_select = state->m_rfmirror ^ tuner_mirror ^ + adc_flip ^ select_pos_image; + state->m_iqm_fs_rate_ofs = + Frac28a((frequency_shift), sampling_frequency); - if (imageToSelect) - state->m_IqmFsRateOfs = ~state->m_IqmFsRateOfs + 1; + if (image_to_select) + state->m_iqm_fs_rate_ofs = ~state->m_iqm_fs_rate_ofs + 1; /* Program frequency shifter with tuner offset compensation */ - /* frequencyShift += tunerFreqOffset; TODO */ + /* frequency_shift += tuner_freq_offset; TODO */ status = write32(state, IQM_FS_RATE_OFS_LO__A, - state->m_IqmFsRateOfs); + state->m_iqm_fs_rate_ofs); if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } -static int InitAGC(struct drxk_state *state, bool isDTV) +static int init_agc(struct drxk_state *state, bool is_dtv) { - u16 ingainTgt = 0; - u16 ingainTgtMin = 0; - u16 ingainTgtMax = 0; - u16 clpCyclen = 0; - u16 clpSumMin = 0; - u16 clpDirTo = 0; - u16 snsSumMin = 0; - u16 snsSumMax = 0; - u16 clpSumMax = 0; - u16 snsDirTo = 0; - u16 kiInnergainMin = 0; - u16 ifIaccuHiTgt = 0; - u16 ifIaccuHiTgtMin = 0; - u16 ifIaccuHiTgtMax = 0; + u16 ingain_tgt = 0; + u16 ingain_tgt_min = 0; + u16 ingain_tgt_max = 0; + u16 clp_cyclen = 0; + u16 clp_sum_min = 0; + u16 clp_dir_to = 0; + u16 sns_sum_min = 0; + u16 sns_sum_max = 0; + u16 clp_sum_max = 0; + u16 sns_dir_to = 0; + u16 ki_innergain_min = 0; + u16 if_iaccu_hi_tgt = 0; + u16 if_iaccu_hi_tgt_min = 0; + u16 if_iaccu_hi_tgt_max = 0; u16 data = 0; - u16 fastClpCtrlDelay = 0; - u16 clpCtrlMode = 0; + u16 fast_clp_ctrl_delay = 0; + u16 clp_ctrl_mode = 0; int status = 0; dprintk(1, "\n"); /* Common settings */ - snsSumMax = 1023; - ifIaccuHiTgtMin = 2047; - clpCyclen = 500; - clpSumMax = 1023; + sns_sum_max = 1023; + if_iaccu_hi_tgt_min = 2047; + clp_cyclen = 500; + clp_sum_max = 1023; /* AGCInit() not available for DVBT; init done in microcode */ - if (!IsQAM(state)) { - printk(KERN_ERR "drxk: %s: mode %d is not DVB-C\n", __func__, state->m_OperationMode); + if (!is_qam(state)) { + pr_err("%s: mode %d is not DVB-C\n", + __func__, state->m_operation_mode); return -EINVAL; } /* FIXME: Analog TV AGC require different settings */ /* Standard specific settings */ - clpSumMin = 8; - clpDirTo = (u16) -9; - clpCtrlMode = 0; - snsSumMin = 8; - snsDirTo = (u16) -9; - kiInnergainMin = (u16) -1030; - ifIaccuHiTgtMax = 0x2380; - ifIaccuHiTgt = 0x2380; - ingainTgtMin = 0x0511; - ingainTgt = 0x0511; - ingainTgtMax = 5119; - fastClpCtrlDelay = state->m_qamIfAgcCfg.FastClipCtrlDelay; + clp_sum_min = 8; + clp_dir_to = (u16) -9; + clp_ctrl_mode = 0; + sns_sum_min = 8; + sns_dir_to = (u16) -9; + ki_innergain_min = (u16) -1030; + if_iaccu_hi_tgt_max = 0x2380; + if_iaccu_hi_tgt = 0x2380; + ingain_tgt_min = 0x0511; + ingain_tgt = 0x0511; + ingain_tgt_max = 5119; + fast_clp_ctrl_delay = state->m_qam_if_agc_cfg.fast_clip_ctrl_delay; - status = write16(state, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A, fastClpCtrlDelay); + status = write16(state, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A, + fast_clp_ctrl_delay); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_CLP_CTRL_MODE__A, clpCtrlMode); + status = write16(state, SCU_RAM_AGC_CLP_CTRL_MODE__A, clp_ctrl_mode); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_INGAIN_TGT__A, ingainTgt); + status = write16(state, SCU_RAM_AGC_INGAIN_TGT__A, ingain_tgt); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A, ingainTgtMin); + status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A, ingain_tgt_min); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MAX__A, ingainTgtMax); + status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MAX__A, ingain_tgt_max); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MIN__A, ifIaccuHiTgtMin); + status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MIN__A, + if_iaccu_hi_tgt_min); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, ifIaccuHiTgtMax); + status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, + if_iaccu_hi_tgt_max); if (status < 0) goto error; status = write16(state, SCU_RAM_AGC_IF_IACCU_HI__A, 0); @@ -3134,20 +3095,22 @@ static int InitAGC(struct drxk_state *state, bool isDTV) status = write16(state, SCU_RAM_AGC_RF_IACCU_LO__A, 0); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_CLP_SUM_MAX__A, clpSumMax); + status = write16(state, SCU_RAM_AGC_CLP_SUM_MAX__A, clp_sum_max); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_SNS_SUM_MAX__A, snsSumMax); + status = write16(state, SCU_RAM_AGC_SNS_SUM_MAX__A, sns_sum_max); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_KI_INNERGAIN_MIN__A, kiInnergainMin); + status = write16(state, SCU_RAM_AGC_KI_INNERGAIN_MIN__A, + ki_innergain_min); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT__A, ifIaccuHiTgt); + status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT__A, + if_iaccu_hi_tgt); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_CLP_CYCLEN__A, clpCyclen); + status = write16(state, SCU_RAM_AGC_CLP_CYCLEN__A, clp_cyclen); if (status < 0) goto error; @@ -3164,16 +3127,16 @@ static int InitAGC(struct drxk_state *state, bool isDTV) status = write16(state, SCU_RAM_AGC_KI_MAXMINGAIN_TH__A, 20); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_CLP_SUM_MIN__A, clpSumMin); + status = write16(state, SCU_RAM_AGC_CLP_SUM_MIN__A, clp_sum_min); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_SNS_SUM_MIN__A, snsSumMin); + status = write16(state, SCU_RAM_AGC_SNS_SUM_MIN__A, sns_sum_min); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_CLP_DIR_TO__A, clpDirTo); + status = write16(state, SCU_RAM_AGC_CLP_DIR_TO__A, clp_dir_to); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_SNS_DIR_TO__A, snsDirTo); + status = write16(state, SCU_RAM_AGC_SNS_DIR_TO__A, sns_dir_to); if (status < 0) goto error; status = write16(state, SCU_RAM_AGC_KI_MINGAIN__A, 0x7fff); @@ -3233,38 +3196,39 @@ static int InitAGC(struct drxk_state *state, bool isDTV) status = write16(state, SCU_RAM_AGC_KI__A, data); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } -static int DVBTQAMGetAccPktErr(struct drxk_state *state, u16 *packetErr) +static int dvbtqam_get_acc_pkt_err(struct drxk_state *state, u16 *packet_err) { int status; dprintk(1, "\n"); - if (packetErr == NULL) + if (packet_err == NULL) status = write16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, 0); else - status = read16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, packetErr); + status = read16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, + packet_err); if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } -static int DVBTScCommand(struct drxk_state *state, +static int dvbt_sc_command(struct drxk_state *state, u16 cmd, u16 subcmd, u16 param0, u16 param1, u16 param2, u16 param3, u16 param4) { - u16 curCmd = 0; - u16 errCode = 0; - u16 retryCnt = 0; - u16 scExec = 0; + u16 cur_cmd = 0; + u16 err_code = 0; + u16 retry_cnt = 0; + u16 sc_exec = 0; int status; dprintk(1, "\n"); - status = read16(state, OFDM_SC_COMM_EXEC__A, &scExec); - if (scExec != 1) { + status = read16(state, OFDM_SC_COMM_EXEC__A, &sc_exec); + if (sc_exec != 1) { /* SC is not running */ status = -EINVAL; } @@ -3272,13 +3236,13 @@ static int DVBTScCommand(struct drxk_state *state, goto error; /* Wait until sc is ready to receive command */ - retryCnt = 0; + retry_cnt = 0; do { - msleep(1); - status = read16(state, OFDM_SC_RA_RAM_CMD__A, &curCmd); - retryCnt++; - } while ((curCmd != 0) && (retryCnt < DRXK_MAX_RETRIES)); - if (retryCnt >= DRXK_MAX_RETRIES && (status < 0)) + usleep_range(1000, 2000); + status = read16(state, OFDM_SC_RA_RAM_CMD__A, &cur_cmd); + retry_cnt++; + } while ((cur_cmd != 0) && (retry_cnt < DRXK_MAX_RETRIES)); + if (retry_cnt >= DRXK_MAX_RETRIES && (status < 0)) goto error; /* Write sub-command */ @@ -3324,18 +3288,18 @@ static int DVBTScCommand(struct drxk_state *state, goto error; /* Wait until sc is ready processing command */ - retryCnt = 0; + retry_cnt = 0; do { - msleep(1); - status = read16(state, OFDM_SC_RA_RAM_CMD__A, &curCmd); - retryCnt++; - } while ((curCmd != 0) && (retryCnt < DRXK_MAX_RETRIES)); - if (retryCnt >= DRXK_MAX_RETRIES && (status < 0)) + usleep_range(1000, 2000); + status = read16(state, OFDM_SC_RA_RAM_CMD__A, &cur_cmd); + retry_cnt++; + } while ((cur_cmd != 0) && (retry_cnt < DRXK_MAX_RETRIES)); + if (retry_cnt >= DRXK_MAX_RETRIES && (status < 0)) goto error; /* Check for illegal cmd */ - status = read16(state, OFDM_SC_RA_RAM_CMD_ADDR__A, &errCode); - if (errCode == 0xFFFF) { + status = read16(state, OFDM_SC_RA_RAM_CMD_ADDR__A, &err_code); + if (err_code == 0xFFFF) { /* illegal command */ status = -EINVAL; } @@ -3367,23 +3331,23 @@ static int DVBTScCommand(struct drxk_state *state, } /* switch (cmd->cmd) */ error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } -static int PowerUpDVBT(struct drxk_state *state) +static int power_up_dvbt(struct drxk_state *state) { - enum DRXPowerMode powerMode = DRX_POWER_UP; + enum drx_power_mode power_mode = DRX_POWER_UP; int status; dprintk(1, "\n"); - status = CtrlPowerMode(state, &powerMode); + status = ctrl_power_mode(state, &power_mode); if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } -static int DVBTCtrlSetIncEnable(struct drxk_state *state, bool *enabled) +static int dvbt_ctrl_set_inc_enable(struct drxk_state *state, bool *enabled) { int status; @@ -3393,12 +3357,12 @@ static int DVBTCtrlSetIncEnable(struct drxk_state *state, bool *enabled) else status = write16(state, IQM_CF_BYPASSDET__A, 1); if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } #define DEFAULT_FR_THRES_8K 4000 -static int DVBTCtrlSetFrEnable(struct drxk_state *state, bool *enabled) +static int dvbt_ctrl_set_fr_enable(struct drxk_state *state, bool *enabled) { int status; @@ -3413,13 +3377,13 @@ static int DVBTCtrlSetFrEnable(struct drxk_state *state, bool *enabled) status = write16(state, OFDM_SC_RA_RAM_FR_THRES_8K__A, 0); } if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } -static int DVBTCtrlSetEchoThreshold(struct drxk_state *state, - struct DRXKCfgDvbtEchoThres_t *echoThres) +static int dvbt_ctrl_set_echo_threshold(struct drxk_state *state, + struct drxk_cfg_dvbt_echo_thres_t *echo_thres) { u16 data = 0; int status; @@ -3429,16 +3393,16 @@ static int DVBTCtrlSetEchoThreshold(struct drxk_state *state, if (status < 0) goto error; - switch (echoThres->fftMode) { + switch (echo_thres->fft_mode) { case DRX_FFTMODE_2K: data &= ~OFDM_SC_RA_RAM_ECHO_THRES_2K__M; - data |= ((echoThres->threshold << + data |= ((echo_thres->threshold << OFDM_SC_RA_RAM_ECHO_THRES_2K__B) & (OFDM_SC_RA_RAM_ECHO_THRES_2K__M)); break; case DRX_FFTMODE_8K: data &= ~OFDM_SC_RA_RAM_ECHO_THRES_8K__M; - data |= ((echoThres->threshold << + data |= ((echo_thres->threshold << OFDM_SC_RA_RAM_ECHO_THRES_8K__B) & (OFDM_SC_RA_RAM_ECHO_THRES_8K__M)); break; @@ -3449,12 +3413,12 @@ static int DVBTCtrlSetEchoThreshold(struct drxk_state *state, status = write16(state, OFDM_SC_RA_RAM_ECHO_THRES__A, data); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } -static int DVBTCtrlSetSqiSpeed(struct drxk_state *state, - enum DRXKCfgDvbtSqiSpeed *speed) +static int dvbt_ctrl_set_sqi_speed(struct drxk_state *state, + enum drxk_cfg_dvbt_sqi_speed *speed) { int status = -EINVAL; @@ -3472,7 +3436,7 @@ static int DVBTCtrlSetSqiSpeed(struct drxk_state *state, (u16) *speed); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -3486,32 +3450,33 @@ error: * Called in DVBTSetStandard * */ -static int DVBTActivatePresets(struct drxk_state *state) +static int dvbt_activate_presets(struct drxk_state *state) { int status; bool setincenable = false; bool setfrenable = true; - struct DRXKCfgDvbtEchoThres_t echoThres2k = { 0, DRX_FFTMODE_2K }; - struct DRXKCfgDvbtEchoThres_t echoThres8k = { 0, DRX_FFTMODE_8K }; + struct drxk_cfg_dvbt_echo_thres_t echo_thres2k = { 0, DRX_FFTMODE_2K }; + struct drxk_cfg_dvbt_echo_thres_t echo_thres8k = { 0, DRX_FFTMODE_8K }; dprintk(1, "\n"); - status = DVBTCtrlSetIncEnable(state, &setincenable); + status = dvbt_ctrl_set_inc_enable(state, &setincenable); if (status < 0) goto error; - status = DVBTCtrlSetFrEnable(state, &setfrenable); + status = dvbt_ctrl_set_fr_enable(state, &setfrenable); if (status < 0) goto error; - status = DVBTCtrlSetEchoThreshold(state, &echoThres2k); + status = dvbt_ctrl_set_echo_threshold(state, &echo_thres2k); if (status < 0) goto error; - status = DVBTCtrlSetEchoThreshold(state, &echoThres8k); + status = dvbt_ctrl_set_echo_threshold(state, &echo_thres8k); if (status < 0) goto error; - status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MAX__A, state->m_dvbtIfAgcCfg.IngainTgtMax); + status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MAX__A, + state->m_dvbt_if_agc_cfg.ingain_tgt_max); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -3525,25 +3490,30 @@ error: * For ROM code channel filter taps are loaded from the bootloader. For microcode * the DVB-T taps from the drxk_filters.h are used. */ -static int SetDVBTStandard(struct drxk_state *state, - enum OperationMode oMode) +static int set_dvbt_standard(struct drxk_state *state, + enum operation_mode o_mode) { - u16 cmdResult = 0; + u16 cmd_result = 0; u16 data = 0; int status; dprintk(1, "\n"); - PowerUpDVBT(state); + power_up_dvbt(state); /* added antenna switch */ - SwitchAntennaToDVBT(state); + switch_antenna_to_dvbt(state); /* send OFDM reset command */ - status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_RESET, 0, NULL, 1, &cmdResult); + status = scu_command(state, + SCU_RAM_COMMAND_STANDARD_OFDM + | SCU_RAM_COMMAND_CMD_DEMOD_RESET, + 0, NULL, 1, &cmd_result); if (status < 0) goto error; /* send OFDM setenv command */ - status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV, 0, NULL, 1, &cmdResult); + status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM + | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV, + 0, NULL, 1, &cmd_result); if (status < 0) goto error; @@ -3575,7 +3545,7 @@ static int SetDVBTStandard(struct drxk_state *state, status = write16(state, IQM_AF_AMUX__A, IQM_AF_AMUX_SIGNAL2ADC); if (status < 0) goto error; - status = SetIqmAf(state, true); + status = set_iqm_af(state, true); if (status < 0) goto error; @@ -3597,7 +3567,7 @@ static int SetDVBTStandard(struct drxk_state *state, status = write16(state, IQM_RC_STRETCH__A, 16); if (status < 0) goto error; - status = write16(state, IQM_CF_OUT_ENA__A, 0x4); /* enable output 2 */ + status = write16(state, IQM_CF_OUT_ENA__A, 0x4); /* enable output 2 */ if (status < 0) goto error; status = write16(state, IQM_CF_DS_ENA__A, 0x4); /* decimate output 2 */ @@ -3618,7 +3588,8 @@ static int SetDVBTStandard(struct drxk_state *state, if (status < 0) goto error; - status = BLChainCmd(state, DRXK_BL_ROM_OFFSET_TAPS_DVBT, DRXK_BLCC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT); + status = bl_chain_cmd(state, DRXK_BL_ROM_OFFSET_TAPS_DVBT, + DRXK_BLCC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT); if (status < 0) goto error; @@ -3637,10 +3608,10 @@ static int SetDVBTStandard(struct drxk_state *state, goto error; /* IQM will not be reset from here, sync ADC and update/init AGC */ - status = ADCSynchronization(state); + status = adc_synchronization(state); if (status < 0) goto error; - status = SetPreSaw(state, &state->m_dvbtPreSawCfg); + status = set_pre_saw(state, &state->m_dvbt_pre_saw_cfg); if (status < 0) goto error; @@ -3649,10 +3620,10 @@ static int SetDVBTStandard(struct drxk_state *state, if (status < 0) goto error; - status = SetAgcRf(state, &state->m_dvbtRfAgcCfg, true); + status = set_agc_rf(state, &state->m_dvbt_rf_agc_cfg, true); if (status < 0) goto error; - status = SetAgcIf(state, &state->m_dvbtIfAgcCfg, true); + status = set_agc_if(state, &state->m_dvbt_if_agc_cfg, true); if (status < 0) goto error; @@ -3670,9 +3641,10 @@ static int SetDVBTStandard(struct drxk_state *state, if (status < 0) goto error; - if (!state->m_DRXK_A3_ROM_CODE) { - /* AGCInit() is not done for DVBT, so set agcFastClipCtrlDelay */ - status = write16(state, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A, state->m_dvbtIfAgcCfg.FastClipCtrlDelay); + if (!state->m_drxk_a3_rom_code) { + /* AGCInit() is not done for DVBT, so set agcfast_clip_ctrl_delay */ + status = write16(state, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A, + state->m_dvbt_if_agc_cfg.fast_clip_ctrl_delay); if (status < 0) goto error; } @@ -3707,41 +3679,43 @@ static int SetDVBTStandard(struct drxk_state *state, goto error; /* Setup MPEG bus */ - status = MPEGTSDtoSetup(state, OM_DVBT); + status = mpegts_dto_setup(state, OM_DVBT); if (status < 0) goto error; /* Set DVBT Presets */ - status = DVBTActivatePresets(state); + status = dvbt_activate_presets(state); if (status < 0) goto error; error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } /*============================================================================*/ /** -* \brief Start dvbt demodulating for channel. +* \brief start dvbt demodulating for channel. * \param demod instance of demodulator. * \return DRXStatus_t. */ -static int DVBTStart(struct drxk_state *state) +static int dvbt_start(struct drxk_state *state) { u16 param1; int status; - /* DRXKOfdmScCmd_t scCmd; */ + /* drxk_ofdm_sc_cmd_t scCmd; */ dprintk(1, "\n"); - /* Start correct processes to get in lock */ + /* start correct processes to get in lock */ /* DRXK: OFDM_SC_RA_RAM_PROC_LOCKTRACK is no longer in mapfile! */ param1 = OFDM_SC_RA_RAM_LOCKTRACK_MIN; - status = DVBTScCommand(state, OFDM_SC_RA_RAM_CMD_PROC_START, 0, OFDM_SC_RA_RAM_SW_EVENT_RUN_NMASK__M, param1, 0, 0, 0); + status = dvbt_sc_command(state, OFDM_SC_RA_RAM_CMD_PROC_START, 0, + OFDM_SC_RA_RAM_SW_EVENT_RUN_NMASK__M, param1, + 0, 0, 0); if (status < 0) goto error; - /* Start FEC OC */ - status = MPEGTSStart(state); + /* start FEC OC */ + status = mpegts_start(state); if (status < 0) goto error; status = write16(state, FEC_COMM_EXEC__A, FEC_COMM_EXEC_ACTIVE); @@ -3749,7 +3723,7 @@ static int DVBTStart(struct drxk_state *state) goto error; error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -3762,20 +3736,23 @@ error: * \return DRXStatus_t. * // original DVBTSetChannel() */ -static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz, - s32 tunerFreqOffset) +static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, + s32 tuner_freq_offset) { - u16 cmdResult = 0; - u16 transmissionParams = 0; - u16 operationMode = 0; - u32 iqmRcRateOfs = 0; + u16 cmd_result = 0; + u16 transmission_params = 0; + u16 operation_mode = 0; + u32 iqm_rc_rate_ofs = 0; u32 bandwidth = 0; u16 param1; int status; - dprintk(1, "IF =%d, TFO = %d\n", IntermediateFreqkHz, tunerFreqOffset); + dprintk(1, "IF =%d, TFO = %d\n", + intermediate_freqk_hz, tuner_freq_offset); - status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_STOP, 0, NULL, 1, &cmdResult); + status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM + | SCU_RAM_COMMAND_CMD_DEMOD_STOP, + 0, NULL, 1, &cmd_result); if (status < 0) goto error; @@ -3798,19 +3775,19 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz, if (status < 0) goto error; - /*== Write channel settings to device =====================================*/ + /*== Write channel settings to device ================================*/ /* mode */ switch (state->props.transmission_mode) { case TRANSMISSION_MODE_AUTO: default: - operationMode |= OFDM_SC_RA_RAM_OP_AUTO_MODE__M; + operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_MODE__M; /* fall through , try first guess DRX_FFTMODE_8K */ case TRANSMISSION_MODE_8K: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_MODE_8K; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_MODE_8K; break; case TRANSMISSION_MODE_2K: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_MODE_2K; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_MODE_2K; break; } @@ -3818,19 +3795,19 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz, switch (state->props.guard_interval) { default: case GUARD_INTERVAL_AUTO: - operationMode |= OFDM_SC_RA_RAM_OP_AUTO_GUARD__M; + operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_GUARD__M; /* fall through , try first guess DRX_GUARD_1DIV4 */ case GUARD_INTERVAL_1_4: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_4; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_4; break; case GUARD_INTERVAL_1_32: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_32; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_32; break; case GUARD_INTERVAL_1_16: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_16; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_16; break; case GUARD_INTERVAL_1_8: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_8; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_8; break; } @@ -3839,18 +3816,18 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz, case HIERARCHY_AUTO: case HIERARCHY_NONE: default: - operationMode |= OFDM_SC_RA_RAM_OP_AUTO_HIER__M; + operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_HIER__M; /* fall through , try first guess SC_RA_RAM_OP_PARAM_HIER_NO */ - /* transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_NO; */ + /* transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_HIER_NO; */ /* break; */ case HIERARCHY_1: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A1; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A1; break; case HIERARCHY_2: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A2; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A2; break; case HIERARCHY_4: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A4; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A4; break; } @@ -3859,16 +3836,16 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz, switch (state->props.modulation) { case QAM_AUTO: default: - operationMode |= OFDM_SC_RA_RAM_OP_AUTO_CONST__M; + operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_CONST__M; /* fall through , try first guess DRX_CONSTELLATION_QAM64 */ case QAM_64: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM64; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM64; break; case QPSK: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QPSK; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QPSK; break; case QAM_16: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM16; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM16; break; } #if 0 @@ -3876,13 +3853,13 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz, /* Priority (only for hierarchical channels) */ switch (channel->priority) { case DRX_PRIORITY_LOW: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_LO; - WR16(devAddr, OFDM_EC_SB_PRIOR__A, + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_LO; + WR16(dev_addr, OFDM_EC_SB_PRIOR__A, OFDM_EC_SB_PRIOR_LO); break; case DRX_PRIORITY_HIGH: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI; - WR16(devAddr, OFDM_EC_SB_PRIOR__A, + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI; + WR16(dev_addr, OFDM_EC_SB_PRIOR__A, OFDM_EC_SB_PRIOR_HI)); break; case DRX_PRIORITY_UNKNOWN: /* fall through */ @@ -3892,7 +3869,7 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz, } #else /* Set Priorty high */ - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI; status = write16(state, OFDM_EC_SB_PRIOR__A, OFDM_EC_SB_PRIOR_HI); if (status < 0) goto error; @@ -3902,90 +3879,111 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz, switch (state->props.code_rate_HP) { case FEC_AUTO: default: - operationMode |= OFDM_SC_RA_RAM_OP_AUTO_RATE__M; + operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_RATE__M; /* fall through , try first guess DRX_CODERATE_2DIV3 */ case FEC_2_3: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_2_3; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_2_3; break; case FEC_1_2: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_1_2; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_1_2; break; case FEC_3_4: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_3_4; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_3_4; break; case FEC_5_6: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_5_6; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_5_6; break; case FEC_7_8: - transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_7_8; + transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_7_8; break; } - /* SAW filter selection: normaly not necesarry, but if wanted - the application can select a SAW filter via the driver by using UIOs */ + /* + * SAW filter selection: normaly not necesarry, but if wanted + * the application can select a SAW filter via the driver by + * using UIOs + */ + /* First determine real bandwidth (Hz) */ /* Also set delay for impulse noise cruncher */ - /* Also set parameters for EC_OC fix, note EC_OC_REG_TMD_HIL_MAR is changed - by SC for fix for some 8K,1/8 guard but is restored by InitEC and ResetEC - functions */ + /* + * Also set parameters for EC_OC fix, note EC_OC_REG_TMD_HIL_MAR is + * changed by SC for fix for some 8K,1/8 guard but is restored by + * InitEC and ResetEC functions + */ switch (state->props.bandwidth_hz) { case 0: state->props.bandwidth_hz = 8000000; /* fall though */ case 8000000: bandwidth = DRXK_BANDWIDTH_8MHZ_IN_HZ; - status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, 3052); + status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, + 3052); if (status < 0) goto error; /* cochannel protection for PAL 8 MHz */ - status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, 7); + status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, + 7); if (status < 0) goto error; - status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, 7); + status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, + 7); if (status < 0) goto error; - status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, 7); + status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, + 7); if (status < 0) goto error; - status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, 1); + status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, + 1); if (status < 0) goto error; break; case 7000000: bandwidth = DRXK_BANDWIDTH_7MHZ_IN_HZ; - status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, 3491); + status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, + 3491); if (status < 0) goto error; /* cochannel protection for PAL 7 MHz */ - status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, 8); + status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, + 8); if (status < 0) goto error; - status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, 8); + status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, + 8); if (status < 0) goto error; - status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, 4); + status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, + 4); if (status < 0) goto error; - status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, 1); + status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, + 1); if (status < 0) goto error; break; case 6000000: bandwidth = DRXK_BANDWIDTH_6MHZ_IN_HZ; - status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, 4073); + status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, + 4073); if (status < 0) goto error; /* cochannel protection for NTSC 6 MHz */ - status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, 19); + status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, + 19); if (status < 0) goto error; - status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, 19); + status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, + 19); if (status < 0) goto error; - status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, 14); + status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, + 14); if (status < 0) goto error; - status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, 1); + status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, + 1); if (status < 0) goto error; break; @@ -3994,46 +3992,50 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz, goto error; } - if (iqmRcRateOfs == 0) { + if (iqm_rc_rate_ofs == 0) { /* Now compute IQM_RC_RATE_OFS (((SysFreq/BandWidth)/2)/2) -1) * 2^23) => ((SysFreq / BandWidth) * (2^21)) - (2^23) */ /* (SysFreq / BandWidth) * (2^28) */ - /* assert (MAX(sysClk)/MIN(bandwidth) < 16) - => assert(MAX(sysClk) < 16*MIN(bandwidth)) - => assert(109714272 > 48000000) = true so Frac 28 can be used */ - iqmRcRateOfs = Frac28a((u32) - ((state->m_sysClockFreq * + /* + * assert (MAX(sysClk)/MIN(bandwidth) < 16) + * => assert(MAX(sysClk) < 16*MIN(bandwidth)) + * => assert(109714272 > 48000000) = true + * so Frac 28 can be used + */ + iqm_rc_rate_ofs = Frac28a((u32) + ((state->m_sys_clock_freq * 1000) / 3), bandwidth); - /* (SysFreq / BandWidth) * (2^21), rounding before truncating */ - if ((iqmRcRateOfs & 0x7fL) >= 0x40) - iqmRcRateOfs += 0x80L; - iqmRcRateOfs = iqmRcRateOfs >> 7; + /* (SysFreq / BandWidth) * (2^21), rounding before truncating */ + if ((iqm_rc_rate_ofs & 0x7fL) >= 0x40) + iqm_rc_rate_ofs += 0x80L; + iqm_rc_rate_ofs = iqm_rc_rate_ofs >> 7; /* ((SysFreq / BandWidth) * (2^21)) - (2^23) */ - iqmRcRateOfs = iqmRcRateOfs - (1 << 23); + iqm_rc_rate_ofs = iqm_rc_rate_ofs - (1 << 23); } - iqmRcRateOfs &= + iqm_rc_rate_ofs &= ((((u32) IQM_RC_RATE_OFS_HI__M) << IQM_RC_RATE_OFS_LO__W) | IQM_RC_RATE_OFS_LO__M); - status = write32(state, IQM_RC_RATE_OFS_LO__A, iqmRcRateOfs); + status = write32(state, IQM_RC_RATE_OFS_LO__A, iqm_rc_rate_ofs); if (status < 0) goto error; /* Bandwidth setting done */ #if 0 - status = DVBTSetFrequencyShift(demod, channel, tunerOffset); + status = dvbt_set_frequency_shift(demod, channel, tuner_offset); if (status < 0) goto error; #endif - status = SetFrequencyShifter(state, IntermediateFreqkHz, tunerFreqOffset, true); + status = set_frequency_shifter(state, intermediate_freqk_hz, + tuner_freq_offset, true); if (status < 0) goto error; - /*== Start SC, write channel settings to SC ===============================*/ + /*== start SC, write channel settings to SC ==========================*/ /* Activate SCU to enable SCU commands */ status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE); @@ -4049,7 +4051,9 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz, goto error; - status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_START, 0, NULL, 1, &cmdResult); + status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM + | SCU_RAM_COMMAND_CMD_DEMOD_START, + 0, NULL, 1, &cmd_result); if (status < 0) goto error; @@ -4059,16 +4063,16 @@ static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz, OFDM_SC_RA_RAM_OP_AUTO_CONST__M | OFDM_SC_RA_RAM_OP_AUTO_HIER__M | OFDM_SC_RA_RAM_OP_AUTO_RATE__M); - status = DVBTScCommand(state, OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM, - 0, transmissionParams, param1, 0, 0, 0); + status = dvbt_sc_command(state, OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM, + 0, transmission_params, param1, 0, 0, 0); if (status < 0) goto error; - if (!state->m_DRXK_A3_ROM_CODE) - status = DVBTCtrlSetSqiSpeed(state, &state->m_sqiSpeed); + if (!state->m_drxk_a3_rom_code) + status = dvbt_ctrl_set_sqi_speed(state, &state->m_sqi_speed); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -4083,7 +4087,7 @@ error: * \return DRXStatus_t. * */ -static int GetDVBTLockStatus(struct drxk_state *state, u32 *pLockStatus) +static int get_dvbt_lock_status(struct drxk_state *state, u32 *p_lock_status) { int status; const u16 mpeg_lock_mask = (OFDM_SC_RA_RAM_LOCK_MPEG__M | @@ -4091,58 +4095,58 @@ static int GetDVBTLockStatus(struct drxk_state *state, u32 *pLockStatus) const u16 fec_lock_mask = (OFDM_SC_RA_RAM_LOCK_FEC__M); const u16 demod_lock_mask = OFDM_SC_RA_RAM_LOCK_DEMOD__M; - u16 ScRaRamLock = 0; - u16 ScCommExec = 0; + u16 sc_ra_ram_lock = 0; + u16 sc_comm_exec = 0; dprintk(1, "\n"); - *pLockStatus = NOT_LOCKED; + *p_lock_status = NOT_LOCKED; /* driver 0.9.0 */ /* Check if SC is running */ - status = read16(state, OFDM_SC_COMM_EXEC__A, &ScCommExec); + status = read16(state, OFDM_SC_COMM_EXEC__A, &sc_comm_exec); if (status < 0) goto end; - if (ScCommExec == OFDM_SC_COMM_EXEC_STOP) + if (sc_comm_exec == OFDM_SC_COMM_EXEC_STOP) goto end; - status = read16(state, OFDM_SC_RA_RAM_LOCK__A, &ScRaRamLock); + status = read16(state, OFDM_SC_RA_RAM_LOCK__A, &sc_ra_ram_lock); if (status < 0) goto end; - if ((ScRaRamLock & mpeg_lock_mask) == mpeg_lock_mask) - *pLockStatus = MPEG_LOCK; - else if ((ScRaRamLock & fec_lock_mask) == fec_lock_mask) - *pLockStatus = FEC_LOCK; - else if ((ScRaRamLock & demod_lock_mask) == demod_lock_mask) - *pLockStatus = DEMOD_LOCK; - else if (ScRaRamLock & OFDM_SC_RA_RAM_LOCK_NODVBT__M) - *pLockStatus = NEVER_LOCK; + if ((sc_ra_ram_lock & mpeg_lock_mask) == mpeg_lock_mask) + *p_lock_status = MPEG_LOCK; + else if ((sc_ra_ram_lock & fec_lock_mask) == fec_lock_mask) + *p_lock_status = FEC_LOCK; + else if ((sc_ra_ram_lock & demod_lock_mask) == demod_lock_mask) + *p_lock_status = DEMOD_LOCK; + else if (sc_ra_ram_lock & OFDM_SC_RA_RAM_LOCK_NODVBT__M) + *p_lock_status = NEVER_LOCK; end: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } -static int PowerUpQAM(struct drxk_state *state) +static int power_up_qam(struct drxk_state *state) { - enum DRXPowerMode powerMode = DRXK_POWER_DOWN_OFDM; + enum drx_power_mode power_mode = DRXK_POWER_DOWN_OFDM; int status; dprintk(1, "\n"); - status = CtrlPowerMode(state, &powerMode); + status = ctrl_power_mode(state, &power_mode); if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } /** Power Down QAM */ -static int PowerDownQAM(struct drxk_state *state) +static int power_down_qam(struct drxk_state *state) { u16 data = 0; - u16 cmdResult; + u16 cmd_result; int status = 0; dprintk(1, "\n"); @@ -4158,16 +4162,18 @@ static int PowerDownQAM(struct drxk_state *state) status = write16(state, QAM_COMM_EXEC__A, QAM_COMM_EXEC_STOP); if (status < 0) goto error; - status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_STOP, 0, NULL, 1, &cmdResult); + status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM + | SCU_RAM_COMMAND_CMD_DEMOD_STOP, + 0, NULL, 1, &cmd_result); if (status < 0) goto error; } /* powerdown AFE */ - status = SetIqmAf(state, false); + status = set_iqm_af(state, false); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -4185,20 +4191,20 @@ error: * The implementation does not check this. * */ -static int SetQAMMeasurement(struct drxk_state *state, - enum EDrxkConstellation modulation, - u32 symbolRate) +static int set_qam_measurement(struct drxk_state *state, + enum e_drxk_constellation modulation, + u32 symbol_rate) { - u32 fecBitsDesired = 0; /* BER accounting period */ - u32 fecRsPeriodTotal = 0; /* Total period */ - u16 fecRsPrescale = 0; /* ReedSolomon Measurement Prescale */ - u16 fecRsPeriod = 0; /* Value for corresponding I2C register */ + u32 fec_bits_desired = 0; /* BER accounting period */ + u32 fec_rs_period_total = 0; /* Total period */ + u16 fec_rs_prescale = 0; /* ReedSolomon Measurement Prescale */ + u16 fec_rs_period = 0; /* Value for corresponding I2C register */ int status = 0; dprintk(1, "\n"); - fecRsPrescale = 1; - /* fecBitsDesired = symbolRate [kHz] * + fec_rs_prescale = 1; + /* fec_bits_desired = symbol_rate [kHz] * FrameLenght [ms] * (modulation + 1) * SyncLoss (== 1) * @@ -4206,19 +4212,19 @@ static int SetQAMMeasurement(struct drxk_state *state, */ switch (modulation) { case DRX_CONSTELLATION_QAM16: - fecBitsDesired = 4 * symbolRate; + fec_bits_desired = 4 * symbol_rate; break; case DRX_CONSTELLATION_QAM32: - fecBitsDesired = 5 * symbolRate; + fec_bits_desired = 5 * symbol_rate; break; case DRX_CONSTELLATION_QAM64: - fecBitsDesired = 6 * symbolRate; + fec_bits_desired = 6 * symbol_rate; break; case DRX_CONSTELLATION_QAM128: - fecBitsDesired = 7 * symbolRate; + fec_bits_desired = 7 * symbol_rate; break; case DRX_CONSTELLATION_QAM256: - fecBitsDesired = 8 * symbolRate; + fec_bits_desired = 8 * symbol_rate; break; default: status = -EINVAL; @@ -4226,40 +4232,41 @@ static int SetQAMMeasurement(struct drxk_state *state, if (status < 0) goto error; - fecBitsDesired /= 1000; /* symbolRate [Hz] -> symbolRate [kHz] */ - fecBitsDesired *= 500; /* meas. period [ms] */ + fec_bits_desired /= 1000; /* symbol_rate [Hz] -> symbol_rate [kHz] */ + fec_bits_desired *= 500; /* meas. period [ms] */ /* Annex A/C: bits/RsPeriod = 204 * 8 = 1632 */ - /* fecRsPeriodTotal = fecBitsDesired / 1632 */ - fecRsPeriodTotal = (fecBitsDesired / 1632UL) + 1; /* roughly ceil */ + /* fec_rs_period_total = fec_bits_desired / 1632 */ + fec_rs_period_total = (fec_bits_desired / 1632UL) + 1; /* roughly ceil */ - /* fecRsPeriodTotal = fecRsPrescale * fecRsPeriod */ - fecRsPrescale = 1 + (u16) (fecRsPeriodTotal >> 16); - if (fecRsPrescale == 0) { + /* fec_rs_period_total = fec_rs_prescale * fec_rs_period */ + fec_rs_prescale = 1 + (u16) (fec_rs_period_total >> 16); + if (fec_rs_prescale == 0) { /* Divide by zero (though impossible) */ status = -EINVAL; if (status < 0) goto error; } - fecRsPeriod = - ((u16) fecRsPeriodTotal + - (fecRsPrescale >> 1)) / fecRsPrescale; + fec_rs_period = + ((u16) fec_rs_period_total + + (fec_rs_prescale >> 1)) / fec_rs_prescale; /* write corresponding registers */ - status = write16(state, FEC_RS_MEASUREMENT_PERIOD__A, fecRsPeriod); + status = write16(state, FEC_RS_MEASUREMENT_PERIOD__A, fec_rs_period); if (status < 0) goto error; - status = write16(state, FEC_RS_MEASUREMENT_PRESCALE__A, fecRsPrescale); + status = write16(state, FEC_RS_MEASUREMENT_PRESCALE__A, + fec_rs_prescale); if (status < 0) goto error; - status = write16(state, FEC_OC_SNC_FAIL_PERIOD__A, fecRsPeriod); + status = write16(state, FEC_OC_SNC_FAIL_PERIOD__A, fec_rs_period); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } -static int SetQAM16(struct drxk_state *state) +static int set_qam16(struct drxk_state *state) { int status = 0; @@ -4315,7 +4322,8 @@ static int SetQAM16(struct drxk_state *state) goto error; /* QAM Slicer Settings */ - status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM16); + status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, + DRXK_QAM_SL_SIG_POWER_QAM16); if (status < 0) goto error; @@ -4441,7 +4449,7 @@ static int SetQAM16(struct drxk_state *state) error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -4452,7 +4460,7 @@ error: * \param demod instance of demod. * \return DRXStatus_t. */ -static int SetQAM32(struct drxk_state *state) +static int set_qam32(struct drxk_state *state) { int status = 0; @@ -4511,7 +4519,8 @@ static int SetQAM32(struct drxk_state *state) /* QAM Slicer Settings */ - status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM32); + status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, + DRXK_QAM_SL_SIG_POWER_QAM32); if (status < 0) goto error; @@ -4636,7 +4645,7 @@ static int SetQAM32(struct drxk_state *state) status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -86); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -4647,7 +4656,7 @@ error: * \param demod instance of demod. * \return DRXStatus_t. */ -static int SetQAM64(struct drxk_state *state) +static int set_qam64(struct drxk_state *state) { int status = 0; @@ -4704,7 +4713,8 @@ static int SetQAM64(struct drxk_state *state) goto error; /* QAM Slicer Settings */ - status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM64); + status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, + DRXK_QAM_SL_SIG_POWER_QAM64); if (status < 0) goto error; @@ -4829,7 +4839,7 @@ static int SetQAM64(struct drxk_state *state) status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -80); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -4841,7 +4851,7 @@ error: * \param demod: instance of demod. * \return DRXStatus_t. */ -static int SetQAM128(struct drxk_state *state) +static int set_qam128(struct drxk_state *state) { int status = 0; @@ -4900,7 +4910,8 @@ static int SetQAM128(struct drxk_state *state) /* QAM Slicer Settings */ - status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM128); + status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, + DRXK_QAM_SL_SIG_POWER_QAM128); if (status < 0) goto error; @@ -5025,7 +5036,7 @@ static int SetQAM128(struct drxk_state *state) status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -23); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -5037,7 +5048,7 @@ error: * \param demod: instance of demod. * \return DRXStatus_t. */ -static int SetQAM256(struct drxk_state *state) +static int set_qam256(struct drxk_state *state) { int status = 0; @@ -5095,7 +5106,8 @@ static int SetQAM256(struct drxk_state *state) /* QAM Slicer Settings */ - status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM256); + status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, + DRXK_QAM_SL_SIG_POWER_QAM256); if (status < 0) goto error; @@ -5220,7 +5232,7 @@ static int SetQAM256(struct drxk_state *state) status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -8); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -5232,10 +5244,10 @@ error: * \param channel: pointer to channel data. * \return DRXStatus_t. */ -static int QAMResetQAM(struct drxk_state *state) +static int qam_reset_qam(struct drxk_state *state) { int status; - u16 cmdResult; + u16 cmd_result; dprintk(1, "\n"); /* Stop QAM comstate->m_exec */ @@ -5243,10 +5255,12 @@ static int QAMResetQAM(struct drxk_state *state) if (status < 0) goto error; - status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_RESET, 0, NULL, 1, &cmdResult); + status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM + | SCU_RAM_COMMAND_CMD_DEMOD_RESET, + 0, NULL, 1, &cmd_result); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -5258,18 +5272,18 @@ error: * \param channel: pointer to channel data. * \return DRXStatus_t. */ -static int QAMSetSymbolrate(struct drxk_state *state) +static int qam_set_symbolrate(struct drxk_state *state) { - u32 adcFrequency = 0; - u32 symbFreq = 0; - u32 iqmRcRate = 0; + u32 adc_frequency = 0; + u32 symb_freq = 0; + u32 iqm_rc_rate = 0; u16 ratesel = 0; - u32 lcSymbRate = 0; + u32 lc_symb_rate = 0; int status; dprintk(1, "\n"); /* Select & calculate correct IQM rate */ - adcFrequency = (state->m_sysClockFreq * 1000) / 3; + adc_frequency = (state->m_sys_clock_freq * 1000) / 3; ratesel = 0; /* printk(KERN_DEBUG "drxk: SR %d\n", state->props.symbol_rate); */ if (state->props.symbol_rate <= 1188750) @@ -5285,38 +5299,38 @@ static int QAMSetSymbolrate(struct drxk_state *state) /* IqmRcRate = ((Fadc / (symbolrate * (4<<ratesel))) - 1) * (1<<23) */ - symbFreq = state->props.symbol_rate * (1 << ratesel); - if (symbFreq == 0) { + symb_freq = state->props.symbol_rate * (1 << ratesel); + if (symb_freq == 0) { /* Divide by zero */ status = -EINVAL; goto error; } - iqmRcRate = (adcFrequency / symbFreq) * (1 << 21) + - (Frac28a((adcFrequency % symbFreq), symbFreq) >> 7) - + iqm_rc_rate = (adc_frequency / symb_freq) * (1 << 21) + + (Frac28a((adc_frequency % symb_freq), symb_freq) >> 7) - (1 << 23); - status = write32(state, IQM_RC_RATE_OFS_LO__A, iqmRcRate); + status = write32(state, IQM_RC_RATE_OFS_LO__A, iqm_rc_rate); if (status < 0) goto error; - state->m_iqmRcRate = iqmRcRate; + state->m_iqm_rc_rate = iqm_rc_rate; /* - LcSymbFreq = round (.125 * symbolrate / adcFreq * (1<<15)) + LcSymbFreq = round (.125 * symbolrate / adc_freq * (1<<15)) */ - symbFreq = state->props.symbol_rate; - if (adcFrequency == 0) { + symb_freq = state->props.symbol_rate; + if (adc_frequency == 0) { /* Divide by zero */ status = -EINVAL; goto error; } - lcSymbRate = (symbFreq / adcFrequency) * (1 << 12) + - (Frac28a((symbFreq % adcFrequency), adcFrequency) >> + lc_symb_rate = (symb_freq / adc_frequency) * (1 << 12) + + (Frac28a((symb_freq % adc_frequency), adc_frequency) >> 16); - if (lcSymbRate > 511) - lcSymbRate = 511; - status = write16(state, QAM_LC_SYMBOL_FREQ__A, (u16) lcSymbRate); + if (lc_symb_rate > 511) + lc_symb_rate = 511; + status = write16(state, QAM_LC_SYMBOL_FREQ__A, (u16) lc_symb_rate); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -5329,34 +5343,36 @@ error: * \return DRXStatus_t. */ -static int GetQAMLockStatus(struct drxk_state *state, u32 *pLockStatus) +static int get_qam_lock_status(struct drxk_state *state, u32 *p_lock_status) { int status; - u16 Result[2] = { 0, 0 }; + u16 result[2] = { 0, 0 }; dprintk(1, "\n"); - *pLockStatus = NOT_LOCKED; + *p_lock_status = NOT_LOCKED; status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK, 0, NULL, 2, - Result); + result); if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); - if (Result[1] < SCU_RAM_QAM_LOCKED_LOCKED_DEMOD_LOCKED) { + if (result[1] < SCU_RAM_QAM_LOCKED_LOCKED_DEMOD_LOCKED) { /* 0x0000 NOT LOCKED */ - } else if (Result[1] < SCU_RAM_QAM_LOCKED_LOCKED_LOCKED) { + } else if (result[1] < SCU_RAM_QAM_LOCKED_LOCKED_LOCKED) { /* 0x4000 DEMOD LOCKED */ - *pLockStatus = DEMOD_LOCK; - } else if (Result[1] < SCU_RAM_QAM_LOCKED_LOCKED_NEVER_LOCK) { + *p_lock_status = DEMOD_LOCK; + } else if (result[1] < SCU_RAM_QAM_LOCKED_LOCKED_NEVER_LOCK) { /* 0x8000 DEMOD + FEC LOCKED (system lock) */ - *pLockStatus = MPEG_LOCK; + *p_lock_status = MPEG_LOCK; } else { /* 0xC000 NEVER LOCKED */ /* (system will never be able to lock to the signal) */ - /* TODO: check this, intermediate & standard specific lock states are not - taken into account here */ - *pLockStatus = NEVER_LOCK; + /* + * TODO: check this, intermediate & standard specific lock + * states are not taken into account here + */ + *p_lock_status = NEVER_LOCK; } return status; } @@ -5368,68 +5384,70 @@ static int GetQAMLockStatus(struct drxk_state *state, u32 *pLockStatus) #define QAM_LOCKRANGE__M 0x10 #define QAM_LOCKRANGE_NORMAL 0x10 -static int QAMDemodulatorCommand(struct drxk_state *state, - int numberOfParameters) +static int qam_demodulator_command(struct drxk_state *state, + int number_of_parameters) { int status; - u16 cmdResult; - u16 setParamParameters[4] = { 0, 0, 0, 0 }; + u16 cmd_result; + u16 set_param_parameters[4] = { 0, 0, 0, 0 }; - setParamParameters[0] = state->m_Constellation; /* modulation */ - setParamParameters[1] = DRXK_QAM_I12_J17; /* interleave mode */ + set_param_parameters[0] = state->m_constellation; /* modulation */ + set_param_parameters[1] = DRXK_QAM_I12_J17; /* interleave mode */ - if (numberOfParameters == 2) { - u16 setEnvParameters[1] = { 0 }; + if (number_of_parameters == 2) { + u16 set_env_parameters[1] = { 0 }; - if (state->m_OperationMode == OM_QAM_ITU_C) - setEnvParameters[0] = QAM_TOP_ANNEX_C; + if (state->m_operation_mode == OM_QAM_ITU_C) + set_env_parameters[0] = QAM_TOP_ANNEX_C; else - setEnvParameters[0] = QAM_TOP_ANNEX_A; + set_env_parameters[0] = QAM_TOP_ANNEX_A; status = scu_command(state, - SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV, - 1, setEnvParameters, 1, &cmdResult); + SCU_RAM_COMMAND_STANDARD_QAM + | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV, + 1, set_env_parameters, 1, &cmd_result); if (status < 0) goto error; status = scu_command(state, - SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM, - numberOfParameters, setParamParameters, - 1, &cmdResult); - } else if (numberOfParameters == 4) { - if (state->m_OperationMode == OM_QAM_ITU_C) - setParamParameters[2] = QAM_TOP_ANNEX_C; + SCU_RAM_COMMAND_STANDARD_QAM + | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM, + number_of_parameters, set_param_parameters, + 1, &cmd_result); + } else if (number_of_parameters == 4) { + if (state->m_operation_mode == OM_QAM_ITU_C) + set_param_parameters[2] = QAM_TOP_ANNEX_C; else - setParamParameters[2] = QAM_TOP_ANNEX_A; + set_param_parameters[2] = QAM_TOP_ANNEX_A; - setParamParameters[3] |= (QAM_MIRROR_AUTO_ON); + set_param_parameters[3] |= (QAM_MIRROR_AUTO_ON); /* Env parameters */ /* check for LOCKRANGE Extented */ - /* setParamParameters[3] |= QAM_LOCKRANGE_NORMAL; */ + /* set_param_parameters[3] |= QAM_LOCKRANGE_NORMAL; */ status = scu_command(state, - SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM, - numberOfParameters, setParamParameters, - 1, &cmdResult); + SCU_RAM_COMMAND_STANDARD_QAM + | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM, + number_of_parameters, set_param_parameters, + 1, &cmd_result); } else { - printk(KERN_WARNING "drxk: Unknown QAM demodulator parameter " - "count %d\n", numberOfParameters); + pr_warn("Unknown QAM demodulator parameter count %d\n", + number_of_parameters); status = -EINVAL; } error: if (status < 0) - printk(KERN_WARNING "drxk: Warning %d on %s\n", - status, __func__); + pr_warn("Warning %d on %s\n", status, __func__); return status; } -static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz, - s32 tunerFreqOffset) +static int set_qam(struct drxk_state *state, u16 intermediate_freqk_hz, + s32 tuner_freq_offset) { int status; - u16 cmdResult; - int qamDemodParamCount = state->qam_demod_parameter_count; + u16 cmd_result; + int qam_demod_param_count = state->qam_demod_parameter_count; dprintk(1, "\n"); /* @@ -5444,7 +5462,7 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz, status = write16(state, FEC_RS_COMM_EXEC__A, FEC_RS_COMM_EXEC_STOP); if (status < 0) goto error; - status = QAMResetQAM(state); + status = qam_reset_qam(state); if (status < 0) goto error; @@ -5453,27 +5471,27 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz, * -set params; resets IQM,QAM,FEC HW; initializes some * SCU variables */ - status = QAMSetSymbolrate(state); + status = qam_set_symbolrate(state); if (status < 0) goto error; /* Set params */ switch (state->props.modulation) { case QAM_256: - state->m_Constellation = DRX_CONSTELLATION_QAM256; + state->m_constellation = DRX_CONSTELLATION_QAM256; break; case QAM_AUTO: case QAM_64: - state->m_Constellation = DRX_CONSTELLATION_QAM64; + state->m_constellation = DRX_CONSTELLATION_QAM64; break; case QAM_16: - state->m_Constellation = DRX_CONSTELLATION_QAM16; + state->m_constellation = DRX_CONSTELLATION_QAM16; break; case QAM_32: - state->m_Constellation = DRX_CONSTELLATION_QAM32; + state->m_constellation = DRX_CONSTELLATION_QAM32; break; case QAM_128: - state->m_Constellation = DRX_CONSTELLATION_QAM128; + state->m_constellation = DRX_CONSTELLATION_QAM128; break; default: status = -EINVAL; @@ -5486,8 +5504,8 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz, * the correct command. */ if (state->qam_demod_parameter_count == 4 || !state->qam_demod_parameter_count) { - qamDemodParamCount = 4; - status = QAMDemodulatorCommand(state, qamDemodParamCount); + qam_demod_param_count = 4; + status = qam_demodulator_command(state, qam_demod_param_count); } /* Use the 2-parameter command if it was requested or if we're @@ -5495,27 +5513,27 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz, * failed. */ if (state->qam_demod_parameter_count == 2 || (!state->qam_demod_parameter_count && status < 0)) { - qamDemodParamCount = 2; - status = QAMDemodulatorCommand(state, qamDemodParamCount); + qam_demod_param_count = 2; + status = qam_demodulator_command(state, qam_demod_param_count); } if (status < 0) { - dprintk(1, "Could not set demodulator parameters. Make " - "sure qam_demod_parameter_count (%d) is correct for " - "your firmware (%s).\n", + dprintk(1, "Could not set demodulator parameters.\n"); + dprintk(1, + "Make sure qam_demod_parameter_count (%d) is correct for your firmware (%s).\n", state->qam_demod_parameter_count, state->microcode_name); goto error; } else if (!state->qam_demod_parameter_count) { - dprintk(1, "Auto-probing the correct QAM demodulator command " - "parameters was successful - using %d parameters.\n", - qamDemodParamCount); + dprintk(1, + "Auto-probing the QAM command parameters was successful - using %d parameters.\n", + qam_demod_param_count); /* * One of our commands was successful. We don't need to * auto-probe anymore, now that we got the correct command. */ - state->qam_demod_parameter_count = qamDemodParamCount; + state->qam_demod_parameter_count = qam_demod_param_count; } /* @@ -5523,16 +5541,18 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz, * signal setup modulation independent registers */ #if 0 - status = SetFrequency(channel, tunerFreqOffset)); + status = set_frequency(channel, tuner_freq_offset)); if (status < 0) goto error; #endif - status = SetFrequencyShifter(state, IntermediateFreqkHz, tunerFreqOffset, true); + status = set_frequency_shifter(state, intermediate_freqk_hz, + tuner_freq_offset, true); if (status < 0) goto error; /* Setup BER measurement */ - status = SetQAMMeasurement(state, state->m_Constellation, state->props.symbol_rate); + status = set_qam_measurement(state, state->m_constellation, + state->props.symbol_rate); if (status < 0) goto error; @@ -5605,7 +5625,8 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz, goto error; /* Mirroring, QAM-block starting point not inverted */ - status = write16(state, QAM_SY_SP_INV__A, QAM_SY_SP_INV_SPECTRUM_INV_DIS); + status = write16(state, QAM_SY_SP_INV__A, + QAM_SY_SP_INV_SPECTRUM_INV_DIS); if (status < 0) goto error; @@ -5617,20 +5638,20 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz, /* STEP 4: modulation specific setup */ switch (state->props.modulation) { case QAM_16: - status = SetQAM16(state); + status = set_qam16(state); break; case QAM_32: - status = SetQAM32(state); + status = set_qam32(state); break; case QAM_AUTO: case QAM_64: - status = SetQAM64(state); + status = set_qam64(state); break; case QAM_128: - status = SetQAM128(state); + status = set_qam128(state); break; case QAM_256: - status = SetQAM256(state); + status = set_qam256(state); break; default: status = -EINVAL; @@ -5647,12 +5668,12 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz, /* Re-configure MPEG output, requires knowledge of channel bitrate */ /* extAttr->currentChannel.modulation = channel->modulation; */ /* extAttr->currentChannel.symbolrate = channel->symbolrate; */ - status = MPEGTSDtoSetup(state, state->m_OperationMode); + status = mpegts_dto_setup(state, state->m_operation_mode); if (status < 0) goto error; - /* Start processes */ - status = MPEGTSStart(state); + /* start processes */ + status = mpegts_start(state); if (status < 0) goto error; status = write16(state, FEC_COMM_EXEC__A, FEC_COMM_EXEC_ACTIVE); @@ -5666,7 +5687,9 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz, goto error; /* STEP 5: start QAM demodulator (starts FEC, QAM and IQM HW) */ - status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_START, 0, NULL, 1, &cmdResult); + status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM + | SCU_RAM_COMMAND_CMD_DEMOD_START, + 0, NULL, 1, &cmd_result); if (status < 0) goto error; @@ -5675,12 +5698,12 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz, error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } -static int SetQAMStandard(struct drxk_state *state, - enum OperationMode oMode) +static int set_qam_standard(struct drxk_state *state, + enum operation_mode o_mode) { int status; #ifdef DRXK_QAM_TAPS @@ -5692,14 +5715,14 @@ static int SetQAMStandard(struct drxk_state *state, dprintk(1, "\n"); /* added antenna switch */ - SwitchAntennaToQAM(state); + switch_antenna_to_qam(state); /* Ensure correct power-up mode */ - status = PowerUpQAM(state); + status = power_up_qam(state); if (status < 0) goto error; /* Reset QAM block */ - status = QAMResetQAM(state); + status = qam_reset_qam(state); if (status < 0) goto error; @@ -5714,15 +5737,24 @@ static int SetQAMStandard(struct drxk_state *state, /* Upload IQM Channel Filter settings by boot loader from ROM table */ - switch (oMode) { + switch (o_mode) { case OM_QAM_ITU_A: - status = BLChainCmd(state, DRXK_BL_ROM_OFFSET_TAPS_ITU_A, DRXK_BLCC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT); + status = bl_chain_cmd(state, DRXK_BL_ROM_OFFSET_TAPS_ITU_A, + DRXK_BLCC_NR_ELEMENTS_TAPS, + DRXK_BLC_TIMEOUT); break; case OM_QAM_ITU_C: - status = BLDirectCmd(state, IQM_CF_TAP_RE0__A, DRXK_BL_ROM_OFFSET_TAPS_ITU_C, DRXK_BLDC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT); + status = bl_direct_cmd(state, IQM_CF_TAP_RE0__A, + DRXK_BL_ROM_OFFSET_TAPS_ITU_C, + DRXK_BLDC_NR_ELEMENTS_TAPS, + DRXK_BLC_TIMEOUT); if (status < 0) goto error; - status = BLDirectCmd(state, IQM_CF_TAP_IM0__A, DRXK_BL_ROM_OFFSET_TAPS_ITU_C, DRXK_BLDC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT); + status = bl_direct_cmd(state, + IQM_CF_TAP_IM0__A, + DRXK_BL_ROM_OFFSET_TAPS_ITU_C, + DRXK_BLDC_NR_ELEMENTS_TAPS, + DRXK_BLC_TIMEOUT); break; default: status = -EINVAL; @@ -5730,13 +5762,14 @@ static int SetQAMStandard(struct drxk_state *state, if (status < 0) goto error; - status = write16(state, IQM_CF_OUT_ENA__A, (1 << IQM_CF_OUT_ENA_QAM__B)); + status = write16(state, IQM_CF_OUT_ENA__A, 1 << IQM_CF_OUT_ENA_QAM__B); if (status < 0) goto error; status = write16(state, IQM_CF_SYMMETRIC__A, 0); if (status < 0) goto error; - status = write16(state, IQM_CF_MIDTAP__A, ((1 << IQM_CF_MIDTAP_RE__B) | (1 << IQM_CF_MIDTAP_IM__B))); + status = write16(state, IQM_CF_MIDTAP__A, + ((1 << IQM_CF_MIDTAP_RE__B) | (1 << IQM_CF_MIDTAP_IM__B))); if (status < 0) goto error; @@ -5793,7 +5826,7 @@ static int SetQAMStandard(struct drxk_state *state, goto error; /* turn on IQMAF. Must be done before setAgc**() */ - status = SetIqmAf(state, true); + status = set_iqm_af(state, true); if (status < 0) goto error; status = write16(state, IQM_AF_START_LOCK__A, 0x01); @@ -5801,7 +5834,7 @@ static int SetQAMStandard(struct drxk_state *state, goto error; /* IQM will not be reset from here, sync ADC and update/init AGC */ - status = ADCSynchronization(state); + status = adc_synchronization(state); if (status < 0) goto error; @@ -5818,18 +5851,18 @@ static int SetQAMStandard(struct drxk_state *state, /* No more resets of the IQM, current standard correctly set => now AGCs can be configured. */ - status = InitAGC(state, true); + status = init_agc(state, true); if (status < 0) goto error; - status = SetPreSaw(state, &(state->m_qamPreSawCfg)); + status = set_pre_saw(state, &(state->m_qam_pre_saw_cfg)); if (status < 0) goto error; /* Configure AGC's */ - status = SetAgcRf(state, &(state->m_qamRfAgcCfg), true); + status = set_agc_rf(state, &(state->m_qam_rf_agc_cfg), true); if (status < 0) goto error; - status = SetAgcIf(state, &(state->m_qamIfAgcCfg), true); + status = set_agc_if(state, &(state->m_qam_if_agc_cfg), true); if (status < 0) goto error; @@ -5837,18 +5870,19 @@ static int SetQAMStandard(struct drxk_state *state, status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } -static int WriteGPIO(struct drxk_state *state) +static int write_gpio(struct drxk_state *state) { int status; u16 value = 0; dprintk(1, "\n"); /* stop lock indicator process */ - status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); + status = write16(state, SCU_RAM_GPIO__A, + SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); if (status < 0) goto error; @@ -5857,10 +5891,11 @@ static int WriteGPIO(struct drxk_state *state) if (status < 0) goto error; - if (state->m_hasSAWSW) { - if (state->UIO_mask & 0x0001) { /* UIO-1 */ + if (state->m_has_sawsw) { + if (state->uio_mask & 0x0001) { /* UIO-1 */ /* write to io pad configuration register - output mode */ - status = write16(state, SIO_PDR_SMA_TX_CFG__A, state->m_GPIOCfg); + status = write16(state, SIO_PDR_SMA_TX_CFG__A, + state->m_gpio_cfg); if (status < 0) goto error; @@ -5868,7 +5903,7 @@ static int WriteGPIO(struct drxk_state *state) status = read16(state, SIO_PDR_UIO_OUT_LO__A, &value); if (status < 0) goto error; - if ((state->m_GPIO & 0x0001) == 0) + if ((state->m_gpio & 0x0001) == 0) value &= 0x7FFF; /* write zero to 15th bit - 1st UIO */ else value |= 0x8000; /* write one to 15th bit - 1st UIO */ @@ -5877,9 +5912,10 @@ static int WriteGPIO(struct drxk_state *state) if (status < 0) goto error; } - if (state->UIO_mask & 0x0002) { /* UIO-2 */ + if (state->uio_mask & 0x0002) { /* UIO-2 */ /* write to io pad configuration register - output mode */ - status = write16(state, SIO_PDR_SMA_RX_CFG__A, state->m_GPIOCfg); + status = write16(state, SIO_PDR_SMA_RX_CFG__A, + state->m_gpio_cfg); if (status < 0) goto error; @@ -5887,7 +5923,7 @@ static int WriteGPIO(struct drxk_state *state) status = read16(state, SIO_PDR_UIO_OUT_LO__A, &value); if (status < 0) goto error; - if ((state->m_GPIO & 0x0002) == 0) + if ((state->m_gpio & 0x0002) == 0) value &= 0xBFFF; /* write zero to 14th bit - 2st UIO */ else value |= 0x4000; /* write one to 14th bit - 2st UIO */ @@ -5896,9 +5932,10 @@ static int WriteGPIO(struct drxk_state *state) if (status < 0) goto error; } - if (state->UIO_mask & 0x0004) { /* UIO-3 */ + if (state->uio_mask & 0x0004) { /* UIO-3 */ /* write to io pad configuration register - output mode */ - status = write16(state, SIO_PDR_GPIO_CFG__A, state->m_GPIOCfg); + status = write16(state, SIO_PDR_GPIO_CFG__A, + state->m_gpio_cfg); if (status < 0) goto error; @@ -5906,7 +5943,7 @@ static int WriteGPIO(struct drxk_state *state) status = read16(state, SIO_PDR_UIO_OUT_LO__A, &value); if (status < 0) goto error; - if ((state->m_GPIO & 0x0004) == 0) + if ((state->m_gpio & 0x0004) == 0) value &= 0xFFFB; /* write zero to 2nd bit - 3rd UIO */ else value |= 0x0004; /* write one to 2nd bit - 3rd UIO */ @@ -5920,11 +5957,11 @@ static int WriteGPIO(struct drxk_state *state) status = write16(state, SIO_TOP_COMM_KEY__A, 0x0000); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } -static int SwitchAntennaToQAM(struct drxk_state *state) +static int switch_antenna_to_qam(struct drxk_state *state) { int status = 0; bool gpio_state; @@ -5934,22 +5971,22 @@ static int SwitchAntennaToQAM(struct drxk_state *state) if (!state->antenna_gpio) return 0; - gpio_state = state->m_GPIO & state->antenna_gpio; + gpio_state = state->m_gpio & state->antenna_gpio; if (state->antenna_dvbt ^ gpio_state) { /* Antenna is on DVB-T mode. Switch */ if (state->antenna_dvbt) - state->m_GPIO &= ~state->antenna_gpio; + state->m_gpio &= ~state->antenna_gpio; else - state->m_GPIO |= state->antenna_gpio; - status = WriteGPIO(state); + state->m_gpio |= state->antenna_gpio; + status = write_gpio(state); } if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } -static int SwitchAntennaToDVBT(struct drxk_state *state) +static int switch_antenna_to_dvbt(struct drxk_state *state) { int status = 0; bool gpio_state; @@ -5959,23 +5996,23 @@ static int SwitchAntennaToDVBT(struct drxk_state *state) if (!state->antenna_gpio) return 0; - gpio_state = state->m_GPIO & state->antenna_gpio; + gpio_state = state->m_gpio & state->antenna_gpio; if (!(state->antenna_dvbt ^ gpio_state)) { /* Antenna is on DVB-C mode. Switch */ if (state->antenna_dvbt) - state->m_GPIO |= state->antenna_gpio; + state->m_gpio |= state->antenna_gpio; else - state->m_GPIO &= ~state->antenna_gpio; - status = WriteGPIO(state); + state->m_gpio &= ~state->antenna_gpio; + status = write_gpio(state); } if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } -static int PowerDownDevice(struct drxk_state *state) +static int power_down_device(struct drxk_state *state) { /* Power down to requested mode */ /* Backup some register settings */ @@ -5986,28 +6023,29 @@ static int PowerDownDevice(struct drxk_state *state) int status; dprintk(1, "\n"); - if (state->m_bPDownOpenBridge) { + if (state->m_b_p_down_open_bridge) { /* Open I2C bridge before power down of DRXK */ status = ConfigureI2CBridge(state, true); if (status < 0) goto error; } /* driver 0.9.0 */ - status = DVBTEnableOFDMTokenRing(state, false); + status = dvbt_enable_ofdm_token_ring(state, false); if (status < 0) goto error; - status = write16(state, SIO_CC_PWD_MODE__A, SIO_CC_PWD_MODE_LEVEL_CLOCK); + status = write16(state, SIO_CC_PWD_MODE__A, + SIO_CC_PWD_MODE_LEVEL_CLOCK); if (status < 0) goto error; status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY); if (status < 0) goto error; - state->m_HICfgCtrl |= SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ; - status = HI_CfgCommand(state); + state->m_hi_cfg_ctrl |= SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ; + status = hi_cfg_command(state); error: if (status < 0) - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); return status; } @@ -6015,50 +6053,56 @@ error: static int init_drxk(struct drxk_state *state) { int status = 0, n = 0; - enum DRXPowerMode powerMode = DRXK_POWER_DOWN_OFDM; - u16 driverVersion; + enum drx_power_mode power_mode = DRXK_POWER_DOWN_OFDM; + u16 driver_version; dprintk(1, "\n"); - if ((state->m_DrxkState == DRXK_UNINITIALIZED)) { + if ((state->m_drxk_state == DRXK_UNINITIALIZED)) { drxk_i2c_lock(state); - status = PowerUpDevice(state); + status = power_up_device(state); if (status < 0) goto error; - status = DRXX_Open(state); + status = drxx_open(state); if (status < 0) goto error; /* Soft reset of OFDM-, sys- and osc-clockdomain */ - status = write16(state, SIO_CC_SOFT_RST__A, SIO_CC_SOFT_RST_OFDM__M | SIO_CC_SOFT_RST_SYS__M | SIO_CC_SOFT_RST_OSC__M); + status = write16(state, SIO_CC_SOFT_RST__A, + SIO_CC_SOFT_RST_OFDM__M + | SIO_CC_SOFT_RST_SYS__M + | SIO_CC_SOFT_RST_OSC__M); if (status < 0) goto error; status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY); if (status < 0) goto error; - /* TODO is this needed, if yes how much delay in worst case scenario */ - msleep(1); - state->m_DRXK_A3_PATCH_CODE = true; - status = GetDeviceCapabilities(state); + /* + * TODO is this needed? If yes, how much delay in + * worst case scenario + */ + usleep_range(1000, 2000); + state->m_drxk_a3_patch_code = true; + status = get_device_capabilities(state); if (status < 0) goto error; /* Bridge delay, uses oscilator clock */ /* Delay = (delay (nano seconds) * oscclk (kHz))/ 1000 */ /* SDA brdige delay */ - state->m_HICfgBridgeDelay = - (u16) ((state->m_oscClockFreq / 1000) * + state->m_hi_cfg_bridge_delay = + (u16) ((state->m_osc_clock_freq / 1000) * HI_I2C_BRIDGE_DELAY) / 1000; /* Clipping */ - if (state->m_HICfgBridgeDelay > + if (state->m_hi_cfg_bridge_delay > SIO_HI_RA_RAM_PAR_3_CFG_DBL_SDA__M) { - state->m_HICfgBridgeDelay = + state->m_hi_cfg_bridge_delay = SIO_HI_RA_RAM_PAR_3_CFG_DBL_SDA__M; } /* SCL bridge delay, same as SDA for now */ - state->m_HICfgBridgeDelay += - state->m_HICfgBridgeDelay << + state->m_hi_cfg_bridge_delay += + state->m_hi_cfg_bridge_delay << SIO_HI_RA_RAM_PAR_3_CFG_DBL_SCL__B; - status = InitHI(state); + status = init_hi(state); if (status < 0) goto error; /* disable various processes */ @@ -6067,13 +6111,14 @@ static int init_drxk(struct drxk_state *state) && !(state->m_DRXK_A2_ROM_CODE)) #endif { - status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); + status = write16(state, SCU_RAM_GPIO__A, + SCU_RAM_GPIO_HW_LOCK_IND_DISABLE); if (status < 0) goto error; } /* disable MPEG port */ - status = MPEGTSDisable(state); + status = mpegts_disable(state); if (status < 0) goto error; @@ -6086,27 +6131,30 @@ static int init_drxk(struct drxk_state *state) goto error; /* enable token-ring bus through OFDM block for possible ucode upload */ - status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, SIO_OFDM_SH_OFDM_RING_ENABLE_ON); + status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, + SIO_OFDM_SH_OFDM_RING_ENABLE_ON); if (status < 0) goto error; /* include boot loader section */ - status = write16(state, SIO_BL_COMM_EXEC__A, SIO_BL_COMM_EXEC_ACTIVE); + status = write16(state, SIO_BL_COMM_EXEC__A, + SIO_BL_COMM_EXEC_ACTIVE); if (status < 0) goto error; - status = BLChainCmd(state, 0, 6, 100); + status = bl_chain_cmd(state, 0, 6, 100); if (status < 0) goto error; if (state->fw) { - status = DownloadMicrocode(state, state->fw->data, + status = download_microcode(state, state->fw->data, state->fw->size); if (status < 0) goto error; } /* disable token-ring bus through OFDM block for possible ucode upload */ - status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, SIO_OFDM_SH_OFDM_RING_ENABLE_OFF); + status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, + SIO_OFDM_SH_OFDM_RING_ENABLE_OFF); if (status < 0) goto error; @@ -6114,14 +6162,14 @@ static int init_drxk(struct drxk_state *state) status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE); if (status < 0) goto error; - status = DRXX_Open(state); + status = drxx_open(state); if (status < 0) goto error; /* added for test */ msleep(30); - powerMode = DRXK_POWER_DOWN_OFDM; - status = CtrlPowerMode(state, &powerMode); + power_mode = DRXK_POWER_DOWN_OFDM; + status = ctrl_power_mode(state, &power_mode); if (status < 0) goto error; @@ -6131,33 +6179,38 @@ static int init_drxk(struct drxk_state *state) Not using SCU command interface for SCU register access since no microcode may be present. */ - driverVersion = + driver_version = (((DRXK_VERSION_MAJOR / 100) % 10) << 12) + (((DRXK_VERSION_MAJOR / 10) % 10) << 8) + ((DRXK_VERSION_MAJOR % 10) << 4) + (DRXK_VERSION_MINOR % 10); - status = write16(state, SCU_RAM_DRIVER_VER_HI__A, driverVersion); + status = write16(state, SCU_RAM_DRIVER_VER_HI__A, + driver_version); if (status < 0) goto error; - driverVersion = + driver_version = (((DRXK_VERSION_PATCH / 1000) % 10) << 12) + (((DRXK_VERSION_PATCH / 100) % 10) << 8) + (((DRXK_VERSION_PATCH / 10) % 10) << 4) + (DRXK_VERSION_PATCH % 10); - status = write16(state, SCU_RAM_DRIVER_VER_LO__A, driverVersion); + status = write16(state, SCU_RAM_DRIVER_VER_LO__A, + driver_version); if (status < 0) goto error; - printk(KERN_INFO "DRXK driver version %d.%d.%d\n", + pr_info("DRXK driver version %d.%d.%d\n", DRXK_VERSION_MAJOR, DRXK_VERSION_MINOR, DRXK_VERSION_PATCH); - /* Dirty fix of default values for ROM/PATCH microcode - Dirty because this fix makes it impossible to setup suitable values - before calling DRX_Open. This solution requires changes to RF AGC speed - to be done via the CTRL function after calling DRX_Open */ + /* + * Dirty fix of default values for ROM/PATCH microcode + * Dirty because this fix makes it impossible to setup + * suitable values before calling DRX_Open. This solution + * requires changes to RF AGC speed to be done via the CTRL + * function after calling DRX_Open + */ - /* m_dvbtRfAgcCfg.speed = 3; */ + /* m_dvbt_rf_agc_cfg.speed = 3; */ /* Reset driver debug flags to 0 */ status = write16(state, SCU_RAM_DRIVER_DEBUG__A, 0); @@ -6170,42 +6223,42 @@ static int init_drxk(struct drxk_state *state) if (status < 0) goto error; /* MPEGTS functions are still the same */ - status = MPEGTSDtoInit(state); + status = mpegts_dto_init(state); if (status < 0) goto error; - status = MPEGTSStop(state); + status = mpegts_stop(state); if (status < 0) goto error; - status = MPEGTSConfigurePolarity(state); + status = mpegts_configure_polarity(state); if (status < 0) goto error; - status = MPEGTSConfigurePins(state, state->m_enableMPEGOutput); + status = mpegts_configure_pins(state, state->m_enable_mpeg_output); if (status < 0) goto error; /* added: configure GPIO */ - status = WriteGPIO(state); + status = write_gpio(state); if (status < 0) goto error; - state->m_DrxkState = DRXK_STOPPED; + state->m_drxk_state = DRXK_STOPPED; - if (state->m_bPowerDown) { - status = PowerDownDevice(state); + if (state->m_b_power_down) { + status = power_down_device(state); if (status < 0) goto error; - state->m_DrxkState = DRXK_POWERED_DOWN; + state->m_drxk_state = DRXK_POWERED_DOWN; } else - state->m_DrxkState = DRXK_STOPPED; + state->m_drxk_state = DRXK_STOPPED; /* Initialize the supported delivery systems */ n = 0; - if (state->m_hasDVBC) { + if (state->m_has_dvbc) { state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_A; state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_C; strlcat(state->frontend.ops.info.name, " DVB-C", sizeof(state->frontend.ops.info.name)); } - if (state->m_hasDVBT) { + if (state->m_has_dvbt) { state->frontend.ops.delsys[n++] = SYS_DVBT; strlcat(state->frontend.ops.info.name, " DVB-T", sizeof(state->frontend.ops.info.name)); @@ -6214,9 +6267,9 @@ static int init_drxk(struct drxk_state *state) } error: if (status < 0) { - state->m_DrxkState = DRXK_NO_DEV; + state->m_drxk_state = DRXK_NO_DEV; drxk_i2c_unlock(state); - printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); + pr_err("Error %d on %s\n", status, __func__); } return status; @@ -6229,11 +6282,9 @@ static void load_firmware_cb(const struct firmware *fw, dprintk(1, ": %s\n", fw ? "firmware loaded" : "firmware not loaded"); if (!fw) { - printk(KERN_ERR - "drxk: Could not load firmware file %s.\n", + pr_err("Could not load firmware file %s.\n", state->microcode_name); - printk(KERN_INFO - "drxk: Copy %s to your hotplug directory!\n", + pr_info("Copy %s to your hotplug directory!\n", state->microcode_name); state->microcode_name = NULL; @@ -6270,12 +6321,12 @@ static int drxk_sleep(struct dvb_frontend *fe) dprintk(1, "\n"); - if (state->m_DrxkState == DRXK_NO_DEV) + if (state->m_drxk_state == DRXK_NO_DEV) return -ENODEV; - if (state->m_DrxkState == DRXK_UNINITIALIZED) + if (state->m_drxk_state == DRXK_UNINITIALIZED) return 0; - ShutDown(state); + shut_down(state); return 0; } @@ -6285,7 +6336,7 @@ static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) dprintk(1, ": %s\n", enable ? "enable" : "disable"); - if (state->m_DrxkState == DRXK_NO_DEV) + if (state->m_drxk_state == DRXK_NO_DEV) return -ENODEV; return ConfigureI2CBridge(state, enable ? true : false); @@ -6300,15 +6351,14 @@ static int drxk_set_parameters(struct dvb_frontend *fe) dprintk(1, "\n"); - if (state->m_DrxkState == DRXK_NO_DEV) + if (state->m_drxk_state == DRXK_NO_DEV) return -ENODEV; - if (state->m_DrxkState == DRXK_UNINITIALIZED) + if (state->m_drxk_state == DRXK_UNINITIALIZED) return -EAGAIN; if (!fe->ops.tuner_ops.get_if_frequency) { - printk(KERN_ERR - "drxk: Error: get_if_frequency() not defined at tuner. Can't work without it!\n"); + pr_err("Error: get_if_frequency() not defined at tuner. Can't work without it!\n"); return -EINVAL; } @@ -6323,22 +6373,23 @@ static int drxk_set_parameters(struct dvb_frontend *fe) state->props = *p; if (old_delsys != delsys) { - ShutDown(state); + shut_down(state); switch (delsys) { case SYS_DVBC_ANNEX_A: case SYS_DVBC_ANNEX_C: - if (!state->m_hasDVBC) + if (!state->m_has_dvbc) return -EINVAL; - state->m_itut_annex_c = (delsys == SYS_DVBC_ANNEX_C) ? true : false; + state->m_itut_annex_c = (delsys == SYS_DVBC_ANNEX_C) ? + true : false; if (state->m_itut_annex_c) - SetOperationMode(state, OM_QAM_ITU_C); + setoperation_mode(state, OM_QAM_ITU_C); else - SetOperationMode(state, OM_QAM_ITU_A); + setoperation_mode(state, OM_QAM_ITU_A); break; case SYS_DVBT: - if (!state->m_hasDVBT) + if (!state->m_has_dvbt) return -EINVAL; - SetOperationMode(state, OM_DVBT); + setoperation_mode(state, OM_DVBT); break; default: return -EINVAL; @@ -6346,7 +6397,7 @@ static int drxk_set_parameters(struct dvb_frontend *fe) } fe->ops.tuner_ops.get_if_frequency(fe, &IF); - Start(state, 0, IF); + start(state, 0, IF); /* After set_frontend, stats aren't avaliable */ p->strength.stat[0].scale = FE_SCALE_RELATIVE; @@ -6366,31 +6417,31 @@ static int drxk_set_parameters(struct dvb_frontend *fe) static int get_strength(struct drxk_state *state, u64 *strength) { int status; - struct SCfgAgc rfAgc, ifAgc; - u32 totalGain = 0; + struct s_cfg_agc rf_agc, if_agc; + u32 total_gain = 0; u32 atten = 0; - u32 agcRange = 0; + u32 agc_range = 0; u16 scu_lvl = 0; u16 scu_coc = 0; /* FIXME: those are part of the tuner presets */ - u16 tunerRfGain = 50; /* Default value on az6007 driver */ - u16 tunerIfGain = 40; /* Default value on az6007 driver */ + u16 tuner_rf_gain = 50; /* Default value on az6007 driver */ + u16 tuner_if_gain = 40; /* Default value on az6007 driver */ *strength = 0; - if (IsDVBT(state)) { - rfAgc = state->m_dvbtRfAgcCfg; - ifAgc = state->m_dvbtIfAgcCfg; - } else if (IsQAM(state)) { - rfAgc = state->m_qamRfAgcCfg; - ifAgc = state->m_qamIfAgcCfg; + if (is_dvbt(state)) { + rf_agc = state->m_dvbt_rf_agc_cfg; + if_agc = state->m_dvbt_if_agc_cfg; + } else if (is_qam(state)) { + rf_agc = state->m_qam_rf_agc_cfg; + if_agc = state->m_qam_if_agc_cfg; } else { - rfAgc = state->m_atvRfAgcCfg; - ifAgc = state->m_atvIfAgcCfg; + rf_agc = state->m_atv_rf_agc_cfg; + if_agc = state->m_atv_if_agc_cfg; } - if (rfAgc.ctrlMode == DRXK_AGC_CTRL_AUTO) { - /* SCU outputLevel */ + if (rf_agc.ctrl_mode == DRXK_AGC_CTRL_AUTO) { + /* SCU output_level */ status = read16(state, SCU_RAM_AGC_RF_IACCU_HI__A, &scu_lvl); if (status < 0) return status; @@ -6401,54 +6452,54 @@ static int get_strength(struct drxk_state *state, u64 *strength) return status; if (((u32) scu_lvl + (u32) scu_coc) < 0xffff) - rfAgc.outputLevel = scu_lvl + scu_coc; + rf_agc.output_level = scu_lvl + scu_coc; else - rfAgc.outputLevel = 0xffff; + rf_agc.output_level = 0xffff; /* Take RF gain into account */ - totalGain += tunerRfGain; + total_gain += tuner_rf_gain; /* clip output value */ - if (rfAgc.outputLevel < rfAgc.minOutputLevel) - rfAgc.outputLevel = rfAgc.minOutputLevel; - if (rfAgc.outputLevel > rfAgc.maxOutputLevel) - rfAgc.outputLevel = rfAgc.maxOutputLevel; + if (rf_agc.output_level < rf_agc.min_output_level) + rf_agc.output_level = rf_agc.min_output_level; + if (rf_agc.output_level > rf_agc.max_output_level) + rf_agc.output_level = rf_agc.max_output_level; - agcRange = (u32) (rfAgc.maxOutputLevel - rfAgc.minOutputLevel); - if (agcRange > 0) { + agc_range = (u32) (rf_agc.max_output_level - rf_agc.min_output_level); + if (agc_range > 0) { atten += 100UL * - ((u32)(tunerRfGain)) * - ((u32)(rfAgc.outputLevel - rfAgc.minOutputLevel)) - / agcRange; + ((u32)(tuner_rf_gain)) * + ((u32)(rf_agc.output_level - rf_agc.min_output_level)) + / agc_range; } } - if (ifAgc.ctrlMode == DRXK_AGC_CTRL_AUTO) { + if (if_agc.ctrl_mode == DRXK_AGC_CTRL_AUTO) { status = read16(state, SCU_RAM_AGC_IF_IACCU_HI__A, - &ifAgc.outputLevel); + &if_agc.output_level); if (status < 0) return status; status = read16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A, - &ifAgc.top); + &if_agc.top); if (status < 0) return status; /* Take IF gain into account */ - totalGain += (u32) tunerIfGain; + total_gain += (u32) tuner_if_gain; /* clip output value */ - if (ifAgc.outputLevel < ifAgc.minOutputLevel) - ifAgc.outputLevel = ifAgc.minOutputLevel; - if (ifAgc.outputLevel > ifAgc.maxOutputLevel) - ifAgc.outputLevel = ifAgc.maxOutputLevel; + if (if_agc.output_level < if_agc.min_output_level) + if_agc.output_level = if_agc.min_output_level; + if (if_agc.output_level > if_agc.max_output_level) + if_agc.output_level = if_agc.max_output_level; - agcRange = (u32) (ifAgc.maxOutputLevel - ifAgc.minOutputLevel); - if (agcRange > 0) { + agc_range = (u32)(if_agc.max_output_level - if_agc.min_output_level); + if (agc_range > 0) { atten += 100UL * - ((u32)(tunerIfGain)) * - ((u32)(ifAgc.outputLevel - ifAgc.minOutputLevel)) - / agcRange; + ((u32)(tuner_if_gain)) * + ((u32)(if_agc.output_level - if_agc.min_output_level)) + / agc_range; } } @@ -6456,8 +6507,8 @@ static int get_strength(struct drxk_state *state, u64 *strength) * Convert to 0..65535 scale. * If it can't be measured (AGC is disabled), just show 100%. */ - if (totalGain > 0) - *strength = (65535UL * atten / totalGain / 100); + if (total_gain > 0) + *strength = (65535UL * atten / total_gain / 100); else *strength = 65535; @@ -6480,14 +6531,14 @@ static int drxk_get_stats(struct dvb_frontend *fe) u32 pkt_error_count; s32 cnr; - if (state->m_DrxkState == DRXK_NO_DEV) + if (state->m_drxk_state == DRXK_NO_DEV) return -ENODEV; - if (state->m_DrxkState == DRXK_UNINITIALIZED) + if (state->m_drxk_state == DRXK_UNINITIALIZED) return -EAGAIN; /* get status */ state->fe_status = 0; - GetLockStatus(state, &stat); + get_lock_status(state, &stat); if (stat == MPEG_LOCK) state->fe_status |= 0x1f; if (stat == FEC_LOCK) @@ -6503,7 +6554,7 @@ static int drxk_get_stats(struct dvb_frontend *fe) if (stat >= DEMOD_LOCK) { - GetSignalToNoise(state, &cnr); + get_signal_to_noise(state, &cnr); c->cnr.stat[0].svalue = cnr * 100; c->cnr.stat[0].scale = FE_SCALE_DECIBEL; } else { @@ -6524,9 +6575,11 @@ static int drxk_get_stats(struct dvb_frontend *fe) /* BER measurement is valid if at least FEC lock is achieved */ - /* OFDM_EC_VD_REQ_SMB_CNT__A and/or OFDM_EC_VD_REQ_BIT_CNT can be written - to set nr of symbols or bits over which - to measure EC_VD_REG_ERR_BIT_CNT__A . See CtrlSetCfg(). */ + /* + * OFDM_EC_VD_REQ_SMB_CNT__A and/or OFDM_EC_VD_REQ_BIT_CNT can be + * written to set nr of symbols or bits over which to measure + * EC_VD_REG_ERR_BIT_CNT__A . See CtrlSetCfg(). + */ /* Read registers for post/preViterbi BER calculation */ status = read16(state, OFDM_EC_VD_ERR_BIT_CNT__A, ®16); @@ -6610,9 +6663,9 @@ static int drxk_read_signal_strength(struct dvb_frontend *fe, dprintk(1, "\n"); - if (state->m_DrxkState == DRXK_NO_DEV) + if (state->m_drxk_state == DRXK_NO_DEV) return -ENODEV; - if (state->m_DrxkState == DRXK_UNINITIALIZED) + if (state->m_drxk_state == DRXK_UNINITIALIZED) return -EAGAIN; *strength = c->strength.stat[0].uvalue; @@ -6626,12 +6679,12 @@ static int drxk_read_snr(struct dvb_frontend *fe, u16 *snr) dprintk(1, "\n"); - if (state->m_DrxkState == DRXK_NO_DEV) + if (state->m_drxk_state == DRXK_NO_DEV) return -ENODEV; - if (state->m_DrxkState == DRXK_UNINITIALIZED) + if (state->m_drxk_state == DRXK_UNINITIALIZED) return -EAGAIN; - GetSignalToNoise(state, &snr2); + get_signal_to_noise(state, &snr2); /* No negative SNR, clip to zero */ if (snr2 < 0) @@ -6647,27 +6700,27 @@ static int drxk_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) dprintk(1, "\n"); - if (state->m_DrxkState == DRXK_NO_DEV) + if (state->m_drxk_state == DRXK_NO_DEV) return -ENODEV; - if (state->m_DrxkState == DRXK_UNINITIALIZED) + if (state->m_drxk_state == DRXK_UNINITIALIZED) return -EAGAIN; - DVBTQAMGetAccPktErr(state, &err); + dvbtqam_get_acc_pkt_err(state, &err); *ucblocks = (u32) err; return 0; } -static int drxk_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings - *sets) +static int drxk_get_tune_settings(struct dvb_frontend *fe, + struct dvb_frontend_tune_settings *sets) { struct drxk_state *state = fe->demodulator_priv; struct dtv_frontend_properties *p = &fe->dtv_property_cache; dprintk(1, "\n"); - if (state->m_DrxkState == DRXK_NO_DEV) + if (state->m_drxk_state == DRXK_NO_DEV) return -ENODEV; - if (state->m_DrxkState == DRXK_UNINITIALIZED) + if (state->m_drxk_state == DRXK_UNINITIALIZED) return -EAGAIN; switch (p->delivery_system) { @@ -6737,36 +6790,36 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config, state->no_i2c_bridge = config->no_i2c_bridge; state->antenna_gpio = config->antenna_gpio; state->antenna_dvbt = config->antenna_dvbt; - state->m_ChunkSize = config->chunk_size; + state->m_chunk_size = config->chunk_size; state->enable_merr_cfg = config->enable_merr_cfg; if (config->dynamic_clk) { - state->m_DVBTStaticCLK = 0; - state->m_DVBCStaticCLK = 0; + state->m_dvbt_static_clk = 0; + state->m_dvbc_static_clk = 0; } else { - state->m_DVBTStaticCLK = 1; - state->m_DVBCStaticCLK = 1; + state->m_dvbt_static_clk = 1; + state->m_dvbc_static_clk = 1; } if (config->mpeg_out_clk_strength) - state->m_TSClockkStrength = config->mpeg_out_clk_strength & 0x07; + state->m_ts_clockk_strength = config->mpeg_out_clk_strength & 0x07; else - state->m_TSClockkStrength = 0x06; + state->m_ts_clockk_strength = 0x06; if (config->parallel_ts) - state->m_enableParallel = true; + state->m_enable_parallel = true; else - state->m_enableParallel = false; + state->m_enable_parallel = false; /* NOTE: as more UIO bits will be used, add them to the mask */ - state->UIO_mask = config->antenna_gpio; + state->uio_mask = config->antenna_gpio; /* Default gpio to DVB-C */ if (!state->antenna_dvbt && state->antenna_gpio) - state->m_GPIO |= state->antenna_gpio; + state->m_gpio |= state->antenna_gpio; else - state->m_GPIO &= ~state->antenna_gpio; + state->m_gpio &= ~state->antenna_gpio; mutex_init(&state->mutex); @@ -6792,8 +6845,7 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config, GFP_KERNEL, state, load_firmware_cb); if (status < 0) { - printk(KERN_ERR - "drxk: failed to request a firmware\n"); + pr_err("failed to request a firmware\n"); return NULL; } } @@ -6821,11 +6873,11 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config, p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE; - printk(KERN_INFO "drxk: frontend initialized.\n"); + pr_info("frontend initialized.\n"); return &state->frontend; error: - printk(KERN_ERR "drxk: not found\n"); + pr_err("not found\n"); kfree(state); return NULL; } diff --git a/drivers/media/dvb-frontends/drxk_hard.h b/drivers/media/dvb-frontends/drxk_hard.h index b8424f15f9a6..bae9c71dc3e9 100644 --- a/drivers/media/dvb-frontends/drxk_hard.h +++ b/drivers/media/dvb-frontends/drxk_hard.h @@ -46,7 +46,7 @@ #define IQM_RC_ADJ_SEL_B_QAM 0x1 #define IQM_RC_ADJ_SEL_B_VSB 0x2 -enum OperationMode { +enum operation_mode { OM_NONE, OM_QAM_ITU_A, OM_QAM_ITU_B, @@ -54,7 +54,7 @@ enum OperationMode { OM_DVBT }; -enum DRXPowerMode { +enum drx_power_mode { DRX_POWER_UP = 0, DRX_POWER_MODE_1, DRX_POWER_MODE_2, @@ -77,24 +77,29 @@ enum DRXPowerMode { }; -/** /brief Intermediate power mode for DRXK, power down OFDM clock domain */ +/* Intermediate power mode for DRXK, power down OFDM clock domain */ #ifndef DRXK_POWER_DOWN_OFDM #define DRXK_POWER_DOWN_OFDM DRX_POWER_MODE_1 #endif -/** /brief Intermediate power mode for DRXK, power down core (sysclk) */ +/* Intermediate power mode for DRXK, power down core (sysclk) */ #ifndef DRXK_POWER_DOWN_CORE #define DRXK_POWER_DOWN_CORE DRX_POWER_MODE_9 #endif -/** /brief Intermediate power mode for DRXK, power down pll (only osc runs) */ +/* Intermediate power mode for DRXK, power down pll (only osc runs) */ #ifndef DRXK_POWER_DOWN_PLL #define DRXK_POWER_DOWN_PLL DRX_POWER_MODE_10 #endif -enum AGC_CTRL_MODE { DRXK_AGC_CTRL_AUTO = 0, DRXK_AGC_CTRL_USER, DRXK_AGC_CTRL_OFF }; -enum EDrxkState { +enum agc_ctrl_mode { + DRXK_AGC_CTRL_AUTO = 0, + DRXK_AGC_CTRL_USER, + DRXK_AGC_CTRL_OFF +}; + +enum e_drxk_state { DRXK_UNINITIALIZED = 0, DRXK_STOPPED, DRXK_DTV_STARTED, @@ -103,7 +108,7 @@ enum EDrxkState { DRXK_NO_DEV /* If drxk init failed */ }; -enum EDrxkCoefArrayIndex { +enum e_drxk_coef_array_index { DRXK_COEF_IDX_MN = 0, DRXK_COEF_IDX_FM , DRXK_COEF_IDX_L , @@ -113,13 +118,13 @@ enum EDrxkCoefArrayIndex { DRXK_COEF_IDX_I , DRXK_COEF_IDX_MAX }; -enum EDrxkSifAttenuation { +enum e_drxk_sif_attenuation { DRXK_SIF_ATTENUATION_0DB, DRXK_SIF_ATTENUATION_3DB, DRXK_SIF_ATTENUATION_6DB, DRXK_SIF_ATTENUATION_9DB }; -enum EDrxkConstellation { +enum e_drxk_constellation { DRX_CONSTELLATION_BPSK = 0, DRX_CONSTELLATION_QPSK, DRX_CONSTELLATION_PSK8, @@ -133,7 +138,7 @@ enum EDrxkConstellation { DRX_CONSTELLATION_UNKNOWN = DRX_UNKNOWN, DRX_CONSTELLATION_AUTO = DRX_AUTO }; -enum EDrxkInterleaveMode { +enum e_drxk_interleave_mode { DRXK_QAM_I12_J17 = 16, DRXK_QAM_I_UNKNOWN = DRX_UNKNOWN }; @@ -144,14 +149,14 @@ enum { DRXK_SPIN_UNKNOWN }; -enum DRXKCfgDvbtSqiSpeed { +enum drxk_cfg_dvbt_sqi_speed { DRXK_DVBT_SQI_SPEED_FAST = 0, DRXK_DVBT_SQI_SPEED_MEDIUM, DRXK_DVBT_SQI_SPEED_SLOW, DRXK_DVBT_SQI_SPEED_UNKNOWN = DRX_UNKNOWN } ; -enum DRXFftmode_t { +enum drx_fftmode_t { DRX_FFTMODE_2K = 0, DRX_FFTMODE_4K, DRX_FFTMODE_8K, @@ -159,47 +164,47 @@ enum DRXFftmode_t { DRX_FFTMODE_AUTO = DRX_AUTO }; -enum DRXMPEGStrWidth_t { +enum drxmpeg_str_width_t { DRX_MPEG_STR_WIDTH_1, DRX_MPEG_STR_WIDTH_8 }; -enum DRXQamLockRange_t { +enum drx_qam_lock_range_t { DRX_QAM_LOCKRANGE_NORMAL, DRX_QAM_LOCKRANGE_EXTENDED }; -struct DRXKCfgDvbtEchoThres_t { +struct drxk_cfg_dvbt_echo_thres_t { u16 threshold; - enum DRXFftmode_t fftMode; + enum drx_fftmode_t fft_mode; } ; -struct SCfgAgc { - enum AGC_CTRL_MODE ctrlMode; /* off, user, auto */ - u16 outputLevel; /* range dependent on AGC */ - u16 minOutputLevel; /* range dependent on AGC */ - u16 maxOutputLevel; /* range dependent on AGC */ +struct s_cfg_agc { + enum agc_ctrl_mode ctrl_mode; /* off, user, auto */ + u16 output_level; /* range dependent on AGC */ + u16 min_output_level; /* range dependent on AGC */ + u16 max_output_level; /* range dependent on AGC */ u16 speed; /* range dependent on AGC */ u16 top; /* rf-agc take over point */ - u16 cutOffCurrent; /* rf-agc is accelerated if output current + u16 cut_off_current; /* rf-agc is accelerated if output current is below cut-off current */ - u16 IngainTgtMax; - u16 FastClipCtrlDelay; + u16 ingain_tgt_max; + u16 fast_clip_ctrl_delay; }; -struct SCfgPreSaw { +struct s_cfg_pre_saw { u16 reference; /* pre SAW reference value, range 0 .. 31 */ - bool usePreSaw; /* TRUE algorithms must use pre SAW sense */ + bool use_pre_saw; /* TRUE algorithms must use pre SAW sense */ }; -struct DRXKOfdmScCmd_t { - u16 cmd; /**< Command number */ - u16 subcmd; /**< Sub-command parameter*/ - u16 param0; /**< General purpous param */ - u16 param1; /**< General purpous param */ - u16 param2; /**< General purpous param */ - u16 param3; /**< General purpous param */ - u16 param4; /**< General purpous param */ +struct drxk_ofdm_sc_cmd_t { + u16 cmd; /* Command number */ + u16 subcmd; /* Sub-command parameter*/ + u16 param0; /* General purpous param */ + u16 param1; /* General purpous param */ + u16 param2; /* General purpous param */ + u16 param3; /* General purpous param */ + u16 param4; /* General purpous param */ }; struct drxk_state { @@ -213,121 +218,121 @@ struct drxk_state { struct mutex mutex; - u32 m_Instance; /**< Channel 1,2,3 or 4 */ - - int m_ChunkSize; - u8 Chunk[256]; - - bool m_hasLNA; - bool m_hasDVBT; - bool m_hasDVBC; - bool m_hasAudio; - bool m_hasATV; - bool m_hasOOB; - bool m_hasSAWSW; /**< TRUE if mat_tx is available */ - bool m_hasGPIO1; /**< TRUE if mat_rx is available */ - bool m_hasGPIO2; /**< TRUE if GPIO is available */ - bool m_hasIRQN; /**< TRUE if IRQN is available */ - u16 m_oscClockFreq; - u16 m_HICfgTimingDiv; - u16 m_HICfgBridgeDelay; - u16 m_HICfgWakeUpKey; - u16 m_HICfgTimeout; - u16 m_HICfgCtrl; - s32 m_sysClockFreq; /**< system clock frequency in kHz */ - - enum EDrxkState m_DrxkState; /**< State of Drxk (init,stopped,started) */ - enum OperationMode m_OperationMode; /**< digital standards */ - struct SCfgAgc m_vsbRfAgcCfg; /**< settings for VSB RF-AGC */ - struct SCfgAgc m_vsbIfAgcCfg; /**< settings for VSB IF-AGC */ - u16 m_vsbPgaCfg; /**< settings for VSB PGA */ - struct SCfgPreSaw m_vsbPreSawCfg; /**< settings for pre SAW sense */ - s32 m_Quality83percent; /**< MER level (*0.1 dB) for 83% quality indication */ - s32 m_Quality93percent; /**< MER level (*0.1 dB) for 93% quality indication */ - bool m_smartAntInverted; - bool m_bDebugEnableBridge; - bool m_bPDownOpenBridge; /**< only open DRXK bridge before power-down once it has been accessed */ - bool m_bPowerDown; /**< Power down when not used */ - - u32 m_IqmFsRateOfs; /**< frequency shift as written to DRXK register (28bit fixpoint) */ - - bool m_enableMPEGOutput; /**< If TRUE, enable MPEG output */ - bool m_insertRSByte; /**< If TRUE, insert RS byte */ - bool m_enableParallel; /**< If TRUE, parallel out otherwise serial */ - bool m_invertDATA; /**< If TRUE, invert DATA signals */ - bool m_invertERR; /**< If TRUE, invert ERR signal */ - bool m_invertSTR; /**< If TRUE, invert STR signals */ - bool m_invertVAL; /**< If TRUE, invert VAL signals */ - bool m_invertCLK; /**< If TRUE, invert CLK signals */ - bool m_DVBCStaticCLK; - bool m_DVBTStaticCLK; /**< If TRUE, static MPEG clockrate will + u32 m_instance; /* Channel 1,2,3 or 4 */ + + int m_chunk_size; + u8 chunk[256]; + + bool m_has_lna; + bool m_has_dvbt; + bool m_has_dvbc; + bool m_has_audio; + bool m_has_atv; + bool m_has_oob; + bool m_has_sawsw; /* TRUE if mat_tx is available */ + bool m_has_gpio1; /* TRUE if mat_rx is available */ + bool m_has_gpio2; /* TRUE if GPIO is available */ + bool m_has_irqn; /* TRUE if IRQN is available */ + u16 m_osc_clock_freq; + u16 m_hi_cfg_timing_div; + u16 m_hi_cfg_bridge_delay; + u16 m_hi_cfg_wake_up_key; + u16 m_hi_cfg_timeout; + u16 m_hi_cfg_ctrl; + s32 m_sys_clock_freq; /* system clock frequency in kHz */ + + enum e_drxk_state m_drxk_state; /* State of Drxk (init,stopped,started) */ + enum operation_mode m_operation_mode; /* digital standards */ + struct s_cfg_agc m_vsb_rf_agc_cfg; /* settings for VSB RF-AGC */ + struct s_cfg_agc m_vsb_if_agc_cfg; /* settings for VSB IF-AGC */ + u16 m_vsb_pga_cfg; /* settings for VSB PGA */ + struct s_cfg_pre_saw m_vsb_pre_saw_cfg; /* settings for pre SAW sense */ + s32 m_Quality83percent; /* MER level (*0.1 dB) for 83% quality indication */ + s32 m_Quality93percent; /* MER level (*0.1 dB) for 93% quality indication */ + bool m_smart_ant_inverted; + bool m_b_debug_enable_bridge; + bool m_b_p_down_open_bridge; /* only open DRXK bridge before power-down once it has been accessed */ + bool m_b_power_down; /* Power down when not used */ + + u32 m_iqm_fs_rate_ofs; /* frequency shift as written to DRXK register (28bit fixpoint) */ + + bool m_enable_mpeg_output; /* If TRUE, enable MPEG output */ + bool m_insert_rs_byte; /* If TRUE, insert RS byte */ + bool m_enable_parallel; /* If TRUE, parallel out otherwise serial */ + bool m_invert_data; /* If TRUE, invert DATA signals */ + bool m_invert_err; /* If TRUE, invert ERR signal */ + bool m_invert_str; /* If TRUE, invert STR signals */ + bool m_invert_val; /* If TRUE, invert VAL signals */ + bool m_invert_clk; /* If TRUE, invert CLK signals */ + bool m_dvbc_static_clk; + bool m_dvbt_static_clk; /* If TRUE, static MPEG clockrate will be used, otherwise clockrate will adapt to the bitrate of the TS */ - u32 m_DVBTBitrate; - u32 m_DVBCBitrate; + u32 m_dvbt_bitrate; + u32 m_dvbc_bitrate; - u8 m_TSDataStrength; - u8 m_TSClockkStrength; + u8 m_ts_data_strength; + u8 m_ts_clockk_strength; bool m_itut_annex_c; /* If true, uses ITU-T DVB-C Annex C, instead of Annex A */ - enum DRXMPEGStrWidth_t m_widthSTR; /**< MPEG start width */ - u32 m_mpegTsStaticBitrate; /**< Maximum bitrate in b/s in case + enum drxmpeg_str_width_t m_width_str; /* MPEG start width */ + u32 m_mpeg_ts_static_bitrate; /* Maximum bitrate in b/s in case static clockrate is selected */ - /* LARGE_INTEGER m_StartTime; */ /**< Contains the time of the last demod start */ - s32 m_MpegLockTimeOut; /**< WaitForLockStatus Timeout (counts from start time) */ - s32 m_DemodLockTimeOut; /**< WaitForLockStatus Timeout (counts from start time) */ - - bool m_disableTEIhandling; - - bool m_RfAgcPol; - bool m_IfAgcPol; - - struct SCfgAgc m_atvRfAgcCfg; /**< settings for ATV RF-AGC */ - struct SCfgAgc m_atvIfAgcCfg; /**< settings for ATV IF-AGC */ - struct SCfgPreSaw m_atvPreSawCfg; /**< settings for ATV pre SAW sense */ - bool m_phaseCorrectionBypass; - s16 m_atvTopVidPeak; - u16 m_atvTopNoiseTh; - enum EDrxkSifAttenuation m_sifAttenuation; - bool m_enableCVBSOutput; - bool m_enableSIFOutput; - bool m_bMirrorFreqSpect; - enum EDrxkConstellation m_Constellation; /**< Constellation type of the channel */ - u32 m_CurrSymbolRate; /**< Current QAM symbol rate */ - struct SCfgAgc m_qamRfAgcCfg; /**< settings for QAM RF-AGC */ - struct SCfgAgc m_qamIfAgcCfg; /**< settings for QAM IF-AGC */ - u16 m_qamPgaCfg; /**< settings for QAM PGA */ - struct SCfgPreSaw m_qamPreSawCfg; /**< settings for QAM pre SAW sense */ - enum EDrxkInterleaveMode m_qamInterleaveMode; /**< QAM Interleave mode */ - u16 m_fecRsPlen; - u16 m_fecRsPrescale; - - enum DRXKCfgDvbtSqiSpeed m_sqiSpeed; - - u16 m_GPIO; - u16 m_GPIOCfg; - - struct SCfgAgc m_dvbtRfAgcCfg; /**< settings for QAM RF-AGC */ - struct SCfgAgc m_dvbtIfAgcCfg; /**< settings for QAM IF-AGC */ - struct SCfgPreSaw m_dvbtPreSawCfg; /**< settings for QAM pre SAW sense */ - - u16 m_agcFastClipCtrlDelay; - bool m_adcCompPassed; + /* LARGE_INTEGER m_startTime; */ /* Contains the time of the last demod start */ + s32 m_mpeg_lock_time_out; /* WaitForLockStatus Timeout (counts from start time) */ + s32 m_demod_lock_time_out; /* WaitForLockStatus Timeout (counts from start time) */ + + bool m_disable_te_ihandling; + + bool m_rf_agc_pol; + bool m_if_agc_pol; + + struct s_cfg_agc m_atv_rf_agc_cfg; /* settings for ATV RF-AGC */ + struct s_cfg_agc m_atv_if_agc_cfg; /* settings for ATV IF-AGC */ + struct s_cfg_pre_saw m_atv_pre_saw_cfg; /* settings for ATV pre SAW sense */ + bool m_phase_correction_bypass; + s16 m_atv_top_vid_peak; + u16 m_atv_top_noise_th; + enum e_drxk_sif_attenuation m_sif_attenuation; + bool m_enable_cvbs_output; + bool m_enable_sif_output; + bool m_b_mirror_freq_spect; + enum e_drxk_constellation m_constellation; /* constellation type of the channel */ + u32 m_curr_symbol_rate; /* Current QAM symbol rate */ + struct s_cfg_agc m_qam_rf_agc_cfg; /* settings for QAM RF-AGC */ + struct s_cfg_agc m_qam_if_agc_cfg; /* settings for QAM IF-AGC */ + u16 m_qam_pga_cfg; /* settings for QAM PGA */ + struct s_cfg_pre_saw m_qam_pre_saw_cfg; /* settings for QAM pre SAW sense */ + enum e_drxk_interleave_mode m_qam_interleave_mode; /* QAM Interleave mode */ + u16 m_fec_rs_plen; + u16 m_fec_rs_prescale; + + enum drxk_cfg_dvbt_sqi_speed m_sqi_speed; + + u16 m_gpio; + u16 m_gpio_cfg; + + struct s_cfg_agc m_dvbt_rf_agc_cfg; /* settings for QAM RF-AGC */ + struct s_cfg_agc m_dvbt_if_agc_cfg; /* settings for QAM IF-AGC */ + struct s_cfg_pre_saw m_dvbt_pre_saw_cfg; /* settings for QAM pre SAW sense */ + + u16 m_agcfast_clip_ctrl_delay; + bool m_adc_comp_passed; u16 m_adcCompCoef[64]; - u16 m_adcState; + u16 m_adc_state; u8 *m_microcode; int m_microcode_length; - bool m_DRXK_A3_ROM_CODE; - bool m_DRXK_A3_PATCH_CODE; + bool m_drxk_a3_rom_code; + bool m_drxk_a3_patch_code; bool m_rfmirror; - u8 m_deviceSpin; - u32 m_iqmRcRate; + u8 m_device_spin; + u32 m_iqm_rc_rate; - enum DRXPowerMode m_currentPowerMode; + enum drx_power_mode m_current_power_mode; /* when true, avoids other devices to use the I2C bus */ bool drxk_i2c_exclusive_lock; @@ -337,7 +342,7 @@ struct drxk_state { * at struct drxk_config. */ - u16 UIO_mask; /* Bits used by UIO */ + u16 uio_mask; /* Bits used by UIO */ bool enable_merr_cfg; bool single_master; diff --git a/drivers/media/dvb-frontends/stb0899_algo.c b/drivers/media/dvb-frontends/stb0899_algo.c index 117a56926dca..93596e0e640b 100644 --- a/drivers/media/dvb-frontends/stb0899_algo.c +++ b/drivers/media/dvb-frontends/stb0899_algo.c @@ -226,8 +226,8 @@ static enum stb0899_status stb0899_search_tmg(struct stb0899_state *state) next_loop--; if (next_loop) { - STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(state->config->inversion * derot_freq)); - STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->inversion * derot_freq)); + STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(internal->inversion * derot_freq)); + STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(internal->inversion * derot_freq)); stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency */ } internal->direction = -internal->direction; /* Change zigzag direction */ @@ -235,7 +235,7 @@ static enum stb0899_status stb0899_search_tmg(struct stb0899_state *state) if (internal->status == TIMINGOK) { stb0899_read_regs(state, STB0899_CFRM, cfr, 2); /* get derotator frequency */ - internal->derot_freq = state->config->inversion * MAKEWORD16(cfr[0], cfr[1]); + internal->derot_freq = internal->inversion * MAKEWORD16(cfr[0], cfr[1]); dprintk(state->verbose, FE_DEBUG, 1, "------->TIMING OK ! Derot Freq = %d", internal->derot_freq); } @@ -306,8 +306,8 @@ static enum stb0899_status stb0899_search_carrier(struct stb0899_state *state) STB0899_SETFIELD_VAL(CFD_ON, reg, 1); stb0899_write_reg(state, STB0899_CFD, reg); - STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(state->config->inversion * derot_freq)); - STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->inversion * derot_freq)); + STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(internal->inversion * derot_freq)); + STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(internal->inversion * derot_freq)); stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency */ } } @@ -317,7 +317,7 @@ static enum stb0899_status stb0899_search_carrier(struct stb0899_state *state) if (internal->status == CARRIEROK) { stb0899_read_regs(state, STB0899_CFRM, cfr, 2); /* get derotator frequency */ - internal->derot_freq = state->config->inversion * MAKEWORD16(cfr[0], cfr[1]); + internal->derot_freq = internal->inversion * MAKEWORD16(cfr[0], cfr[1]); dprintk(state->verbose, FE_DEBUG, 1, "----> CARRIER OK !, Derot Freq=%d", internal->derot_freq); } else { internal->derot_freq = last_derot_freq; @@ -412,8 +412,8 @@ static enum stb0899_status stb0899_search_data(struct stb0899_state *state) STB0899_SETFIELD_VAL(CFD_ON, reg, 1); stb0899_write_reg(state, STB0899_CFD, reg); - STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(state->config->inversion * derot_freq)); - STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->inversion * derot_freq)); + STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(internal->inversion * derot_freq)); + STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(internal->inversion * derot_freq)); stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency */ stb0899_check_carrier(state); @@ -425,7 +425,15 @@ static enum stb0899_status stb0899_search_data(struct stb0899_state *state) if (internal->status == DATAOK) { stb0899_read_regs(state, STB0899_CFRM, cfr, 2); /* get derotator frequency */ - internal->derot_freq = state->config->inversion * MAKEWORD16(cfr[0], cfr[1]); + + /* store autodetected IQ swapping as default for DVB-S2 tuning */ + reg = stb0899_read_reg(state, STB0899_IQSWAP); + if (STB0899_GETFIELD(SYM, reg)) + internal->inversion = IQ_SWAP_ON; + else + internal->inversion = IQ_SWAP_OFF; + + internal->derot_freq = internal->inversion * MAKEWORD16(cfr[0], cfr[1]); dprintk(state->verbose, FE_DEBUG, 1, "------> DATAOK ! Derot Freq=%d", internal->derot_freq); } @@ -444,7 +452,7 @@ static enum stb0899_status stb0899_check_range(struct stb0899_state *state) int range_offst, tp_freq; range_offst = internal->srch_range / 2000; - tp_freq = internal->freq + (internal->derot_freq * internal->mclk) / 1000; + tp_freq = internal->freq - (internal->derot_freq * internal->mclk) / 1000; if ((tp_freq >= params->freq - range_offst) && (tp_freq <= params->freq + range_offst)) { internal->status = RANGEOK; @@ -638,7 +646,7 @@ enum stb0899_status stb0899_dvbs_algo(struct stb0899_state *state) "RANGE OK ! derot freq=%d, mclk=%d", internal->derot_freq, internal->mclk); - internal->freq = params->freq + ((internal->derot_freq * internal->mclk) / 1000); + internal->freq = params->freq - ((internal->derot_freq * internal->mclk) / 1000); reg = stb0899_read_reg(state, STB0899_PLPARM); internal->fecrate = STB0899_GETFIELD(VITCURPUN, reg); dprintk(state->verbose, FE_DEBUG, 1, @@ -1373,9 +1381,6 @@ enum stb0899_status stb0899_dvbs2_algo(struct stb0899_state *state) case IQ_SWAP_ON: STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, 1); break; - case IQ_SWAP_AUTO: /* use last successful search first */ - STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, 1); - break; } stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_DMD_CNTRL2, STB0899_OFF0_DMD_CNTRL2, reg); stb0899_dvbs2_reacquire(state); @@ -1405,41 +1410,39 @@ enum stb0899_status stb0899_dvbs2_algo(struct stb0899_state *state) } if (internal->status != DVBS2_FEC_LOCK) { - if (internal->inversion == IQ_SWAP_AUTO) { - reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CNTRL2); - iqSpectrum = STB0899_GETFIELD(SPECTRUM_INVERT, reg); - /* IQ Spectrum Inversion */ - STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, !iqSpectrum); - stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_DMD_CNTRL2, STB0899_OFF0_DMD_CNTRL2, reg); - /* start acquistion process */ - stb0899_dvbs2_reacquire(state); + reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CNTRL2); + iqSpectrum = STB0899_GETFIELD(SPECTRUM_INVERT, reg); + /* IQ Spectrum Inversion */ + STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, !iqSpectrum); + stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_DMD_CNTRL2, STB0899_OFF0_DMD_CNTRL2, reg); + /* start acquistion process */ + stb0899_dvbs2_reacquire(state); + + /* Wait for demod lock (UWP and CSM) */ + internal->status = stb0899_dvbs2_get_dmd_status(state, searchTime); + if (internal->status == DVBS2_DEMOD_LOCK) { + i = 0; + /* Demod Locked, check FEC */ + internal->status = stb0899_dvbs2_get_fec_status(state, FecLockTime); + /*try thrice for false locks, (UWP and CSM Locked but no FEC) */ + while ((internal->status != DVBS2_FEC_LOCK) && (i < 3)) { + /* Read the frequency offset*/ + offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ); - /* Wait for demod lock (UWP and CSM) */ - internal->status = stb0899_dvbs2_get_dmd_status(state, searchTime); - if (internal->status == DVBS2_DEMOD_LOCK) { - i = 0; - /* Demod Locked, check FEC */ - internal->status = stb0899_dvbs2_get_fec_status(state, FecLockTime); - /*try thrice for false locks, (UWP and CSM Locked but no FEC) */ - while ((internal->status != DVBS2_FEC_LOCK) && (i < 3)) { - /* Read the frequency offset*/ - offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ); - - /* Set the Nominal frequency to the found frequency offset for the next reacquire*/ - reg = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_NOM_FREQ); - STB0899_SETFIELD_VAL(CRL_NOM_FREQ, reg, offsetfreq); - stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_NOM_FREQ, STB0899_OFF0_CRL_NOM_FREQ, reg); - - stb0899_dvbs2_reacquire(state); - internal->status = stb0899_dvbs2_get_fec_status(state, searchTime); - i++; - } + /* Set the Nominal frequency to the found frequency offset for the next reacquire*/ + reg = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_NOM_FREQ); + STB0899_SETFIELD_VAL(CRL_NOM_FREQ, reg, offsetfreq); + stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_NOM_FREQ, STB0899_OFF0_CRL_NOM_FREQ, reg); + + stb0899_dvbs2_reacquire(state); + internal->status = stb0899_dvbs2_get_fec_status(state, searchTime); + i++; } + } /* - if (pParams->DVBS2State == FE_DVBS2_FEC_LOCKED) - pParams->IQLocked = !iqSpectrum; + if (pParams->DVBS2State == FE_DVBS2_FEC_LOCKED) + pParams->IQLocked = !iqSpectrum; */ - } } if (internal->status == DVBS2_FEC_LOCK) { dprintk(state->verbose, FE_DEBUG, 1, "----------------> DVB-S2 FEC Lock !"); @@ -1487,13 +1490,21 @@ enum stb0899_status stb0899_dvbs2_algo(struct stb0899_state *state) /* Store signal parameters */ offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ); + /* sign extend 30 bit value before using it in calculations */ + if (offsetfreq & (1 << 29)) + offsetfreq |= -1 << 30; + offsetfreq = offsetfreq / ((1 << 30) / 1000); offsetfreq *= (internal->master_clk / 1000000); + + /* store current inversion for next run */ reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CNTRL2); if (STB0899_GETFIELD(SPECTRUM_INVERT, reg)) - offsetfreq *= -1; + internal->inversion = IQ_SWAP_ON; + else + internal->inversion = IQ_SWAP_OFF; - internal->freq = internal->freq - offsetfreq; + internal->freq = internal->freq + offsetfreq; internal->srate = stb0899_dvbs2_get_srate(state); reg = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_STAT2); diff --git a/drivers/media/dvb-frontends/stb0899_drv.c b/drivers/media/dvb-frontends/stb0899_drv.c index cc278b3d6d5a..3dd5714eadba 100644 --- a/drivers/media/dvb-frontends/stb0899_drv.c +++ b/drivers/media/dvb-frontends/stb0899_drv.c @@ -1618,19 +1618,18 @@ static struct dvb_frontend_ops stb0899_ops = { struct dvb_frontend *stb0899_attach(struct stb0899_config *config, struct i2c_adapter *i2c) { struct stb0899_state *state = NULL; - enum stb0899_inversion inversion; state = kzalloc(sizeof (struct stb0899_state), GFP_KERNEL); if (state == NULL) goto error; - inversion = config->inversion; state->verbose = &verbose; state->config = config; state->i2c = i2c; state->frontend.ops = stb0899_ops; state->frontend.demodulator_priv = state; - state->internal.inversion = inversion; + /* use configured inversion as default -- we'll later autodetect inversion */ + state->internal.inversion = config->inversion; stb0899_wakeup(&state->frontend); if (stb0899_get_dev_id(state) == -ENODEV) { diff --git a/drivers/media/dvb-frontends/stb0899_drv.h b/drivers/media/dvb-frontends/stb0899_drv.h index 8d26ff6eb1db..139264d19263 100644 --- a/drivers/media/dvb-frontends/stb0899_drv.h +++ b/drivers/media/dvb-frontends/stb0899_drv.h @@ -45,9 +45,8 @@ struct stb0899_s2_reg { }; enum stb0899_inversion { - IQ_SWAP_OFF = 0, - IQ_SWAP_ON, - IQ_SWAP_AUTO + IQ_SWAP_OFF = +1, /* inversion affects the sign of e. g. */ + IQ_SWAP_ON = -1, /* the derotator frequency register */ }; #define STB0899_GPIO00 0xf140 diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index f981d50a2a8c..b2cd8ca51af7 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -245,6 +245,15 @@ config VIDEO_KS0127 To compile this driver as a module, choose M here: the module will be called ks0127. +config VIDEO_ML86V7667 + tristate "OKI ML86V7667 video decoder" + depends on VIDEO_V4L2 && I2C + ---help--- + Support for the OKI Semiconductor ML86V7667 video decoder. + + To compile this driver as a module, choose M here: the + module will be called ml86v7667. + config VIDEO_SAA7110 tristate "Philips SAA7110 video decoder" depends on VIDEO_V4L2 && I2C @@ -425,6 +434,15 @@ config VIDEO_AK881X help Video output driver for AKM AK8813 and AK8814 TV encoders +config VIDEO_THS8200 + tristate "Texas Instruments THS8200 video encoder" + depends on VIDEO_V4L2 && I2C + ---help--- + Support for the Texas Instruments THS8200 video encoder. + + To compile this driver as a module, choose M here: the + module will be called ths8200. + comment "Camera sensor devices" config VIDEO_APTINA_PLL diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index 720f42d9d9f4..dc20653bb5ad 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_VIDEO_BT856) += bt856.o obj-$(CONFIG_VIDEO_BT866) += bt866.o obj-$(CONFIG_VIDEO_KS0127) += ks0127.o obj-$(CONFIG_VIDEO_THS7303) += ths7303.o +obj-$(CONFIG_VIDEO_THS8200) += ths8200.o obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o obj-$(CONFIG_VIDEO_TVP514X) += tvp514x.o obj-$(CONFIG_VIDEO_TVP7002) += tvp7002.o @@ -70,3 +71,4 @@ obj-$(CONFIG_VIDEO_AS3645A) += as3645a.o obj-$(CONFIG_VIDEO_SMIAPP_PLL) += smiapp-pll.o obj-$(CONFIG_VIDEO_AK881X) += ak881x.o obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o +obj-$(CONFIG_VIDEO_ML86V7667) += ml86v7667.o diff --git a/drivers/media/i2c/ad9389b.c b/drivers/media/i2c/ad9389b.c index 58344b6c3a55..ba4364dfae66 100644 --- a/drivers/media/i2c/ad9389b.c +++ b/drivers/media/i2c/ad9389b.c @@ -32,7 +32,6 @@ #include <linux/workqueue.h> #include <linux/v4l2-dv-timings.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> #include <media/v4l2-common.h> #include <media/v4l2-ctrls.h> #include <media/ad9389b.h> @@ -343,12 +342,6 @@ static const struct v4l2_ctrl_ops ad9389b_ctrl_ops = { #ifdef CONFIG_VIDEO_ADV_DEBUG static int ad9389b_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; reg->val = ad9389b_rd(sd, reg->reg & 0xff); reg->size = 1; return 0; @@ -356,24 +349,11 @@ static int ad9389b_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register * static int ad9389b_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; ad9389b_wr(sd, reg->reg & 0xff, reg->val & 0xff); return 0; } #endif -static int ad9389b_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_AD9389B, 0); -} - static int ad9389b_log_status(struct v4l2_subdev *sd) { struct ad9389b_state *state = get_ad9389b_state(sd); @@ -600,7 +580,6 @@ static int ad9389b_isr(struct v4l2_subdev *sd, u32 status, bool *handled) static const struct v4l2_subdev_core_ops ad9389b_core_ops = { .log_status = ad9389b_log_status, - .g_chip_ident = ad9389b_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = ad9389b_g_register, .s_register = ad9389b_s_register, @@ -1188,15 +1167,14 @@ static int ad9389b_probe(struct i2c_client *client, const struct i2c_device_id * v4l_dbg(1, debug, client, "detecting ad9389b client on address 0x%x\n", client->addr << 1); - state = kzalloc(sizeof(struct ad9389b_state), GFP_KERNEL); + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (!state) return -ENOMEM; /* Platform data */ if (pdata == NULL) { v4l_err(client, "No platform data!\n"); - err = -ENODEV; - goto err_free; + return -ENODEV; } memcpy(&state->pdata, pdata, sizeof(state->pdata)); @@ -1251,12 +1229,14 @@ static int ad9389b_probe(struct i2c_client *client, const struct i2c_device_id * state->edid_i2c_client = i2c_new_dummy(client->adapter, (0x7e>>1)); if (state->edid_i2c_client == NULL) { v4l2_err(sd, "failed to register edid i2c client\n"); + err = -ENOMEM; goto err_entity; } state->work_queue = create_singlethread_workqueue(sd->name); if (state->work_queue == NULL) { v4l2_err(sd, "could not create workqueue\n"); + err = -ENOMEM; goto err_unreg; } @@ -1276,8 +1256,6 @@ err_entity: media_entity_cleanup(&sd->entity); err_hdl: v4l2_ctrl_handler_free(&state->hdl); -err_free: - kfree(state); return err; } @@ -1302,15 +1280,14 @@ static int ad9389b_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); media_entity_cleanup(&sd->entity); v4l2_ctrl_handler_free(sd->ctrl_handler); - kfree(get_ad9389b_state(sd)); return 0; } /* ----------------------------------------------------------------------- */ static struct i2c_device_id ad9389b_id[] = { - { "ad9389b", V4L2_IDENT_AD9389B }, - { "ad9889b", V4L2_IDENT_AD9389B }, + { "ad9389b", 0 }, + { "ad9889b", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, ad9389b_id); diff --git a/drivers/media/i2c/adp1653.c b/drivers/media/i2c/adp1653.c index ef75abe5984c..873fe1949e98 100644 --- a/drivers/media/i2c/adp1653.c +++ b/drivers/media/i2c/adp1653.c @@ -417,7 +417,7 @@ static int adp1653_probe(struct i2c_client *client, if (client->dev.platform_data == NULL) return -ENODEV; - flash = kzalloc(sizeof(*flash), GFP_KERNEL); + flash = devm_kzalloc(&client->dev, sizeof(*flash), GFP_KERNEL); if (flash == NULL) return -ENOMEM; @@ -443,7 +443,6 @@ static int adp1653_probe(struct i2c_client *client, free_and_quit: v4l2_ctrl_handler_free(&flash->ctrls); - kfree(flash); return ret; } @@ -455,7 +454,7 @@ static int adp1653_remove(struct i2c_client *client) v4l2_device_unregister_subdev(&flash->subdev); v4l2_ctrl_handler_free(&flash->ctrls); media_entity_cleanup(&flash->subdev.entity); - kfree(flash); + return 0; } diff --git a/drivers/media/i2c/adv7170.c b/drivers/media/i2c/adv7170.c index 6bc01fb98ff8..04bb29720aaf 100644 --- a/drivers/media/i2c/adv7170.c +++ b/drivers/media/i2c/adv7170.c @@ -36,7 +36,6 @@ #include <linux/i2c.h> #include <linux/videodev2.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> MODULE_DESCRIPTION("Analog Devices ADV7170 video encoder driver"); MODULE_AUTHOR("Maxim Yevtyushkin"); @@ -317,19 +316,8 @@ static int adv7170_s_fmt(struct v4l2_subdev *sd, return ret; } -static int adv7170_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7170, 0); -} - /* ----------------------------------------------------------------------- */ -static const struct v4l2_subdev_core_ops adv7170_core_ops = { - .g_chip_ident = adv7170_g_chip_ident, -}; - static const struct v4l2_subdev_video_ops adv7170_video_ops = { .s_std_output = adv7170_s_std_output, .s_routing = adv7170_s_routing, @@ -339,7 +327,6 @@ static const struct v4l2_subdev_video_ops adv7170_video_ops = { }; static const struct v4l2_subdev_ops adv7170_ops = { - .core = &adv7170_core_ops, .video = &adv7170_video_ops, }; @@ -359,7 +346,7 @@ static int adv7170_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - encoder = kzalloc(sizeof(struct adv7170), GFP_KERNEL); + encoder = devm_kzalloc(&client->dev, sizeof(*encoder), GFP_KERNEL); if (encoder == NULL) return -ENOMEM; sd = &encoder->sd; @@ -384,7 +371,6 @@ static int adv7170_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); v4l2_device_unregister_subdev(sd); - kfree(to_adv7170(sd)); return 0; } diff --git a/drivers/media/i2c/adv7175.c b/drivers/media/i2c/adv7175.c index c7640fab5730..b88f3b3d5ed9 100644 --- a/drivers/media/i2c/adv7175.c +++ b/drivers/media/i2c/adv7175.c @@ -32,7 +32,6 @@ #include <linux/i2c.h> #include <linux/videodev2.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> MODULE_DESCRIPTION("Analog Devices ADV7175 video encoder driver"); MODULE_AUTHOR("Dave Perks"); @@ -355,13 +354,6 @@ static int adv7175_s_fmt(struct v4l2_subdev *sd, return ret; } -static int adv7175_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7175, 0); -} - static int adv7175_s_power(struct v4l2_subdev *sd, int on) { if (on) @@ -375,7 +367,6 @@ static int adv7175_s_power(struct v4l2_subdev *sd, int on) /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops adv7175_core_ops = { - .g_chip_ident = adv7175_g_chip_ident, .init = adv7175_init, .s_power = adv7175_s_power, }; @@ -409,7 +400,7 @@ static int adv7175_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - encoder = kzalloc(sizeof(struct adv7175), GFP_KERNEL); + encoder = devm_kzalloc(&client->dev, sizeof(*encoder), GFP_KERNEL); if (encoder == NULL) return -ENOMEM; sd = &encoder->sd; @@ -434,7 +425,6 @@ static int adv7175_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); v4l2_device_unregister_subdev(sd); - kfree(to_adv7175(sd)); return 0; } diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c index afd561ab190d..d7d99f1c69e4 100644 --- a/drivers/media/i2c/adv7180.c +++ b/drivers/media/i2c/adv7180.c @@ -1,6 +1,8 @@ /* * 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 @@ -27,7 +29,6 @@ #include <linux/videodev2.h> #include <media/v4l2-device.h> #include <media/v4l2-ctrls.h> -#include <media/v4l2-chip-ident.h> #include <linux/mutex.h> #define ADV7180_INPUT_CONTROL_REG 0x00 @@ -272,14 +273,6 @@ static int adv7180_g_input_status(struct v4l2_subdev *sd, u32 *status) return ret; } -static int adv7180_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7180, 0); -} - static int adv7180_s_std(struct v4l2_subdev *sd, v4l2_std_id std) { struct adv7180_state *state = to_state(sd); @@ -397,14 +390,57 @@ static void adv7180_exit_controls(struct adv7180_state *state) v4l2_ctrl_handler_free(&state->ctrl_hdl); } +static int adv7180_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index, + enum v4l2_mbus_pixelcode *code) +{ + if (index > 0) + return -EINVAL; + + *code = V4L2_MBUS_FMT_YUYV8_2X8; + + return 0; +} + +static int adv7180_mbus_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *fmt) +{ + struct adv7180_state *state = to_state(sd); + + fmt->code = V4L2_MBUS_FMT_YUYV8_2X8; + fmt->colorspace = V4L2_COLORSPACE_SMPTE170M; + fmt->field = V4L2_FIELD_INTERLACED; + fmt->width = 720; + fmt->height = state->curr_norm & V4L2_STD_525_60 ? 480 : 576; + + return 0; +} + +static int adv7180_g_mbus_config(struct v4l2_subdev *sd, + struct v4l2_mbus_config *cfg) +{ + /* + * The ADV7180 sensor supports BT.601/656 output modes. + * The BT.656 is default and not yet configurable by s/w. + */ + cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING | + V4L2_MBUS_DATA_ACTIVE_HIGH; + cfg->type = V4L2_MBUS_BT656; + + return 0; +} + static const struct v4l2_subdev_video_ops adv7180_video_ops = { .querystd = adv7180_querystd, .g_input_status = adv7180_g_input_status, .s_routing = adv7180_s_routing, + .enum_mbus_fmt = adv7180_enum_mbus_fmt, + .try_mbus_fmt = adv7180_mbus_fmt, + .g_mbus_fmt = adv7180_mbus_fmt, + .s_mbus_fmt = adv7180_mbus_fmt, + .g_mbus_config = adv7180_g_mbus_config, }; static const struct v4l2_subdev_core_ops adv7180_core_ops = { - .g_chip_ident = adv7180_g_chip_ident, .s_std = adv7180_s_std, }; @@ -555,7 +591,7 @@ static int adv7180_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%02x (%s)\n", client->addr, client->adapter->name); - state = kzalloc(sizeof(struct adv7180_state), GFP_KERNEL); + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (state == NULL) { ret = -ENOMEM; goto err; @@ -582,7 +618,6 @@ err_free_ctrl: err_unreg_subdev: mutex_destroy(&state->mutex); v4l2_device_unregister_subdev(sd); - kfree(state); err: printk(KERN_ERR KBUILD_MODNAME ": Failed to probe: %d\n", ret); return ret; @@ -607,7 +642,6 @@ static int adv7180_remove(struct i2c_client *client) mutex_destroy(&state->mutex); v4l2_device_unregister_subdev(sd); - kfree(to_state(sd)); return 0; } @@ -616,9 +650,10 @@ static const struct i2c_device_id adv7180_id[] = { {}, }; -#ifdef CONFIG_PM -static int adv7180_suspend(struct i2c_client *client, pm_message_t state) +#ifdef CONFIG_PM_SLEEP +static int adv7180_suspend(struct device *dev) { + struct i2c_client *client = to_i2c_client(dev); int ret; ret = i2c_smbus_write_byte_data(client, ADV7180_PWR_MAN_REG, @@ -628,8 +663,9 @@ static int adv7180_suspend(struct i2c_client *client, pm_message_t state) return 0; } -static int adv7180_resume(struct i2c_client *client) +static int adv7180_resume(struct device *dev) { + struct i2c_client *client = to_i2c_client(dev); struct v4l2_subdev *sd = i2c_get_clientdata(client); struct adv7180_state *state = to_state(sd); int ret; @@ -643,6 +679,12 @@ static int adv7180_resume(struct i2c_client *client) return ret; return 0; } + +static SIMPLE_DEV_PM_OPS(adv7180_pm_ops, adv7180_suspend, adv7180_resume); +#define ADV7180_PM_OPS (&adv7180_pm_ops) + +#else +#define ADV7180_PM_OPS NULL #endif MODULE_DEVICE_TABLE(i2c, adv7180_id); @@ -651,13 +693,10 @@ static struct i2c_driver adv7180_driver = { .driver = { .owner = THIS_MODULE, .name = KBUILD_MODNAME, + .pm = ADV7180_PM_OPS, }, .probe = adv7180_probe, .remove = adv7180_remove, -#ifdef CONFIG_PM - .suspend = adv7180_suspend, - .resume = adv7180_resume, -#endif .id_table = adv7180_id, }; diff --git a/drivers/media/i2c/adv7183.c b/drivers/media/i2c/adv7183.c index 56a1fa4af0fe..6f738d8e3a8f 100644 --- a/drivers/media/i2c/adv7183.c +++ b/drivers/media/i2c/adv7183.c @@ -28,7 +28,6 @@ #include <linux/videodev2.h> #include <media/adv7183.h> -#include <media/v4l2-chip-ident.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> @@ -375,28 +374,28 @@ static int adv7183_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) reg = adv7183_read(sd, ADV7183_STATUS_1); switch ((reg >> 0x4) & 0x7) { case 0: - *std = V4L2_STD_NTSC; + *std &= V4L2_STD_NTSC; break; case 1: - *std = V4L2_STD_NTSC_443; + *std &= V4L2_STD_NTSC_443; break; case 2: - *std = V4L2_STD_PAL_M; + *std &= V4L2_STD_PAL_M; break; case 3: - *std = V4L2_STD_PAL_60; + *std &= V4L2_STD_PAL_60; break; case 4: - *std = V4L2_STD_PAL; + *std &= V4L2_STD_PAL; break; case 5: - *std = V4L2_STD_SECAM; + *std &= V4L2_STD_SECAM; break; case 6: - *std = V4L2_STD_PAL_Nc; + *std &= V4L2_STD_PAL_Nc; break; case 7: - *std = V4L2_STD_SECAM; + *std &= V4L2_STD_SECAM; break; default: *std = V4L2_STD_UNKNOWN; @@ -474,34 +473,16 @@ static int adv7183_s_stream(struct v4l2_subdev *sd, int enable) struct adv7183 *decoder = to_adv7183(sd); if (enable) - gpio_direction_output(decoder->oe_pin, 0); + gpio_set_value(decoder->oe_pin, 0); else - gpio_direction_output(decoder->oe_pin, 1); + gpio_set_value(decoder->oe_pin, 1); udelay(1); return 0; } -static int adv7183_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - int rev; - struct i2c_client *client = v4l2_get_subdevdata(sd); - - /* 0x11 for adv7183, 0x13 for adv7183b */ - rev = adv7183_read(sd, ADV7183_IDENT); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7183, rev); -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int adv7183_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; reg->val = adv7183_read(sd, reg->reg & 0xff); reg->size = 1; return 0; @@ -509,12 +490,6 @@ static int adv7183_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register * static int adv7183_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; adv7183_write(sd, reg->reg & 0xff, reg->val & 0xff); return 0; } @@ -529,7 +504,6 @@ static const struct v4l2_subdev_core_ops adv7183_core_ops = { .g_std = adv7183_g_std, .s_std = adv7183_s_std, .reset = adv7183_reset, - .g_chip_ident = adv7183_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = adv7183_g_register, .s_register = adv7183_s_register, @@ -573,23 +547,24 @@ static int adv7183_probe(struct i2c_client *client, if (pin_array == NULL) return -EINVAL; - decoder = kzalloc(sizeof(struct adv7183), GFP_KERNEL); + decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL); if (decoder == NULL) return -ENOMEM; decoder->reset_pin = pin_array[0]; decoder->oe_pin = pin_array[1]; - if (gpio_request(decoder->reset_pin, "ADV7183 Reset")) { + if (devm_gpio_request_one(&client->dev, decoder->reset_pin, + GPIOF_OUT_INIT_LOW, "ADV7183 Reset")) { v4l_err(client, "failed to request GPIO %d\n", decoder->reset_pin); - ret = -EBUSY; - goto err_free_decoder; + return -EBUSY; } - if (gpio_request(decoder->oe_pin, "ADV7183 Output Enable")) { + if (devm_gpio_request_one(&client->dev, decoder->oe_pin, + GPIOF_OUT_INIT_HIGH, + "ADV7183 Output Enable")) { v4l_err(client, "failed to request GPIO %d\n", decoder->oe_pin); - ret = -EBUSY; - goto err_free_reset; + return -EBUSY; } sd = &decoder->sd; @@ -611,7 +586,7 @@ static int adv7183_probe(struct i2c_client *client, ret = hdl->error; v4l2_ctrl_handler_free(hdl); - goto err_free_oe; + return ret; } /* v4l2 doesn't support an autodetect standard, pick PAL as default */ @@ -619,12 +594,10 @@ static int adv7183_probe(struct i2c_client *client, decoder->input = ADV7183_COMPOSITE4; decoder->output = ADV7183_8BIT_OUT; - gpio_direction_output(decoder->oe_pin, 1); /* reset chip */ - gpio_direction_output(decoder->reset_pin, 0); /* reset pulse width at least 5ms */ mdelay(10); - gpio_direction_output(decoder->reset_pin, 1); + gpio_set_value(decoder->reset_pin, 1); /* wait 5ms before any further i2c writes are performed */ mdelay(5); @@ -638,29 +611,18 @@ static int adv7183_probe(struct i2c_client *client, ret = v4l2_ctrl_handler_setup(hdl); if (ret) { v4l2_ctrl_handler_free(hdl); - goto err_free_oe; + return ret; } return 0; -err_free_oe: - gpio_free(decoder->oe_pin); -err_free_reset: - gpio_free(decoder->reset_pin); -err_free_decoder: - kfree(decoder); - return ret; } static int adv7183_remove(struct i2c_client *client) { struct v4l2_subdev *sd = i2c_get_clientdata(client); - struct adv7183 *decoder = to_adv7183(sd); v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(sd->ctrl_handler); - gpio_free(decoder->oe_pin); - gpio_free(decoder->reset_pin); - kfree(decoder); return 0; } diff --git a/drivers/media/i2c/adv7343.c b/drivers/media/i2c/adv7343.c index 9fc2b985df0e..7606218ec4a7 100644 --- a/drivers/media/i2c/adv7343.c +++ b/drivers/media/i2c/adv7343.c @@ -28,7 +28,6 @@ #include <media/adv7343.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> #include <media/v4l2-ctrls.h> #include "adv7343_regs.h" @@ -311,21 +310,12 @@ static int adv7343_s_ctrl(struct v4l2_ctrl *ctrl) return -EINVAL; } -static int adv7343_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7343, 0); -} - static const struct v4l2_ctrl_ops adv7343_ctrl_ops = { .s_ctrl = adv7343_s_ctrl, }; static const struct v4l2_subdev_core_ops adv7343_core_ops = { .log_status = adv7343_log_status, - .g_chip_ident = adv7343_g_chip_ident, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, diff --git a/drivers/media/i2c/adv7393.c b/drivers/media/i2c/adv7393.c index 3dc6098c7267..558f19154eb9 100644 --- a/drivers/media/i2c/adv7393.c +++ b/drivers/media/i2c/adv7393.c @@ -33,7 +33,6 @@ #include <media/adv7393.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> #include <media/v4l2-ctrls.h> #include "adv7393_regs.h" @@ -301,21 +300,12 @@ static int adv7393_s_ctrl(struct v4l2_ctrl *ctrl) return -EINVAL; } -static int adv7393_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7393, 0); -} - static const struct v4l2_ctrl_ops adv7393_ctrl_ops = { .s_ctrl = adv7393_s_ctrl, }; static const struct v4l2_subdev_core_ops adv7393_core_ops = { .log_status = adv7393_log_status, - .g_chip_ident = adv7393_g_chip_ident, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, @@ -410,7 +400,7 @@ static int adv7393_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - state = kzalloc(sizeof(struct adv7393_state), GFP_KERNEL); + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (state == NULL) return -ENOMEM; @@ -444,16 +434,13 @@ static int adv7393_probe(struct i2c_client *client, int err = state->hdl.error; v4l2_ctrl_handler_free(&state->hdl); - kfree(state); return err; } v4l2_ctrl_handler_setup(&state->hdl); err = adv7393_initialize(&state->sd); - if (err) { + if (err) v4l2_ctrl_handler_free(&state->hdl); - kfree(state); - } return err; } @@ -464,7 +451,6 @@ static int adv7393_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&state->hdl); - kfree(state); return 0; } diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index 31a63c9324fe..1d675b58fd71 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -38,7 +38,6 @@ #include <linux/v4l2-dv-timings.h> #include <media/v4l2-device.h> #include <media/v4l2-ctrls.h> -#include <media/v4l2-chip-ident.h> #include <media/adv7604.h> static int debug; @@ -643,12 +642,6 @@ static void adv7604_inv_register(struct v4l2_subdev *sd) static int adv7604_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; reg->size = 1; switch (reg->reg >> 8) { case 0: @@ -701,12 +694,6 @@ static int adv7604_g_register(struct v4l2_subdev *sd, static int adv7604_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; switch (reg->reg >> 8) { case 0: io_write(sd, reg->reg & 0xff, reg->val & 0xff); @@ -984,14 +971,6 @@ static int adv7604_s_ctrl(struct v4l2_ctrl *ctrl) return -EINVAL; } -static int adv7604_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7604, 0); -} - /* ----------------------------------------------------------------------- */ static inline bool no_power(struct v4l2_subdev *sd) @@ -1787,7 +1766,6 @@ static const struct v4l2_subdev_core_ops adv7604_core_ops = { .s_ctrl = v4l2_subdev_s_ctrl, .queryctrl = v4l2_subdev_queryctrl, .querymenu = v4l2_subdev_querymenu, - .g_chip_ident = adv7604_g_chip_ident, .interrupt_service_routine = adv7604_isr, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = adv7604_g_register, @@ -1968,7 +1946,7 @@ static int adv7604_probe(struct i2c_client *client, v4l_dbg(1, debug, client, "detecting adv7604 client on address 0x%x\n", client->addr << 1); - state = kzalloc(sizeof(struct adv7604_state), GFP_KERNEL); + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (!state) { v4l_err(client, "Could not allocate adv7604_state memory!\n"); return -ENOMEM; @@ -1977,8 +1955,7 @@ static int adv7604_probe(struct i2c_client *client, /* platform data */ if (!pdata) { v4l_err(client, "No platform data!\n"); - err = -ENODEV; - goto err_state; + return -ENODEV; } memcpy(&state->pdata, pdata, sizeof(state->pdata)); @@ -1991,8 +1968,7 @@ static int adv7604_probe(struct i2c_client *client, if (adv_smbus_read_byte_data_check(client, 0xfb, false) != 0x68) { v4l2_info(sd, "not an adv7604 on address 0x%x\n", client->addr << 1); - err = -ENODEV; - goto err_state; + return -ENODEV; } /* control handlers */ @@ -2093,8 +2069,6 @@ err_i2c: adv7604_unregister_clients(state); err_hdl: v4l2_ctrl_handler_free(hdl); -err_state: - kfree(state); return err; } @@ -2111,7 +2085,6 @@ static int adv7604_remove(struct i2c_client *client) media_entity_cleanup(&sd->entity); adv7604_unregister_clients(to_state(sd)); v4l2_ctrl_handler_free(sd->ctrl_handler); - kfree(to_state(sd)); return 0; } diff --git a/drivers/media/i2c/ak881x.c b/drivers/media/i2c/ak881x.c index fd47465e4f6a..c14e66756b98 100644 --- a/drivers/media/i2c/ak881x.c +++ b/drivers/media/i2c/ak881x.c @@ -16,7 +16,6 @@ #include <linux/module.h> #include <media/ak881x.h> -#include <media/v4l2-chip-ident.h> #include <media/v4l2-common.h> #include <media/v4l2-device.h> @@ -33,7 +32,6 @@ struct ak881x { struct v4l2_subdev subdev; struct ak881x_pdata *pdata; unsigned int lines; - int id; /* DEVICE_ID code V4L2_IDENT_AK881X code from v4l2-chip-ident.h */ char revision; /* DEVICE_REVISION content */ }; @@ -62,36 +60,16 @@ static struct ak881x *to_ak881x(const struct i2c_client *client) return container_of(i2c_get_clientdata(client), struct ak881x, subdev); } -static int ak881x_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *id) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ak881x *ak881x = to_ak881x(client); - - if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) - return -EINVAL; - - if (id->match.addr != client->addr) - return -ENODEV; - - id->ident = ak881x->id; - id->revision = ak881x->revision; - - return 0; -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int ak881x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x26) + if (reg->reg > 0x26) return -EINVAL; - if (reg->match.addr != client->addr) - return -ENODEV; - + reg->size = 1; reg->val = reg_read(client, reg->reg); if (reg->val > 0xffff) @@ -105,12 +83,9 @@ static int ak881x_s_register(struct v4l2_subdev *sd, { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x26) + if (reg->reg > 0x26) return -EINVAL; - if (reg->match.addr != client->addr) - return -ENODEV; - if (reg_write(client, reg->reg, reg->val) < 0) return -EIO; @@ -229,7 +204,6 @@ static int ak881x_s_stream(struct v4l2_subdev *sd, int enable) } static struct v4l2_subdev_core_ops ak881x_subdev_core_ops = { - .g_chip_ident = ak881x_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = ak881x_g_register, .s_register = ak881x_s_register, @@ -264,7 +238,7 @@ static int ak881x_probe(struct i2c_client *client, return -EIO; } - ak881x = kzalloc(sizeof(struct ak881x), GFP_KERNEL); + ak881x = devm_kzalloc(&client->dev, sizeof(*ak881x), GFP_KERNEL); if (!ak881x) return -ENOMEM; @@ -274,15 +248,11 @@ static int ak881x_probe(struct i2c_client *client, switch (data) { case 0x13: - ak881x->id = V4L2_IDENT_AK8813; - break; case 0x14: - ak881x->id = V4L2_IDENT_AK8814; break; default: dev_err(&client->dev, "No ak881x chip detected, register read %x\n", data); - kfree(ak881x); return -ENODEV; } @@ -331,7 +301,6 @@ static int ak881x_remove(struct i2c_client *client) struct ak881x *ak881x = to_ak881x(client); v4l2_device_unregister_subdev(&ak881x->subdev); - kfree(ak881x); return 0; } diff --git a/drivers/media/i2c/as3645a.c b/drivers/media/i2c/as3645a.c index 58d523f2648f..301084b07887 100644 --- a/drivers/media/i2c/as3645a.c +++ b/drivers/media/i2c/as3645a.c @@ -813,7 +813,7 @@ static int as3645a_probe(struct i2c_client *client, if (client->dev.platform_data == NULL) return -ENODEV; - flash = kzalloc(sizeof(*flash), GFP_KERNEL); + flash = devm_kzalloc(&client->dev, sizeof(*flash), GFP_KERNEL); if (flash == NULL) return -ENOMEM; @@ -838,10 +838,8 @@ static int as3645a_probe(struct i2c_client *client, flash->led_mode = V4L2_FLASH_LED_MODE_NONE; done: - if (ret < 0) { + if (ret < 0) v4l2_ctrl_handler_free(&flash->ctrls); - kfree(flash); - } return ret; } @@ -855,7 +853,6 @@ static int as3645a_remove(struct i2c_client *client) v4l2_ctrl_handler_free(&flash->ctrls); media_entity_cleanup(&flash->subdev.entity); mutex_destroy(&flash->power_lock); - kfree(flash); return 0; } diff --git a/drivers/media/i2c/bt819.c b/drivers/media/i2c/bt819.c index 377bf05b1efd..369cf6ff88f7 100644 --- a/drivers/media/i2c/bt819.c +++ b/drivers/media/i2c/bt819.c @@ -36,7 +36,6 @@ #include <linux/videodev2.h> #include <linux/slab.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> #include <media/v4l2-ctrls.h> #include <media/bt819.h> @@ -57,7 +56,6 @@ struct bt819 { unsigned char reg[32]; v4l2_std_id norm; - int ident; int input; int enable; }; @@ -217,15 +215,17 @@ static int bt819_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pstd) struct bt819 *decoder = to_bt819(sd); int status = bt819_read(decoder, 0x00); int res = V4L2_IN_ST_NO_SIGNAL; - v4l2_std_id std; + v4l2_std_id std = pstd ? *pstd : V4L2_STD_ALL; if ((status & 0x80)) res = 0; + else + std = V4L2_STD_UNKNOWN; if ((status & 0x10)) - std = V4L2_STD_PAL; + std &= V4L2_STD_PAL; else - std = V4L2_STD_NTSC; + std &= V4L2_STD_NTSC; if (pstd) *pstd = std; if (pstatus) @@ -373,14 +373,6 @@ static int bt819_s_ctrl(struct v4l2_ctrl *ctrl) return 0; } -static int bt819_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct bt819 *decoder = to_bt819(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, decoder->ident, 0); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_ctrl_ops bt819_ctrl_ops = { @@ -388,7 +380,6 @@ static const struct v4l2_ctrl_ops bt819_ctrl_ops = { }; static const struct v4l2_subdev_core_ops bt819_core_ops = { - .g_chip_ident = bt819_g_chip_ident, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, @@ -425,7 +416,7 @@ static int bt819_probe(struct i2c_client *client, if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -ENODEV; - decoder = kzalloc(sizeof(struct bt819), GFP_KERNEL); + decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL); if (decoder == NULL) return -ENOMEM; sd = &decoder->sd; @@ -435,15 +426,12 @@ static int bt819_probe(struct i2c_client *client, switch (ver & 0xf0) { case 0x70: name = "bt819a"; - decoder->ident = V4L2_IDENT_BT819A; break; case 0x60: name = "bt817a"; - decoder->ident = V4L2_IDENT_BT817A; break; case 0x20: name = "bt815a"; - decoder->ident = V4L2_IDENT_BT815A; break; default: v4l2_dbg(1, debug, sd, @@ -476,7 +464,6 @@ static int bt819_probe(struct i2c_client *client, int err = decoder->hdl.error; v4l2_ctrl_handler_free(&decoder->hdl); - kfree(decoder); return err; } v4l2_ctrl_handler_setup(&decoder->hdl); @@ -490,7 +477,6 @@ static int bt819_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&decoder->hdl); - kfree(decoder); return 0; } diff --git a/drivers/media/i2c/bt856.c b/drivers/media/i2c/bt856.c index 7e5bd365c239..7fc163d0253c 100644 --- a/drivers/media/i2c/bt856.c +++ b/drivers/media/i2c/bt856.c @@ -36,7 +36,6 @@ #include <linux/i2c.h> #include <linux/videodev2.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> MODULE_DESCRIPTION("Brooktree-856A video encoder driver"); MODULE_AUTHOR("Mike Bernson & Dave Perks"); @@ -177,17 +176,9 @@ static int bt856_s_routing(struct v4l2_subdev *sd, return 0; } -static int bt856_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_BT856, 0); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops bt856_core_ops = { - .g_chip_ident = bt856_g_chip_ident, .init = bt856_init, }; @@ -216,7 +207,7 @@ static int bt856_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - encoder = kzalloc(sizeof(struct bt856), GFP_KERNEL); + encoder = devm_kzalloc(&client->dev, sizeof(*encoder), GFP_KERNEL); if (encoder == NULL) return -ENOMEM; sd = &encoder->sd; @@ -250,7 +241,6 @@ static int bt856_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); v4l2_device_unregister_subdev(sd); - kfree(to_bt856(sd)); return 0; } diff --git a/drivers/media/i2c/bt866.c b/drivers/media/i2c/bt866.c index 905320b67a1c..a8bf10fc665d 100644 --- a/drivers/media/i2c/bt866.c +++ b/drivers/media/i2c/bt866.c @@ -36,7 +36,6 @@ #include <linux/i2c.h> #include <linux/videodev2.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> MODULE_DESCRIPTION("Brooktree-866 video encoder driver"); MODULE_AUTHOR("Mike Bernson & Dave Perks"); @@ -175,26 +174,14 @@ static int bt866_s_routing(struct v4l2_subdev *sd, bt866_write(client, 0xdc, val); #endif -static int bt866_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_BT866, 0); -} - /* ----------------------------------------------------------------------- */ -static const struct v4l2_subdev_core_ops bt866_core_ops = { - .g_chip_ident = bt866_g_chip_ident, -}; - static const struct v4l2_subdev_video_ops bt866_video_ops = { .s_std_output = bt866_s_std_output, .s_routing = bt866_s_routing, }; static const struct v4l2_subdev_ops bt866_ops = { - .core = &bt866_core_ops, .video = &bt866_video_ops, }; @@ -207,7 +194,7 @@ static int bt866_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - encoder = kzalloc(sizeof(*encoder), GFP_KERNEL); + encoder = devm_kzalloc(&client->dev, sizeof(*encoder), GFP_KERNEL); if (encoder == NULL) return -ENOMEM; sd = &encoder->sd; @@ -220,7 +207,6 @@ static int bt866_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); v4l2_device_unregister_subdev(sd); - kfree(to_bt866(sd)); return 0; } diff --git a/drivers/media/i2c/cs5345.c b/drivers/media/i2c/cs5345.c index 1d2f7c8512b5..34b76a9e7515 100644 --- a/drivers/media/i2c/cs5345.c +++ b/drivers/media/i2c/cs5345.c @@ -24,7 +24,6 @@ #include <linux/videodev2.h> #include <linux/slab.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> #include <media/v4l2-ctrls.h> MODULE_DESCRIPTION("i2c device driver for cs5345 Audio ADC"); @@ -99,12 +98,6 @@ static int cs5345_s_ctrl(struct v4l2_ctrl *ctrl) #ifdef CONFIG_VIDEO_ADV_DEBUG static int cs5345_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; reg->size = 1; reg->val = cs5345_read(sd, reg->reg & 0x1f); return 0; @@ -112,24 +105,11 @@ static int cs5345_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *r static int cs5345_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; cs5345_write(sd, reg->reg & 0x1f, reg->val & 0xff); return 0; } #endif -static int cs5345_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_CS5345, 0); -} - static int cs5345_log_status(struct v4l2_subdev *sd) { u8 v = cs5345_read(sd, 0x09) & 7; @@ -152,7 +132,6 @@ static const struct v4l2_ctrl_ops cs5345_ctrl_ops = { static const struct v4l2_subdev_core_ops cs5345_core_ops = { .log_status = cs5345_log_status, - .g_chip_ident = cs5345_g_chip_ident, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, @@ -190,7 +169,7 @@ static int cs5345_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - state = kzalloc(sizeof(struct cs5345_state), GFP_KERNEL); + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (state == NULL) return -ENOMEM; sd = &state->sd; @@ -206,7 +185,6 @@ static int cs5345_probe(struct i2c_client *client, int err = state->hdl.error; v4l2_ctrl_handler_free(&state->hdl); - kfree(state); return err; } /* set volume/mute */ @@ -227,7 +205,6 @@ static int cs5345_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&state->hdl); - kfree(state); return 0; } diff --git a/drivers/media/i2c/cs53l32a.c b/drivers/media/i2c/cs53l32a.c index b293912206eb..27400c16ef9a 100644 --- a/drivers/media/i2c/cs53l32a.c +++ b/drivers/media/i2c/cs53l32a.c @@ -28,7 +28,6 @@ #include <linux/i2c.h> #include <linux/videodev2.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> #include <media/v4l2-ctrls.h> MODULE_DESCRIPTION("i2c device driver for cs53l32a Audio ADC"); @@ -104,14 +103,6 @@ static int cs53l32a_s_ctrl(struct v4l2_ctrl *ctrl) return -EINVAL; } -static int cs53l32a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, - chip, V4L2_IDENT_CS53l32A, 0); -} - static int cs53l32a_log_status(struct v4l2_subdev *sd) { struct cs53l32a_state *state = to_state(sd); @@ -130,7 +121,6 @@ static const struct v4l2_ctrl_ops cs53l32a_ctrl_ops = { static const struct v4l2_subdev_core_ops cs53l32a_core_ops = { .log_status = cs53l32a_log_status, - .g_chip_ident = cs53l32a_g_chip_ident, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, @@ -175,7 +165,7 @@ static int cs53l32a_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - state = kzalloc(sizeof(struct cs53l32a_state), GFP_KERNEL); + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (state == NULL) return -ENOMEM; sd = &state->sd; @@ -197,7 +187,6 @@ static int cs53l32a_probe(struct i2c_client *client, int err = state->hdl.error; v4l2_ctrl_handler_free(&state->hdl); - kfree(state); return err; } @@ -228,7 +217,6 @@ static int cs53l32a_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&state->hdl); - kfree(state); return 0; } diff --git a/drivers/media/i2c/cx25840/cx25840-core.c b/drivers/media/i2c/cx25840/cx25840-core.c index 12fb9b2eb887..2e3771d57354 100644 --- a/drivers/media/i2c/cx25840/cx25840-core.c +++ b/drivers/media/i2c/cx25840/cx25840-core.c @@ -45,7 +45,6 @@ #include <linux/delay.h> #include <linux/math64.h> #include <media/v4l2-common.h> -#include <media/v4l2-chip-ident.h> #include <media/cx25840.h> #include "cx25840-core.h" @@ -498,7 +497,7 @@ static void cx23885_initialize(struct i2c_client *client) /* Sys PLL */ switch (state->id) { - case V4L2_IDENT_CX23888_AV: + case CX23888_AV: /* * 50.0 MHz * (0xb + 0xe8ba26/0x2000000)/4 = 5 * 28.636363 MHz * 572.73 MHz before post divide @@ -511,7 +510,7 @@ static void cx23885_initialize(struct i2c_client *client) cx25840_write4(client, 0x42c, 0x42600000); cx25840_write4(client, 0x44c, 0x161f1000); break; - case V4L2_IDENT_CX23887_AV: + case CX23887_AV: /* * 25.0 MHz * (0x16 + 0x1d1744c/0x2000000)/4 = 5 * 28.636363 MHz * 572.73 MHz before post divide @@ -519,7 +518,7 @@ static void cx23885_initialize(struct i2c_client *client) cx25840_write4(client, 0x11c, 0x01d1744c); cx25840_write4(client, 0x118, 0x00000416); break; - case V4L2_IDENT_CX23885_AV: + case CX23885_AV: default: /* * 28.636363 MHz * (0x14 + 0x0/0x2000000)/4 = 5 * 28.636363 MHz @@ -546,7 +545,7 @@ static void cx23885_initialize(struct i2c_client *client) /* HVR1850 */ switch (state->id) { - case V4L2_IDENT_CX23888_AV: + case CX23888_AV: /* 888/HVR1250 specific */ cx25840_write4(client, 0x10c, 0x13333333); cx25840_write4(client, 0x108, 0x00000515); @@ -570,7 +569,7 @@ static void cx23885_initialize(struct i2c_client *client) * 48 ksps, 16 bits/sample, x16 multiplier = 12.288 MHz */ switch (state->id) { - case V4L2_IDENT_CX23888_AV: + case CX23888_AV: /* * 50.0 MHz * (0x7 + 0x0bedfa4/0x2000000)/3 = 122.88 MHz * 368.64 MHz before post divide @@ -580,7 +579,7 @@ static void cx23885_initialize(struct i2c_client *client) cx25840_write4(client, 0x114, 0x017dbf48); cx25840_write4(client, 0x110, 0x000a030e); break; - case V4L2_IDENT_CX23887_AV: + case CX23887_AV: /* * 25.0 MHz * (0xe + 0x17dbf48/0x2000000)/3 = 122.88 MHz * 368.64 MHz before post divide @@ -589,7 +588,7 @@ static void cx23885_initialize(struct i2c_client *client) cx25840_write4(client, 0x114, 0x017dbf48); cx25840_write4(client, 0x110, 0x000a030e); break; - case V4L2_IDENT_CX23885_AV: + case CX23885_AV: default: /* * 28.636363 MHz * (0xc + 0x1bf0c9e/0x2000000)/3 = 122.88 MHz @@ -1662,10 +1661,6 @@ static int cx25840_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register * { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; reg->size = 1; reg->val = cx25840_read(client, reg->reg & 0x0fff); return 0; @@ -1675,10 +1670,6 @@ static int cx25840_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_regi { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; cx25840_write(client, reg->reg & 0x0fff, reg->val & 0xff); return 0; } @@ -1938,14 +1929,6 @@ static int cx25840_reset(struct v4l2_subdev *sd, u32 val) return 0; } -static int cx25840_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct cx25840_state *state = to_state(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, state->id, state->rev); -} - static int cx25840_log_status(struct v4l2_subdev *sd) { struct cx25840_state *state = to_state(sd); @@ -5051,7 +5034,6 @@ static const struct v4l2_ctrl_ops cx25840_ctrl_ops = { static const struct v4l2_subdev_core_ops cx25840_core_ops = { .log_status = cx25840_log_status, - .g_chip_ident = cx25840_g_chip_ident, .g_ctrl = v4l2_subdev_g_ctrl, .s_ctrl = v4l2_subdev_s_ctrl, .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, @@ -5128,18 +5110,18 @@ static u32 get_cx2388x_ident(struct i2c_client *client) ret = cx25840_read4(client, 0x300); if (((ret & 0xffff0000) >> 16) == (ret & 0xffff)) { /* No DIF */ - ret = V4L2_IDENT_CX23885_AV; + ret = CX23885_AV; } else { /* CX23887 has a broken DIF, but the registers * appear valid (but unused), good enough to detect. */ - ret = V4L2_IDENT_CX23887_AV; + ret = CX23887_AV; } } else if (cx25840_read4(client, 0x300) & 0x0fffffff) { /* DIF PLL Freq Word reg exists; chip must be a CX23888 */ - ret = V4L2_IDENT_CX23888_AV; + ret = CX23888_AV; } else { v4l_err(client, "Unable to detect h/w, assuming cx23887\n"); - ret = V4L2_IDENT_CX23887_AV; + ret = CX23887_AV; } /* Back into digital power down */ @@ -5153,7 +5135,7 @@ static int cx25840_probe(struct i2c_client *client, struct cx25840_state *state; struct v4l2_subdev *sd; int default_volume; - u32 id = V4L2_IDENT_NONE; + u32 id; u16 device_id; /* Check if the adapter supports the needed features */ @@ -5169,14 +5151,14 @@ static int cx25840_probe(struct i2c_client *client, /* The high byte of the device ID should be * 0x83 for the cx2583x and 0x84 for the cx2584x */ if ((device_id & 0xff00) == 0x8300) { - id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6; + id = CX25836 + ((device_id >> 4) & 0xf) - 6; } else if ((device_id & 0xff00) == 0x8400) { - id = V4L2_IDENT_CX25840 + ((device_id >> 4) & 0xf); + id = CX25840 + ((device_id >> 4) & 0xf); } else if (device_id == 0x0000) { id = get_cx2388x_ident(client); } else if ((device_id & 0xfff0) == 0x5A30) { /* The CX23100 (0x5A3C = 23100) doesn't have an A/V decoder */ - id = V4L2_IDENT_CX2310X_AV; + id = CX2310X_AV; } else if ((device_id & 0xff) == (device_id >> 8)) { v4l_err(client, "likely a confused/unresponsive cx2388[578] A/V decoder" @@ -5190,7 +5172,7 @@ static int cx25840_probe(struct i2c_client *client, return -ENODEV; } - state = kzalloc(sizeof(struct cx25840_state), GFP_KERNEL); + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (state == NULL) return -ENOMEM; @@ -5198,26 +5180,26 @@ static int cx25840_probe(struct i2c_client *client, v4l2_i2c_subdev_init(sd, client, &cx25840_ops); switch (id) { - case V4L2_IDENT_CX23885_AV: + case CX23885_AV: v4l_info(client, "cx23885 A/V decoder found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); break; - case V4L2_IDENT_CX23887_AV: + case CX23887_AV: v4l_info(client, "cx23887 A/V decoder found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); break; - case V4L2_IDENT_CX23888_AV: + case CX23888_AV: v4l_info(client, "cx23888 A/V decoder found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); break; - case V4L2_IDENT_CX2310X_AV: + case CX2310X_AV: v4l_info(client, "cx%d A/V decoder found @ 0x%x (%s)\n", device_id, client->addr << 1, client->adapter->name); break; - case V4L2_IDENT_CX25840: - case V4L2_IDENT_CX25841: - case V4L2_IDENT_CX25842: - case V4L2_IDENT_CX25843: + case CX25840: + case CX25841: + case CX25842: + case CX25843: /* Note: revision '(device_id & 0x0f) == 2' was never built. The marking skips from 0x1 == 22 to 0x3 == 23. */ v4l_info(client, "cx25%3x-2%x found @ 0x%x (%s)\n", @@ -5226,8 +5208,8 @@ static int cx25840_probe(struct i2c_client *client, : (device_id & 0x0f), client->addr << 1, client->adapter->name); break; - case V4L2_IDENT_CX25836: - case V4L2_IDENT_CX25837: + case CX25836: + case CX25837: default: v4l_info(client, "cx25%3x-%x found @ 0x%x (%s)\n", (device_id & 0xfff0) >> 4, device_id & 0x0f, @@ -5292,7 +5274,6 @@ static int cx25840_probe(struct i2c_client *client, int err = state->hdl.error; v4l2_ctrl_handler_free(&state->hdl); - kfree(state); return err; } if (!is_cx2583x(state)) @@ -5317,7 +5298,6 @@ static int cx25840_remove(struct i2c_client *client) cx25840_ir_remove(sd); v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&state->hdl); - kfree(state); return 0; } diff --git a/drivers/media/i2c/cx25840/cx25840-core.h b/drivers/media/i2c/cx25840/cx25840-core.h index bd4ada28b490..37bc04217c44 100644 --- a/drivers/media/i2c/cx25840/cx25840-core.h +++ b/drivers/media/i2c/cx25840/cx25840-core.h @@ -23,12 +23,24 @@ #include <linux/videodev2.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> #include <media/v4l2-ctrls.h> #include <linux/i2c.h> struct cx25840_ir_state; +enum cx25840_model { + CX23885_AV, + CX23887_AV, + CX23888_AV, + CX2310X_AV, + CX25840, + CX25841, + CX25842, + CX25843, + CX25836, + CX25837, +}; + struct cx25840_state { struct i2c_client *c; struct v4l2_subdev sd; @@ -46,7 +58,7 @@ struct cx25840_state { u32 audclk_freq; int audmode; int vbi_line_offset; - u32 id; + enum cx25840_model id; u32 rev; int is_initialized; wait_queue_head_t fw_wait; /* wake up when the fw load is finished */ @@ -66,35 +78,35 @@ static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) static inline bool is_cx2583x(struct cx25840_state *state) { - return state->id == V4L2_IDENT_CX25836 || - state->id == V4L2_IDENT_CX25837; + return state->id == CX25836 || + state->id == CX25837; } static inline bool is_cx231xx(struct cx25840_state *state) { - return state->id == V4L2_IDENT_CX2310X_AV; + return state->id == CX2310X_AV; } static inline bool is_cx2388x(struct cx25840_state *state) { - return state->id == V4L2_IDENT_CX23885_AV || - state->id == V4L2_IDENT_CX23887_AV || - state->id == V4L2_IDENT_CX23888_AV; + return state->id == CX23885_AV || + state->id == CX23887_AV || + state->id == CX23888_AV; } static inline bool is_cx23885(struct cx25840_state *state) { - return state->id == V4L2_IDENT_CX23885_AV; + return state->id == CX23885_AV; } static inline bool is_cx23887(struct cx25840_state *state) { - return state->id == V4L2_IDENT_CX23887_AV; + return state->id == CX23887_AV; } static inline bool is_cx23888(struct cx25840_state *state) { - return state->id == V4L2_IDENT_CX23888_AV; + return state->id == CX23888_AV; } /* ----------------------------------------------------------------------- */ diff --git a/drivers/media/i2c/cx25840/cx25840-ir.c b/drivers/media/i2c/cx25840/cx25840-ir.c index 9ae977b5983a..e6588ee5bdb0 100644 --- a/drivers/media/i2c/cx25840/cx25840-ir.c +++ b/drivers/media/i2c/cx25840/cx25840-ir.c @@ -1230,16 +1230,14 @@ int cx25840_ir_probe(struct v4l2_subdev *sd) if (!(is_cx23885(state) || is_cx23887(state))) return 0; - ir_state = kzalloc(sizeof(struct cx25840_ir_state), GFP_KERNEL); + ir_state = devm_kzalloc(&state->c->dev, sizeof(*ir_state), GFP_KERNEL); if (ir_state == NULL) return -ENOMEM; spin_lock_init(&ir_state->rx_kfifo_lock); if (kfifo_alloc(&ir_state->rx_kfifo, - CX25840_IR_RX_KFIFO_SIZE, GFP_KERNEL)) { - kfree(ir_state); + CX25840_IR_RX_KFIFO_SIZE, GFP_KERNEL)) return -ENOMEM; - } ir_state->c = state->c; state->ir_state = ir_state; @@ -1273,7 +1271,6 @@ int cx25840_ir_remove(struct v4l2_subdev *sd) cx25840_ir_tx_shutdown(sd); kfifo_free(&ir_state->rx_kfifo); - kfree(ir_state); state->ir_state = NULL; return 0; } diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c index 8e2f79cb045e..82bf5679da30 100644 --- a/drivers/media/i2c/ir-kbd-i2c.c +++ b/drivers/media/i2c/ir-kbd-i2c.c @@ -295,7 +295,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) unsigned short addr = client->addr; int err; - ir = kzalloc(sizeof(struct IR_i2c), GFP_KERNEL); + ir = devm_kzalloc(&client->dev, sizeof(*ir), GFP_KERNEL); if (!ir) return -ENOMEM; @@ -398,10 +398,8 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) * internally */ rc = rc_allocate_device(); - if (!rc) { - err = -ENOMEM; - goto err_out_free; - } + if (!rc) + return -ENOMEM; } ir->rc = rc; @@ -454,7 +452,6 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) err_out_free: /* Only frees rc if it were allocated internally */ rc_free_device(rc); - kfree(ir); return err; } @@ -470,7 +467,6 @@ static int ir_remove(struct i2c_client *client) rc_unregister_device(ir->rc); /* free memory */ - kfree(ir); return 0; } diff --git a/drivers/media/i2c/ks0127.c b/drivers/media/i2c/ks0127.c index 04a6efa37cc3..c3e94ae82c03 100644 --- a/drivers/media/i2c/ks0127.c +++ b/drivers/media/i2c/ks0127.c @@ -42,7 +42,6 @@ #include <linux/videodev2.h> #include <linux/slab.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> #include "ks0127.h" MODULE_DESCRIPTION("KS0127 video decoder driver"); @@ -200,7 +199,6 @@ struct adjust { struct ks0127 { struct v4l2_subdev sd; v4l2_std_id norm; - int ident; u8 regs[256]; }; @@ -371,12 +369,9 @@ static void ks0127_and_or(struct v4l2_subdev *sd, u8 reg, u8 and_v, u8 or_v) ****************************************************************************/ static void ks0127_init(struct v4l2_subdev *sd) { - struct ks0127 *ks = to_ks0127(sd); u8 *table = reg_defaults; int i; - ks->ident = V4L2_IDENT_KS0127; - v4l2_dbg(1, debug, sd, "reset\n"); msleep(1); @@ -397,7 +392,6 @@ static void ks0127_init(struct v4l2_subdev *sd) if ((ks0127_read(sd, KS_STAT) & 0x80) == 0) { - ks->ident = V4L2_IDENT_KS0122S; v4l2_dbg(1, debug, sd, "ks0122s found\n"); return; } @@ -408,7 +402,6 @@ static void ks0127_init(struct v4l2_subdev *sd) break; case 9: - ks->ident = V4L2_IDENT_KS0127B; v4l2_dbg(1, debug, sd, "ks0127B Revision A found\n"); break; @@ -616,17 +609,24 @@ static int ks0127_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pstd { int stat = V4L2_IN_ST_NO_SIGNAL; u8 status; - v4l2_std_id std = V4L2_STD_ALL; + v4l2_std_id std = pstd ? *pstd : V4L2_STD_ALL; status = ks0127_read(sd, KS_STAT); if (!(status & 0x20)) /* NOVID not set */ stat = 0; - if (!(status & 0x01)) /* CLOCK set */ + if (!(status & 0x01)) { /* CLOCK set */ stat |= V4L2_IN_ST_NO_COLOR; - if ((status & 0x08)) /* PALDET set */ - std = V4L2_STD_PAL; + std = V4L2_STD_UNKNOWN; + } else { + if ((status & 0x08)) /* PALDET set */ + std &= V4L2_STD_PAL; + else + std &= V4L2_STD_NTSC; + } + if ((status & 0x10)) /* PALDET set */ + std &= V4L2_STD_525_60; else - std = V4L2_STD_NTSC; + std &= V4L2_STD_625_50; if (pstd) *pstd = std; if (pstatus) @@ -646,18 +646,9 @@ static int ks0127_g_input_status(struct v4l2_subdev *sd, u32 *status) return ks0127_status(sd, status, NULL); } -static int ks0127_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ks0127 *ks = to_ks0127(sd); - - return v4l2_chip_ident_i2c_client(client, chip, ks->ident, 0); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops ks0127_core_ops = { - .g_chip_ident = ks0127_g_chip_ident, .s_std = ks0127_s_std, }; @@ -685,7 +676,7 @@ static int ks0127_probe(struct i2c_client *client, const struct i2c_device_id *i client->addr == (I2C_KS0127_ADDON >> 1) ? "addon" : "on-board", client->addr << 1, client->adapter->name); - ks = kzalloc(sizeof(*ks), GFP_KERNEL); + ks = devm_kzalloc(&client->dev, sizeof(*ks), GFP_KERNEL); if (ks == NULL) return -ENOMEM; sd = &ks->sd; @@ -708,7 +699,6 @@ static int ks0127_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); ks0127_write(sd, KS_OFMTA, 0x20); /* tristate */ ks0127_write(sd, KS_CMDA, 0x2c | 0x80); /* power down */ - kfree(to_ks0127(sd)); return 0; } diff --git a/drivers/media/i2c/m52790.c b/drivers/media/i2c/m52790.c index 39f50fd2b8d2..bf476358704d 100644 --- a/drivers/media/i2c/m52790.c +++ b/drivers/media/i2c/m52790.c @@ -29,7 +29,6 @@ #include <linux/videodev2.h> #include <media/m52790.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> MODULE_DESCRIPTION("i2c device driver for m52790 A/V switch"); MODULE_AUTHOR("Hans Verkuil"); @@ -83,12 +82,7 @@ static int m52790_s_routing(struct v4l2_subdev *sd, static int m52790_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { struct m52790_state *state = to_state(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; if (reg->reg != 0) return -EINVAL; reg->size = 1; @@ -99,12 +93,7 @@ static int m52790_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *r static int m52790_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { struct m52790_state *state = to_state(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; if (reg->reg != 0) return -EINVAL; state->input = reg->val & 0x0303; @@ -114,13 +103,6 @@ static int m52790_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_regis } #endif -static int m52790_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_M52790, 0); -} - static int m52790_log_status(struct v4l2_subdev *sd) { struct m52790_state *state = to_state(sd); @@ -136,7 +118,6 @@ static int m52790_log_status(struct v4l2_subdev *sd) static const struct v4l2_subdev_core_ops m52790_core_ops = { .log_status = m52790_log_status, - .g_chip_ident = m52790_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = m52790_g_register, .s_register = m52790_s_register, @@ -174,7 +155,7 @@ static int m52790_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - state = kzalloc(sizeof(struct m52790_state), GFP_KERNEL); + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (state == NULL) return -ENOMEM; @@ -191,7 +172,6 @@ static int m52790_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); v4l2_device_unregister_subdev(sd); - kfree(to_state(sd)); return 0; } diff --git a/drivers/media/i2c/m5mols/m5mols_core.c b/drivers/media/i2c/m5mols/m5mols_core.c index 0b899cb6cda1..8d870b7b43ff 100644 --- a/drivers/media/i2c/m5mols/m5mols_core.c +++ b/drivers/media/i2c/m5mols/m5mols_core.c @@ -930,6 +930,7 @@ static int m5mols_probe(struct i2c_client *client, const struct i2c_device_id *id) { const struct m5mols_platform_data *pdata = client->dev.platform_data; + unsigned long gpio_flags; struct m5mols_info *info; struct v4l2_subdev *sd; int ret; @@ -949,24 +950,27 @@ static int m5mols_probe(struct i2c_client *client, return -EINVAL; } - info = kzalloc(sizeof(struct m5mols_info), GFP_KERNEL); + info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; info->pdata = pdata; info->set_power = pdata->set_power; - ret = gpio_request(pdata->gpio_reset, "M5MOLS_NRST"); + gpio_flags = pdata->reset_polarity + ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; + ret = devm_gpio_request_one(&client->dev, pdata->gpio_reset, gpio_flags, + "M5MOLS_NRST"); if (ret) { dev_err(&client->dev, "Failed to request gpio: %d\n", ret); - goto out_free; + return ret; } - gpio_direction_output(pdata->gpio_reset, pdata->reset_polarity); - ret = regulator_bulk_get(&client->dev, ARRAY_SIZE(supplies), supplies); + ret = devm_regulator_bulk_get(&client->dev, ARRAY_SIZE(supplies), + supplies); if (ret) { dev_err(&client->dev, "Failed to get regulators: %d\n", ret); - goto out_gpio; + return ret; } sd = &info->sd; @@ -978,17 +982,17 @@ static int m5mols_probe(struct i2c_client *client, info->pad.flags = MEDIA_PAD_FL_SOURCE; ret = media_entity_init(&sd->entity, 1, &info->pad, 0); if (ret < 0) - goto out_reg; + return ret; sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR; init_waitqueue_head(&info->irq_waitq); mutex_init(&info->lock); - ret = request_irq(client->irq, m5mols_irq_handler, - IRQF_TRIGGER_RISING, MODULE_NAME, sd); + ret = devm_request_irq(&client->dev, client->irq, m5mols_irq_handler, + IRQF_TRIGGER_RISING, MODULE_NAME, sd); if (ret) { dev_err(&client->dev, "Interrupt request failed: %d\n", ret); - goto out_me; + goto error; } info->res_type = M5MOLS_RESTYPE_MONITOR; info->ffmt[0] = m5mols_default_ffmt[0]; @@ -996,7 +1000,7 @@ static int m5mols_probe(struct i2c_client *client, ret = m5mols_sensor_power(info, true); if (ret) - goto out_irq; + goto error; ret = m5mols_fw_start(sd); if (!ret) @@ -1005,32 +1009,19 @@ static int m5mols_probe(struct i2c_client *client, ret = m5mols_sensor_power(info, false); if (!ret) return 0; -out_irq: - free_irq(client->irq, sd); -out_me: +error: media_entity_cleanup(&sd->entity); -out_reg: - regulator_bulk_free(ARRAY_SIZE(supplies), supplies); -out_gpio: - gpio_free(pdata->gpio_reset); -out_free: - kfree(info); return ret; } static int m5mols_remove(struct i2c_client *client) { struct v4l2_subdev *sd = i2c_get_clientdata(client); - struct m5mols_info *info = to_m5mols(sd); v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(sd->ctrl_handler); - free_irq(client->irq, sd); - - regulator_bulk_free(ARRAY_SIZE(supplies), supplies); - gpio_free(info->pdata->gpio_reset); media_entity_cleanup(&sd->entity); - kfree(info); + return 0; } diff --git a/drivers/media/i2c/ml86v7667.c b/drivers/media/i2c/ml86v7667.c new file mode 100644 index 000000000000..efdc873e58d1 --- /dev/null +++ b/drivers/media/i2c/ml86v7667.c @@ -0,0 +1,431 @@ +/* + * OKI Semiconductor ML86V7667 video decoder driver + * + * Author: Vladimir Barinov <source@cogentembedded.com> + * 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 as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/i2c.h> +#include <linux/slab.h> +#include <linux/videodev2.h> +#include <media/v4l2-subdev.h> +#include <media/v4l2-device.h> +#include <media/v4l2-ioctl.h> +#include <media/v4l2-ctrls.h> + +#define DRV_NAME "ml86v7667" + +/* Subaddresses */ +#define MRA_REG 0x00 /* Mode Register A */ +#define MRC_REG 0x02 /* Mode Register C */ +#define LUMC_REG 0x0C /* Luminance Control */ +#define CLC_REG 0x10 /* Contrast level control */ +#define SSEPL_REG 0x11 /* Sync separation level */ +#define CHRCA_REG 0x12 /* Chrominance Control A */ +#define ACCC_REG 0x14 /* ACC Loop filter & Chrominance control */ +#define ACCRC_REG 0x15 /* ACC Reference level control */ +#define HUE_REG 0x16 /* Hue control */ +#define ADC2_REG 0x1F /* ADC Register 2 */ +#define PLLR1_REG 0x20 /* PLL Register 1 */ +#define STATUS_REG 0x2C /* STATUS Register */ + +/* Mode Register A register bits */ +#define MRA_OUTPUT_MODE_MASK (3 << 6) +#define MRA_ITUR_BT601 (1 << 6) +#define MRA_ITUR_BT656 (0 << 6) +#define MRA_INPUT_MODE_MASK (7 << 3) +#define MRA_PAL_BT601 (4 << 3) +#define MRA_NTSC_BT601 (0 << 3) +#define MRA_REGISTER_MODE (1 << 0) + +/* Mode Register C register bits */ +#define MRC_AUTOSELECT (1 << 7) + +/* Luminance Control register bits */ +#define LUMC_ONOFF_SHIFT 7 +#define LUMC_ONOFF_MASK (1 << 7) + +/* Contrast level control register bits */ +#define CLC_CONTRAST_ONOFF (1 << 7) +#define CLC_CONTRAST_MASK 0x0F + +/* Sync separation level register bits */ +#define SSEPL_LUMINANCE_ONOFF (1 << 7) +#define SSEPL_LUMINANCE_MASK 0x7F + +/* Chrominance Control A register bits */ +#define CHRCA_MODE_SHIFT 6 +#define CHRCA_MODE_MASK (1 << 6) + +/* ACC Loop filter & Chrominance control register bits */ +#define ACCC_CHROMA_CR_SHIFT 3 +#define ACCC_CHROMA_CR_MASK (7 << 3) +#define ACCC_CHROMA_CB_SHIFT 0 +#define ACCC_CHROMA_CB_MASK (7 << 0) + +/* ACC Reference level control register bits */ +#define ACCRC_CHROMA_MASK 0xfc +#define ACCRC_CHROMA_SHIFT 2 + +/* ADC Register 2 register bits */ +#define ADC2_CLAMP_VOLTAGE_MASK (7 << 1) +#define ADC2_CLAMP_VOLTAGE(n) ((n & 7) << 1) + +/* PLL Register 1 register bits */ +#define PLLR1_FIXED_CLOCK (1 << 7) + +/* STATUS Register register bits */ +#define STATUS_HLOCK_DETECT (1 << 3) +#define STATUS_NTSCPAL (1 << 2) + +struct ml86v7667_priv { + struct v4l2_subdev sd; + struct v4l2_ctrl_handler hdl; + v4l2_std_id std; +}; + +static inline struct ml86v7667_priv *to_ml86v7667(struct v4l2_subdev *subdev) +{ + return container_of(subdev, struct ml86v7667_priv, sd); +} + +static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) +{ + return &container_of(ctrl->handler, struct ml86v7667_priv, hdl)->sd; +} + +static int ml86v7667_mask_set(struct i2c_client *client, const u8 reg, + const u8 mask, const u8 data) +{ + int val = i2c_smbus_read_byte_data(client, reg); + if (val < 0) + return val; + + val = (val & ~mask) | (data & mask); + return i2c_smbus_write_byte_data(client, reg, val); +} + +static int ml86v7667_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct v4l2_subdev *sd = to_sd(ctrl); + struct i2c_client *client = v4l2_get_subdevdata(sd); + int ret; + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: + ret = ml86v7667_mask_set(client, SSEPL_REG, + SSEPL_LUMINANCE_MASK, ctrl->val); + break; + case V4L2_CID_CONTRAST: + ret = ml86v7667_mask_set(client, CLC_REG, + CLC_CONTRAST_MASK, ctrl->val); + break; + case V4L2_CID_CHROMA_GAIN: + ret = ml86v7667_mask_set(client, ACCRC_REG, ACCRC_CHROMA_MASK, + ctrl->val << ACCRC_CHROMA_SHIFT); + break; + case V4L2_CID_HUE: + ret = ml86v7667_mask_set(client, HUE_REG, ~0, ctrl->val); + break; + case V4L2_CID_RED_BALANCE: + ret = ml86v7667_mask_set(client, ACCC_REG, + ACCC_CHROMA_CR_MASK, + ctrl->val << ACCC_CHROMA_CR_SHIFT); + break; + case V4L2_CID_BLUE_BALANCE: + ret = ml86v7667_mask_set(client, ACCC_REG, + ACCC_CHROMA_CB_MASK, + ctrl->val << ACCC_CHROMA_CB_SHIFT); + break; + case V4L2_CID_SHARPNESS: + ret = ml86v7667_mask_set(client, LUMC_REG, + LUMC_ONOFF_MASK, + ctrl->val << LUMC_ONOFF_SHIFT); + break; + case V4L2_CID_COLOR_KILLER: + ret = ml86v7667_mask_set(client, CHRCA_REG, + CHRCA_MODE_MASK, + ctrl->val << CHRCA_MODE_SHIFT); + break; + } + + return 0; +} + +static int ml86v7667_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + int status; + + status = i2c_smbus_read_byte_data(client, STATUS_REG); + if (status < 0) + return status; + + if (status & STATUS_HLOCK_DETECT) + *std &= status & STATUS_NTSCPAL ? V4L2_STD_625_50 : V4L2_STD_525_60; + else + *std = V4L2_STD_UNKNOWN; + + return 0; +} + +static int ml86v7667_g_input_status(struct v4l2_subdev *sd, u32 *status) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + int status_reg; + + status_reg = i2c_smbus_read_byte_data(client, STATUS_REG); + if (status_reg < 0) + return status_reg; + + *status = status_reg & STATUS_HLOCK_DETECT ? 0 : V4L2_IN_ST_NO_SIGNAL; + + return 0; +} + +static int ml86v7667_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index, + enum v4l2_mbus_pixelcode *code) +{ + if (index > 0) + return -EINVAL; + + *code = V4L2_MBUS_FMT_YUYV8_2X8; + + return 0; +} + +static int ml86v7667_mbus_fmt(struct v4l2_subdev *sd, + struct v4l2_mbus_framefmt *fmt) +{ + struct ml86v7667_priv *priv = to_ml86v7667(sd); + + fmt->code = V4L2_MBUS_FMT_YUYV8_2X8; + fmt->colorspace = V4L2_COLORSPACE_SMPTE170M; + fmt->field = V4L2_FIELD_INTERLACED; + fmt->width = 720; + fmt->height = priv->std & V4L2_STD_525_60 ? 480 : 576; + + return 0; +} + +static int ml86v7667_g_mbus_config(struct v4l2_subdev *sd, + struct v4l2_mbus_config *cfg) +{ + cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING | + V4L2_MBUS_DATA_ACTIVE_HIGH; + cfg->type = V4L2_MBUS_BT656; + + return 0; +} + +static int ml86v7667_s_std(struct v4l2_subdev *sd, v4l2_std_id std) +{ + struct ml86v7667_priv *priv = to_ml86v7667(sd); + struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); + int ret; + u8 mode; + + /* PAL/NTSC ITU-R BT.601 input mode */ + mode = std & V4L2_STD_525_60 ? MRA_NTSC_BT601 : MRA_PAL_BT601; + ret = ml86v7667_mask_set(client, MRA_REG, MRA_INPUT_MODE_MASK, mode); + if (ret < 0) + return ret; + + priv->std = std; + + return 0; +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int ml86v7667_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + int ret; + + ret = i2c_smbus_read_byte_data(client, (u8)reg->reg); + if (ret < 0) + return ret; + + reg->val = ret; + reg->size = sizeof(u8); + + return 0; +} + +static int ml86v7667_s_register(struct v4l2_subdev *sd, + const struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return i2c_smbus_write_byte_data(client, (u8)reg->reg, (u8)reg->val); +} +#endif + +static const struct v4l2_ctrl_ops ml86v7667_ctrl_ops = { + .s_ctrl = ml86v7667_s_ctrl, +}; + +static struct v4l2_subdev_video_ops ml86v7667_subdev_video_ops = { + .querystd = ml86v7667_querystd, + .g_input_status = ml86v7667_g_input_status, + .enum_mbus_fmt = ml86v7667_enum_mbus_fmt, + .try_mbus_fmt = ml86v7667_mbus_fmt, + .g_mbus_fmt = ml86v7667_mbus_fmt, + .s_mbus_fmt = ml86v7667_mbus_fmt, + .g_mbus_config = ml86v7667_g_mbus_config, +}; + +static struct v4l2_subdev_core_ops ml86v7667_subdev_core_ops = { + .s_std = ml86v7667_s_std, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = ml86v7667_g_register, + .s_register = ml86v7667_s_register, +#endif +}; + +static struct v4l2_subdev_ops ml86v7667_subdev_ops = { + .core = &ml86v7667_subdev_core_ops, + .video = &ml86v7667_subdev_video_ops, +}; + +static int ml86v7667_init(struct ml86v7667_priv *priv) +{ + struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); + int val; + int ret; + + /* BT.656-4 output mode, register mode */ + ret = ml86v7667_mask_set(client, MRA_REG, + MRA_OUTPUT_MODE_MASK | MRA_REGISTER_MODE, + MRA_ITUR_BT656 | MRA_REGISTER_MODE); + + /* PLL circuit fixed clock, 32MHz */ + ret |= ml86v7667_mask_set(client, PLLR1_REG, PLLR1_FIXED_CLOCK, + PLLR1_FIXED_CLOCK); + + /* ADC2 clamping voltage maximum */ + ret |= ml86v7667_mask_set(client, ADC2_REG, ADC2_CLAMP_VOLTAGE_MASK, + ADC2_CLAMP_VOLTAGE(7)); + + /* enable luminance function */ + ret |= ml86v7667_mask_set(client, SSEPL_REG, SSEPL_LUMINANCE_ONOFF, + SSEPL_LUMINANCE_ONOFF); + + /* enable contrast function */ + ret |= ml86v7667_mask_set(client, CLC_REG, CLC_CONTRAST_ONOFF, 0); + + /* + * PAL/NTSC autodetection is enabled after reset, + * set the autodetected std in manual std mode and + * disable autodetection + */ + val = i2c_smbus_read_byte_data(client, STATUS_REG); + if (val < 0) + return val; + + priv->std = val & STATUS_NTSCPAL ? V4L2_STD_625_50 : V4L2_STD_525_60; + ret |= ml86v7667_mask_set(client, MRC_REG, MRC_AUTOSELECT, 0); + + val = priv->std & V4L2_STD_525_60 ? MRA_NTSC_BT601 : MRA_PAL_BT601; + ret |= ml86v7667_mask_set(client, MRA_REG, MRA_INPUT_MODE_MASK, val); + + return ret; +} + +static int ml86v7667_probe(struct i2c_client *client, + const struct i2c_device_id *did) +{ + struct ml86v7667_priv *priv; + int ret; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -EIO; + + priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + v4l2_i2c_subdev_init(&priv->sd, client, &ml86v7667_subdev_ops); + + v4l2_ctrl_handler_init(&priv->hdl, 8); + v4l2_ctrl_new_std(&priv->hdl, &ml86v7667_ctrl_ops, + V4L2_CID_BRIGHTNESS, -64, 63, 1, 0); + v4l2_ctrl_new_std(&priv->hdl, &ml86v7667_ctrl_ops, + V4L2_CID_CONTRAST, -8, 7, 1, 0); + v4l2_ctrl_new_std(&priv->hdl, &ml86v7667_ctrl_ops, + V4L2_CID_CHROMA_GAIN, -32, 31, 1, 0); + v4l2_ctrl_new_std(&priv->hdl, &ml86v7667_ctrl_ops, + V4L2_CID_HUE, -128, 127, 1, 0); + v4l2_ctrl_new_std(&priv->hdl, &ml86v7667_ctrl_ops, + V4L2_CID_RED_BALANCE, -4, 3, 1, 0); + v4l2_ctrl_new_std(&priv->hdl, &ml86v7667_ctrl_ops, + V4L2_CID_BLUE_BALANCE, -4, 3, 1, 0); + v4l2_ctrl_new_std(&priv->hdl, &ml86v7667_ctrl_ops, + V4L2_CID_SHARPNESS, 0, 1, 1, 0); + v4l2_ctrl_new_std(&priv->hdl, &ml86v7667_ctrl_ops, + V4L2_CID_COLOR_KILLER, 0, 1, 1, 0); + priv->sd.ctrl_handler = &priv->hdl; + + ret = priv->hdl.error; + if (ret) + goto cleanup; + + v4l2_ctrl_handler_setup(&priv->hdl); + + ret = ml86v7667_init(priv); + if (ret) + goto cleanup; + + v4l_info(client, "chip found @ 0x%02x (%s)\n", + client->addr, client->adapter->name); + return 0; + +cleanup: + v4l2_ctrl_handler_free(&priv->hdl); + v4l2_device_unregister_subdev(&priv->sd); + v4l_err(client, "failed to probe @ 0x%02x (%s)\n", + client->addr, client->adapter->name); + return ret; +} + +static int ml86v7667_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct ml86v7667_priv *priv = to_ml86v7667(sd); + + v4l2_ctrl_handler_free(&priv->hdl); + v4l2_device_unregister_subdev(&priv->sd); + + return 0; +} + +static const struct i2c_device_id ml86v7667_id[] = { + {DRV_NAME, 0}, + {}, +}; +MODULE_DEVICE_TABLE(i2c, ml86v7667_id); + +static struct i2c_driver ml86v7667_i2c_driver = { + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, + .probe = ml86v7667_probe, + .remove = ml86v7667_remove, + .id_table = ml86v7667_id, +}; + +module_i2c_driver(ml86v7667_i2c_driver); + +MODULE_DESCRIPTION("OKI Semiconductor ML86V7667 video decoder driver"); +MODULE_AUTHOR("Vladimir Barinov"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/i2c/msp3400-driver.c b/drivers/media/i2c/msp3400-driver.c index 54a9dd394f45..8190fec68080 100644 --- a/drivers/media/i2c/msp3400-driver.c +++ b/drivers/media/i2c/msp3400-driver.c @@ -570,15 +570,6 @@ static int msp_s_i2s_clock_freq(struct v4l2_subdev *sd, u32 freq) return 0; } -static int msp_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct msp_state *state = to_state(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, state->ident, - (state->rev1 << 16) | state->rev2); -} - static int msp_log_status(struct v4l2_subdev *sd) { struct msp_state *state = to_state(sd); @@ -651,7 +642,6 @@ static const struct v4l2_ctrl_ops msp_ctrl_ops = { static const struct v4l2_subdev_core_ops msp_core_ops = { .log_status = msp_log_status, - .g_chip_ident = msp_g_chip_ident, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, @@ -707,7 +697,7 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id) return -ENODEV; } - state = kzalloc(sizeof(*state), GFP_KERNEL); + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (!state) return -ENOMEM; @@ -732,7 +722,6 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id) if (state->rev1 == -1 || (state->rev1 == 0 && state->rev2 == 0)) { v4l_dbg(1, msp_debug, client, "not an msp3400 (cannot read chip version)\n"); - kfree(state); return -ENODEV; } @@ -827,7 +816,6 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id) int err = hdl->error; v4l2_ctrl_handler_free(hdl); - kfree(state); return err; } @@ -889,7 +877,6 @@ static int msp_remove(struct i2c_client *client) msp_reset(client); v4l2_ctrl_handler_free(&state->hdl); - kfree(state); return 0; } diff --git a/drivers/media/i2c/mt9m032.c b/drivers/media/i2c/mt9m032.c index 8edb3d8f7b90..846b15f0bf64 100644 --- a/drivers/media/i2c/mt9m032.c +++ b/drivers/media/i2c/mt9m032.c @@ -554,10 +554,8 @@ static int mt9m032_g_register(struct v4l2_subdev *sd, struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); int val; - if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + if (reg->reg > 0xff) return -EINVAL; - if (reg->match.addr != client->addr) - return -ENODEV; val = mt9m032_read(client, reg->reg); if (val < 0) @@ -575,12 +573,9 @@ static int mt9m032_s_register(struct v4l2_subdev *sd, struct mt9m032 *sensor = to_mt9m032(sd); struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); - if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + if (reg->reg > 0xff) return -EINVAL; - if (reg->match.addr != client->addr) - return -ENODEV; - return mt9m032_write(client, reg->reg, reg->val); } #endif @@ -730,7 +725,7 @@ static int mt9m032_probe(struct i2c_client *client, if (!client->dev.platform_data) return -ENODEV; - sensor = kzalloc(sizeof(*sensor), GFP_KERNEL); + sensor = devm_kzalloc(&client->dev, sizeof(*sensor), GFP_KERNEL); if (sensor == NULL) return -ENOMEM; @@ -860,7 +855,6 @@ error_ctrl: v4l2_ctrl_handler_free(&sensor->ctrls); error_sensor: mutex_destroy(&sensor->lock); - kfree(sensor); return ret; } @@ -873,7 +867,6 @@ static int mt9m032_remove(struct i2c_client *client) v4l2_ctrl_handler_free(&sensor->ctrls); media_entity_cleanup(&subdev->entity); mutex_destroy(&sensor->lock); - kfree(sensor); return 0; } diff --git a/drivers/media/i2c/mt9p031.c b/drivers/media/i2c/mt9p031.c index 28cf95b37285..4734836fe5a4 100644 --- a/drivers/media/i2c/mt9p031.c +++ b/drivers/media/i2c/mt9p031.c @@ -16,18 +16,19 @@ #include <linux/delay.h> #include <linux/device.h> #include <linux/gpio.h> -#include <linux/module.h> #include <linux/i2c.h> #include <linux/log2.h> +#include <linux/module.h> +#include <linux/of_gpio.h> #include <linux/pm.h> #include <linux/regulator/consumer.h> #include <linux/slab.h> #include <linux/videodev2.h> #include <media/mt9p031.h> -#include <media/v4l2-chip-ident.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> +#include <media/v4l2-of.h> #include <media/v4l2-subdev.h> #include "aptina-pll.h" @@ -124,9 +125,7 @@ struct mt9p031 { int power_count; struct clk *clk; - struct regulator *vaa; - struct regulator *vdd; - struct regulator *vdd_io; + struct regulator_bulk_data regulators[3]; enum mt9p031_model model; struct aptina_pll pll; @@ -271,23 +270,26 @@ static inline int mt9p031_pll_disable(struct mt9p031 *mt9p031) static int mt9p031_power_on(struct mt9p031 *mt9p031) { + int ret; + /* Ensure RESET_BAR is low */ - if (mt9p031->reset != -1) { + if (gpio_is_valid(mt9p031->reset)) { gpio_set_value(mt9p031->reset, 0); usleep_range(1000, 2000); } /* Bring up the supplies */ - regulator_enable(mt9p031->vdd); - regulator_enable(mt9p031->vdd_io); - regulator_enable(mt9p031->vaa); + ret = regulator_bulk_enable(ARRAY_SIZE(mt9p031->regulators), + mt9p031->regulators); + if (ret < 0) + return ret; /* Emable clock */ if (mt9p031->clk) clk_prepare_enable(mt9p031->clk); /* Now RESET_BAR must be high */ - if (mt9p031->reset != -1) { + if (gpio_is_valid(mt9p031->reset)) { gpio_set_value(mt9p031->reset, 1); usleep_range(1000, 2000); } @@ -297,14 +299,13 @@ static int mt9p031_power_on(struct mt9p031 *mt9p031) static void mt9p031_power_off(struct mt9p031 *mt9p031) { - if (mt9p031->reset != -1) { + if (gpio_is_valid(mt9p031->reset)) { gpio_set_value(mt9p031->reset, 0); usleep_range(1000, 2000); } - regulator_disable(mt9p031->vaa); - regulator_disable(mt9p031->vdd_io); - regulator_disable(mt9p031->vdd); + regulator_bulk_disable(ARRAY_SIZE(mt9p031->regulators), + mt9p031->regulators); if (mt9p031->clk) clk_disable_unprepare(mt9p031->clk); @@ -849,18 +850,18 @@ static int mt9p031_registered(struct v4l2_subdev *subdev) /* Read out the chip version register */ data = mt9p031_read(client, MT9P031_CHIP_VERSION); + mt9p031_power_off(mt9p031); + if (data != MT9P031_CHIP_VERSION_VALUE) { dev_err(&client->dev, "MT9P031 not detected, wrong version " "0x%04x\n", data); return -ENODEV; } - mt9p031_power_off(mt9p031); - dev_info(&client->dev, "MT9P031 detected at address 0x%02x\n", client->addr); - return ret; + return 0; } static int mt9p031_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh) @@ -928,10 +929,36 @@ static const struct v4l2_subdev_internal_ops mt9p031_subdev_internal_ops = { * Driver initialization and probing */ +static struct mt9p031_platform_data * +mt9p031_get_pdata(struct i2c_client *client) +{ + struct mt9p031_platform_data *pdata; + struct device_node *np; + + if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) + return client->dev.platform_data; + + np = v4l2_of_get_next_endpoint(client->dev.of_node, NULL); + if (!np) + return NULL; + + pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + goto done; + + pdata->reset = of_get_named_gpio(client->dev.of_node, "reset-gpios", 0); + of_property_read_u32(np, "input-clock-frequency", &pdata->ext_freq); + of_property_read_u32(np, "pixel-clock-frequency", &pdata->target_freq); + +done: + of_node_put(np); + return pdata; +} + static int mt9p031_probe(struct i2c_client *client, const struct i2c_device_id *did) { - struct mt9p031_platform_data *pdata = client->dev.platform_data; + struct mt9p031_platform_data *pdata = mt9p031_get_pdata(client); struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct mt9p031 *mt9p031; unsigned int i; @@ -958,14 +985,14 @@ static int mt9p031_probe(struct i2c_client *client, mt9p031->model = did->driver_data; mt9p031->reset = -1; - mt9p031->vaa = devm_regulator_get(&client->dev, "vaa"); - mt9p031->vdd = devm_regulator_get(&client->dev, "vdd"); - mt9p031->vdd_io = devm_regulator_get(&client->dev, "vdd_io"); + mt9p031->regulators[0].supply = "vdd"; + mt9p031->regulators[1].supply = "vdd_io"; + mt9p031->regulators[2].supply = "vaa"; - if (IS_ERR(mt9p031->vaa) || IS_ERR(mt9p031->vdd) || - IS_ERR(mt9p031->vdd_io)) { + ret = devm_regulator_bulk_get(&client->dev, 3, mt9p031->regulators); + if (ret < 0) { dev_err(&client->dev, "Unable to get regulators\n"); - return -ENODEV; + return ret; } v4l2_ctrl_handler_init(&mt9p031->ctrls, ARRAY_SIZE(mt9p031_ctrls) + 6); @@ -1031,7 +1058,7 @@ static int mt9p031_probe(struct i2c_client *client, mt9p031->format.field = V4L2_FIELD_NONE; mt9p031->format.colorspace = V4L2_COLORSPACE_SRGB; - if (pdata->reset != -1) { + if (gpio_is_valid(pdata->reset)) { ret = devm_gpio_request_one(&client->dev, pdata->reset, GPIOF_OUT_INIT_LOW, "mt9p031_rst"); if (ret < 0) @@ -1070,8 +1097,18 @@ static const struct i2c_device_id mt9p031_id[] = { }; MODULE_DEVICE_TABLE(i2c, mt9p031_id); +#if IS_ENABLED(CONFIG_OF) +static const struct of_device_id mt9p031_of_match[] = { + { .compatible = "aptina,mt9p031", }, + { .compatible = "aptina,mt9p031m", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, mt9p031_of_match); +#endif + static struct i2c_driver mt9p031_i2c_driver = { .driver = { + .of_match_table = of_match_ptr(mt9p031_of_match), .name = "mt9p031", }, .probe = mt9p031_probe, diff --git a/drivers/media/i2c/mt9t001.c b/drivers/media/i2c/mt9t001.c index 2e189d8b71bb..796463466ef0 100644 --- a/drivers/media/i2c/mt9t001.c +++ b/drivers/media/i2c/mt9t001.c @@ -740,7 +740,7 @@ static int mt9t001_probe(struct i2c_client *client, if (ret < 0) return ret; - mt9t001 = kzalloc(sizeof(*mt9t001), GFP_KERNEL); + mt9t001 = devm_kzalloc(&client->dev, sizeof(*mt9t001), GFP_KERNEL); if (!mt9t001) return -ENOMEM; @@ -801,7 +801,6 @@ done: if (ret < 0) { v4l2_ctrl_handler_free(&mt9t001->ctrls); media_entity_cleanup(&mt9t001->subdev.entity); - kfree(mt9t001); } return ret; @@ -815,7 +814,6 @@ static int mt9t001_remove(struct i2c_client *client) v4l2_ctrl_handler_free(&mt9t001->ctrls); v4l2_device_unregister_subdev(subdev); media_entity_cleanup(&subdev->entity); - kfree(mt9t001); return 0; } diff --git a/drivers/media/i2c/mt9v011.c b/drivers/media/i2c/mt9v011.c index 3f415fd12de3..f74698cf14c9 100644 --- a/drivers/media/i2c/mt9v011.c +++ b/drivers/media/i2c/mt9v011.c @@ -12,7 +12,6 @@ #include <linux/module.h> #include <asm/div64.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> #include <media/v4l2-ctrls.h> #include <media/mt9v011.h> @@ -407,13 +406,6 @@ static int mt9v011_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt static int mt9v011_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - reg->val = mt9v011_read(sd, reg->reg & 0xff); reg->size = 2; @@ -423,31 +415,12 @@ static int mt9v011_g_register(struct v4l2_subdev *sd, static int mt9v011_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - mt9v011_write(sd, reg->reg & 0xff, reg->val & 0xffff); return 0; } #endif -static int mt9v011_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - u16 version; - struct i2c_client *client = v4l2_get_subdevdata(sd); - - version = mt9v011_read(sd, R00_MT9V011_CHIP_VERSION); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_MT9V011, - version); -} - static int mt9v011_s_ctrl(struct v4l2_ctrl *ctrl) { struct mt9v011 *core = @@ -489,7 +462,6 @@ static struct v4l2_ctrl_ops mt9v011_ctrl_ops = { static const struct v4l2_subdev_core_ops mt9v011_core_ops = { .reset = mt9v011_reset, - .g_chip_ident = mt9v011_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = mt9v011_g_register, .s_register = mt9v011_s_register, @@ -526,7 +498,7 @@ static int mt9v011_probe(struct i2c_client *c, I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) return -EIO; - core = kzalloc(sizeof(struct mt9v011), GFP_KERNEL); + core = devm_kzalloc(&c->dev, sizeof(struct mt9v011), GFP_KERNEL); if (!core) return -ENOMEM; @@ -539,7 +511,6 @@ static int mt9v011_probe(struct i2c_client *c, (version != MT9V011_REV_B_VERSION)) { v4l2_info(sd, "*** unknown micron chip detected (0x%04x).\n", version); - kfree(core); return -EINVAL; } @@ -562,7 +533,6 @@ static int mt9v011_probe(struct i2c_client *c, v4l2_err(sd, "control initialization error %d\n", ret); v4l2_ctrl_handler_free(&core->ctrls); - kfree(core); return ret; } core->sd.ctrl_handler = &core->ctrls; @@ -598,7 +568,7 @@ static int mt9v011_remove(struct i2c_client *c) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&core->ctrls); - kfree(to_mt9v011(sd)); + return 0; } diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c index 3f356cb28256..60c6f6739560 100644 --- a/drivers/media/i2c/mt9v032.c +++ b/drivers/media/i2c/mt9v032.c @@ -744,7 +744,7 @@ static int mt9v032_probe(struct i2c_client *client, return -EIO; } - mt9v032 = kzalloc(sizeof(*mt9v032), GFP_KERNEL); + mt9v032 = devm_kzalloc(&client->dev, sizeof(*mt9v032), GFP_KERNEL); if (!mt9v032) return -ENOMEM; @@ -830,8 +830,9 @@ static int mt9v032_probe(struct i2c_client *client, mt9v032->pad.flags = MEDIA_PAD_FL_SOURCE; ret = media_entity_init(&mt9v032->subdev.entity, 1, &mt9v032->pad, 0); + if (ret < 0) - kfree(mt9v032); + v4l2_ctrl_handler_free(&mt9v032->ctrls); return ret; } @@ -841,9 +842,10 @@ static int mt9v032_remove(struct i2c_client *client) struct v4l2_subdev *subdev = i2c_get_clientdata(client); struct mt9v032 *mt9v032 = to_mt9v032(subdev); + v4l2_ctrl_handler_free(&mt9v032->ctrls); v4l2_device_unregister_subdev(subdev); media_entity_cleanup(&subdev->entity); - kfree(mt9v032); + return 0; } diff --git a/drivers/media/i2c/noon010pc30.c b/drivers/media/i2c/noon010pc30.c index 8554b47f993a..271d0b7967a6 100644 --- a/drivers/media/i2c/noon010pc30.c +++ b/drivers/media/i2c/noon010pc30.c @@ -19,7 +19,6 @@ #include <linux/slab.h> #include <linux/regulator/consumer.h> #include <media/noon010pc30.h> -#include <media/v4l2-chip-ident.h> #include <linux/videodev2.h> #include <linux/module.h> #include <media/v4l2-ctrls.h> @@ -712,7 +711,7 @@ static int noon010_probe(struct i2c_client *client, return -EIO; } - info = kzalloc(sizeof(*info), GFP_KERNEL); + info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; @@ -746,57 +745,50 @@ static int noon010_probe(struct i2c_client *client, info->curr_win = &noon010_sizes[0]; if (gpio_is_valid(pdata->gpio_nreset)) { - ret = gpio_request(pdata->gpio_nreset, "NOON010PC30 NRST"); + ret = devm_gpio_request_one(&client->dev, pdata->gpio_nreset, + GPIOF_OUT_INIT_LOW, + "NOON010PC30 NRST"); if (ret) { dev_err(&client->dev, "GPIO request error: %d\n", ret); goto np_err; } info->gpio_nreset = pdata->gpio_nreset; - gpio_direction_output(info->gpio_nreset, 0); gpio_export(info->gpio_nreset, 0); } if (gpio_is_valid(pdata->gpio_nstby)) { - ret = gpio_request(pdata->gpio_nstby, "NOON010PC30 NSTBY"); + ret = devm_gpio_request_one(&client->dev, pdata->gpio_nstby, + GPIOF_OUT_INIT_LOW, + "NOON010PC30 NSTBY"); if (ret) { dev_err(&client->dev, "GPIO request error: %d\n", ret); - goto np_gpio_err; + goto np_err; } info->gpio_nstby = pdata->gpio_nstby; - gpio_direction_output(info->gpio_nstby, 0); gpio_export(info->gpio_nstby, 0); } for (i = 0; i < NOON010_NUM_SUPPLIES; i++) info->supply[i].supply = noon010_supply_name[i]; - ret = regulator_bulk_get(&client->dev, NOON010_NUM_SUPPLIES, + ret = devm_regulator_bulk_get(&client->dev, NOON010_NUM_SUPPLIES, info->supply); if (ret) - goto np_reg_err; + goto np_err; info->pad.flags = MEDIA_PAD_FL_SOURCE; sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR; ret = media_entity_init(&sd->entity, 1, &info->pad, 0); if (ret < 0) - goto np_me_err; + goto np_err; ret = noon010_detect(client, info); if (!ret) return 0; -np_me_err: - regulator_bulk_free(NOON010_NUM_SUPPLIES, info->supply); -np_reg_err: - if (gpio_is_valid(info->gpio_nstby)) - gpio_free(info->gpio_nstby); -np_gpio_err: - if (gpio_is_valid(info->gpio_nreset)) - gpio_free(info->gpio_nreset); np_err: v4l2_ctrl_handler_free(&info->hdl); v4l2_device_unregister_subdev(sd); - kfree(info); return ret; } @@ -807,17 +799,8 @@ static int noon010_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&info->hdl); - - regulator_bulk_free(NOON010_NUM_SUPPLIES, info->supply); - - if (gpio_is_valid(info->gpio_nreset)) - gpio_free(info->gpio_nreset); - - if (gpio_is_valid(info->gpio_nstby)) - gpio_free(info->gpio_nstby); - media_entity_cleanup(&sd->entity); - kfree(info); + return 0; } diff --git a/drivers/media/i2c/ov7640.c b/drivers/media/i2c/ov7640.c index b0cc927e8b19..faa64baf09e8 100644 --- a/drivers/media/i2c/ov7640.c +++ b/drivers/media/i2c/ov7640.c @@ -20,7 +20,6 @@ #include <linux/i2c.h> #include <linux/videodev2.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> #include <linux/slab.h> MODULE_DESCRIPTION("OmniVision ov7640 sensor driver"); @@ -59,7 +58,7 @@ static int ov7640_probe(struct i2c_client *client, if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -ENODEV; - sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); + sd = devm_kzalloc(&client->dev, sizeof(*sd), GFP_KERNEL); if (sd == NULL) return -ENOMEM; v4l2_i2c_subdev_init(sd, client, &ov7640_ops); @@ -71,7 +70,6 @@ static int ov7640_probe(struct i2c_client *client, if (write_regs(client, initial_registers) < 0) { v4l_err(client, "error initializing OV7640\n"); - kfree(sd); return -ENODEV; } @@ -84,7 +82,7 @@ static int ov7640_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); v4l2_device_unregister_subdev(sd); - kfree(sd); + return 0; } diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c index 617ad3fff4aa..e8a1ce204036 100644 --- a/drivers/media/i2c/ov7670.c +++ b/drivers/media/i2c/ov7670.c @@ -17,7 +17,6 @@ #include <linux/delay.h> #include <linux/videodev2.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-mediabus.h> #include <media/ov7670.h> @@ -1462,25 +1461,12 @@ static const struct v4l2_ctrl_ops ov7670_ctrl_ops = { .g_volatile_ctrl = ov7670_g_volatile_ctrl, }; -static int ov7670_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_OV7670, 0); -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int ov7670_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); unsigned char val = 0; int ret; - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; ret = ov7670_read(sd, reg->reg & 0xff, &val); reg->val = val; reg->size = 1; @@ -1489,12 +1475,6 @@ static int ov7670_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *r static int ov7670_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; ov7670_write(sd, reg->reg & 0xff, reg->val & 0xff); return 0; } @@ -1503,7 +1483,6 @@ static int ov7670_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_regis /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops ov7670_core_ops = { - .g_chip_ident = ov7670_g_chip_ident, .reset = ov7670_reset, .init = ov7670_init, #ifdef CONFIG_VIDEO_ADV_DEBUG @@ -1552,7 +1531,7 @@ static int ov7670_probe(struct i2c_client *client, struct ov7670_info *info; int ret; - info = kzalloc(sizeof(struct ov7670_info), GFP_KERNEL); + info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL); if (info == NULL) return -ENOMEM; sd = &info->sd; @@ -1590,7 +1569,6 @@ static int ov7670_probe(struct i2c_client *client, v4l_dbg(1, debug, client, "chip found @ 0x%x (%s) is not an ov7670 chip.\n", client->addr << 1, client->adapter->name); - kfree(info); return ret; } v4l_info(client, "chip found @ 0x%02x (%s)\n", @@ -1635,7 +1613,6 @@ static int ov7670_probe(struct i2c_client *client, int err = info->hdl.error; v4l2_ctrl_handler_free(&info->hdl); - kfree(info); return err; } /* @@ -1659,7 +1636,6 @@ static int ov7670_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&info->hdl); - kfree(info); return 0; } diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c index 9eac5310942f..825ea86d982d 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c @@ -1385,9 +1385,12 @@ static int __s5c73m3_power_off(struct s5c73m3 *state) } return 0; err: - for (++i; i < S5C73M3_MAX_SUPPLIES; i++) - regulator_enable(state->supplies[i].consumer); - + for (++i; i < S5C73M3_MAX_SUPPLIES; i++) { + int r = regulator_enable(state->supplies[i].consumer); + if (r < 0) + v4l2_err(&state->oif_sd, "Failed to reenable %s: %d\n", + state->supplies[i].supply, r); + } return ret; } @@ -1511,59 +1514,40 @@ static const struct v4l2_subdev_ops oif_subdev_ops = { .video = &s5c73m3_oif_video_ops, }; -static int s5c73m3_configure_gpio(int nr, int val, const char *name) -{ - unsigned long flags = val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; - int ret; - - if (!gpio_is_valid(nr)) - return 0; - ret = gpio_request_one(nr, flags, name); - if (!ret) - gpio_export(nr, 0); - return ret; -} - -static int s5c73m3_free_gpios(struct s5c73m3 *state) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(state->gpio); i++) { - if (!gpio_is_valid(state->gpio[i].gpio)) - continue; - gpio_free(state->gpio[i].gpio); - state->gpio[i].gpio = -EINVAL; - } - return 0; -} - static int s5c73m3_configure_gpios(struct s5c73m3 *state, const struct s5c73m3_platform_data *pdata) { - const struct s5c73m3_gpio *gpio = &pdata->gpio_stby; + struct device *dev = &state->i2c_client->dev; + const struct s5c73m3_gpio *gpio; + unsigned long flags; int ret; state->gpio[STBY].gpio = -EINVAL; state->gpio[RST].gpio = -EINVAL; - ret = s5c73m3_configure_gpio(gpio->gpio, gpio->level, "S5C73M3_STBY"); - if (ret) { - s5c73m3_free_gpios(state); - return ret; + gpio = &pdata->gpio_stby; + if (gpio_is_valid(gpio->gpio)) { + flags = (gpio->level ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW) + | GPIOF_EXPORT; + ret = devm_gpio_request_one(dev, gpio->gpio, flags, + "S5C73M3_STBY"); + if (ret < 0) + return ret; + + state->gpio[STBY] = *gpio; } - state->gpio[STBY] = *gpio; - if (gpio_is_valid(gpio->gpio)) - gpio_set_value(gpio->gpio, 0); gpio = &pdata->gpio_reset; - ret = s5c73m3_configure_gpio(gpio->gpio, gpio->level, "S5C73M3_RST"); - if (ret) { - s5c73m3_free_gpios(state); - return ret; + if (gpio_is_valid(gpio->gpio)) { + flags = (gpio->level ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW) + | GPIOF_EXPORT; + ret = devm_gpio_request_one(dev, gpio->gpio, flags, + "S5C73M3_RST"); + if (ret < 0) + return ret; + + state->gpio[RST] = *gpio; } - state->gpio[RST] = *gpio; - if (gpio_is_valid(gpio->gpio)) - gpio_set_value(gpio->gpio, 0); return 0; } @@ -1626,10 +1610,11 @@ static int s5c73m3_probe(struct i2c_client *client, state->mclk_frequency = pdata->mclk_frequency; state->bus_type = pdata->bus_type; + state->i2c_client = client; ret = s5c73m3_configure_gpios(state, pdata); if (ret) - goto out_err1; + goto out_err; for (i = 0; i < S5C73M3_MAX_SUPPLIES; i++) state->supplies[i].supply = s5c73m3_supply_names[i]; @@ -1638,12 +1623,12 @@ static int s5c73m3_probe(struct i2c_client *client, state->supplies); if (ret) { dev_err(dev, "failed to get regulators\n"); - goto out_err2; + goto out_err; } ret = s5c73m3_init_controls(state); if (ret) - goto out_err2; + goto out_err; state->sensor_pix_size[RES_ISP] = &s5c73m3_isp_resolutions[1]; state->sensor_pix_size[RES_JPEG] = &s5c73m3_jpeg_resolutions[1]; @@ -1659,16 +1644,12 @@ static int s5c73m3_probe(struct i2c_client *client, ret = s5c73m3_register_spi_driver(state); if (ret < 0) - goto out_err2; - - state->i2c_client = client; + goto out_err; v4l2_info(sd, "%s: completed succesfully\n", __func__); return 0; -out_err2: - s5c73m3_free_gpios(state); -out_err1: +out_err: media_entity_cleanup(&sd->entity); return ret; } @@ -1688,7 +1669,6 @@ static int s5c73m3_remove(struct i2c_client *client) media_entity_cleanup(&sensor_sd->entity); s5c73m3_unregister_spi_driver(state); - s5c73m3_free_gpios(state); return 0; } diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-spi.c b/drivers/media/i2c/s5c73m3/s5c73m3-spi.c index 6f3a9c00fe65..8079e26eb5e2 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-spi.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-spi.c @@ -73,7 +73,7 @@ int s5c73m3_spi_write(struct s5c73m3 *state, const void *addr, memset(padding, 0, sizeof(padding)); - for (i = 0; i < count ; i++) { + for (i = 0; i < count; i++) { r = spi_xmit(spi_dev, (void *)addr + j, tx_size, SPI_DIR_TX); if (r < 0) return r; @@ -98,7 +98,7 @@ int s5c73m3_spi_read(struct s5c73m3 *state, void *addr, unsigned int i, j = 0; int r = 0; - for (i = 0; i < count ; i++) { + for (i = 0; i < count; i++) { r = spi_xmit(spi_dev, addr + j, tx_size, SPI_DIR_RX); if (r < 0) return r; diff --git a/drivers/media/i2c/s5k6aa.c b/drivers/media/i2c/s5k6aa.c index bdf5e3db31d1..789c02a6ca1a 100644 --- a/drivers/media/i2c/s5k6aa.c +++ b/drivers/media/i2c/s5k6aa.c @@ -1491,58 +1491,41 @@ static const struct v4l2_subdev_ops s5k6aa_subdev_ops = { /* * GPIO setup */ -static int s5k6aa_configure_gpio(int nr, int val, const char *name) -{ - unsigned long flags = val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; - int ret; - - if (!gpio_is_valid(nr)) - return 0; - ret = gpio_request_one(nr, flags, name); - if (!ret) - gpio_export(nr, 0); - return ret; -} - -static void s5k6aa_free_gpios(struct s5k6aa *s5k6aa) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(s5k6aa->gpio); i++) { - if (!gpio_is_valid(s5k6aa->gpio[i].gpio)) - continue; - gpio_free(s5k6aa->gpio[i].gpio); - s5k6aa->gpio[i].gpio = -EINVAL; - } -} static int s5k6aa_configure_gpios(struct s5k6aa *s5k6aa, const struct s5k6aa_platform_data *pdata) { - const struct s5k6aa_gpio *gpio = &pdata->gpio_stby; + struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd); + const struct s5k6aa_gpio *gpio; + unsigned long flags; int ret; s5k6aa->gpio[STBY].gpio = -EINVAL; s5k6aa->gpio[RST].gpio = -EINVAL; - ret = s5k6aa_configure_gpio(gpio->gpio, gpio->level, "S5K6AA_STBY"); - if (ret) { - s5k6aa_free_gpios(s5k6aa); - return ret; + gpio = &pdata->gpio_stby; + if (gpio_is_valid(gpio->gpio)) { + flags = (gpio->level ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW) + | GPIOF_EXPORT; + ret = devm_gpio_request_one(&client->dev, gpio->gpio, flags, + "S5K6AA_STBY"); + if (ret < 0) + return ret; + + s5k6aa->gpio[STBY] = *gpio; } - s5k6aa->gpio[STBY] = *gpio; - if (gpio_is_valid(gpio->gpio)) - gpio_set_value(gpio->gpio, 0); gpio = &pdata->gpio_reset; - ret = s5k6aa_configure_gpio(gpio->gpio, gpio->level, "S5K6AA_RST"); - if (ret) { - s5k6aa_free_gpios(s5k6aa); - return ret; + if (gpio_is_valid(gpio->gpio)) { + flags = (gpio->level ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW) + | GPIOF_EXPORT; + ret = devm_gpio_request_one(&client->dev, gpio->gpio, flags, + "S5K6AA_RST"); + if (ret < 0) + return ret; + + s5k6aa->gpio[RST] = *gpio; } - s5k6aa->gpio[RST] = *gpio; - if (gpio_is_valid(gpio->gpio)) - gpio_set_value(gpio->gpio, 0); return 0; } @@ -1593,7 +1576,7 @@ static int s5k6aa_probe(struct i2c_client *client, ret = s5k6aa_configure_gpios(s5k6aa, pdata); if (ret) - goto out_err2; + goto out_err; for (i = 0; i < S5K6AA_NUM_SUPPLIES; i++) s5k6aa->supplies[i].supply = s5k6aa_supply_names[i]; @@ -1602,12 +1585,12 @@ static int s5k6aa_probe(struct i2c_client *client, s5k6aa->supplies); if (ret) { dev_err(&client->dev, "Failed to get regulators\n"); - goto out_err3; + goto out_err; } ret = s5k6aa_initialize_ctrls(s5k6aa); if (ret) - goto out_err3; + goto out_err; s5k6aa_presets_data_init(s5k6aa); @@ -1618,9 +1601,7 @@ static int s5k6aa_probe(struct i2c_client *client, return 0; -out_err3: - s5k6aa_free_gpios(s5k6aa); -out_err2: +out_err: media_entity_cleanup(&s5k6aa->sd.entity); return ret; } @@ -1628,12 +1609,10 @@ out_err2: static int s5k6aa_remove(struct i2c_client *client) { struct v4l2_subdev *sd = i2c_get_clientdata(client); - struct s5k6aa *s5k6aa = to_s5k6aa(sd); v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(sd->ctrl_handler); media_entity_cleanup(&sd->entity); - s5k6aa_free_gpios(s5k6aa); return 0; } diff --git a/drivers/media/i2c/saa6588.c b/drivers/media/i2c/saa6588.c index b4e1ccbd87ec..70bc72e795d0 100644 --- a/drivers/media/i2c/saa6588.c +++ b/drivers/media/i2c/saa6588.c @@ -33,7 +33,6 @@ #include <media/saa6588.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> /* insmod options */ @@ -443,17 +442,9 @@ static int saa6588_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt) return 0; } -static int saa6588_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA6588, 0); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops saa6588_core_ops = { - .g_chip_ident = saa6588_g_chip_ident, .ioctl = saa6588_ioctl, }; @@ -478,17 +469,15 @@ static int saa6588_probe(struct i2c_client *client, v4l_info(client, "saa6588 found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - s = kzalloc(sizeof(*s), GFP_KERNEL); + s = devm_kzalloc(&client->dev, sizeof(*s), GFP_KERNEL); if (s == NULL) return -ENOMEM; s->buf_size = bufblocks * 3; - s->buffer = kmalloc(s->buf_size, GFP_KERNEL); - if (s->buffer == NULL) { - kfree(s); + s->buffer = devm_kzalloc(&client->dev, s->buf_size, GFP_KERNEL); + if (s->buffer == NULL) return -ENOMEM; - } sd = &s->sd; v4l2_i2c_subdev_init(sd, client, &saa6588_ops); spin_lock_init(&s->lock); @@ -516,8 +505,6 @@ static int saa6588_remove(struct i2c_client *client) cancel_delayed_work_sync(&s->work); - kfree(s->buffer); - kfree(s); return 0; } diff --git a/drivers/media/i2c/saa7110.c b/drivers/media/i2c/saa7110.c index 51cd4c8f0520..ac43e929a1d6 100644 --- a/drivers/media/i2c/saa7110.c +++ b/drivers/media/i2c/saa7110.c @@ -35,7 +35,6 @@ #include <linux/i2c.h> #include <linux/videodev2.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> #include <media/v4l2-ctrls.h> MODULE_DESCRIPTION("Philips SAA7110 video decoder driver"); @@ -203,7 +202,7 @@ static v4l2_std_id determine_norm(struct v4l2_subdev *sd) status = saa7110_read(sd); if (status & 0x40) { v4l2_dbg(1, debug, sd, "status=0x%02x (no signal)\n", status); - return decoder->norm; /* no change*/ + return V4L2_STD_UNKNOWN; } if ((status & 3) == 0) { saa7110_write(sd, 0x06, 0x83); @@ -265,7 +264,7 @@ static int saa7110_g_input_status(struct v4l2_subdev *sd, u32 *pstatus) static int saa7110_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) { - *(v4l2_std_id *)std = determine_norm(sd); + *std &= determine_norm(sd); return 0; } @@ -352,13 +351,6 @@ static int saa7110_s_ctrl(struct v4l2_ctrl *ctrl) return 0; } -static int saa7110_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7110, 0); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_ctrl_ops saa7110_ctrl_ops = { @@ -366,7 +358,6 @@ static const struct v4l2_ctrl_ops saa7110_ctrl_ops = { }; static const struct v4l2_subdev_core_ops saa7110_core_ops = { - .g_chip_ident = saa7110_g_chip_ident, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, @@ -406,7 +397,7 @@ static int saa7110_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - decoder = kzalloc(sizeof(struct saa7110), GFP_KERNEL); + decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL); if (!decoder) return -ENOMEM; sd = &decoder->sd; @@ -428,7 +419,6 @@ static int saa7110_probe(struct i2c_client *client, int err = decoder->hdl.error; v4l2_ctrl_handler_free(&decoder->hdl); - kfree(decoder); return err; } v4l2_ctrl_handler_setup(&decoder->hdl); @@ -469,7 +459,6 @@ static int saa7110_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&decoder->hdl); - kfree(decoder); return 0; } diff --git a/drivers/media/i2c/saa7115.c b/drivers/media/i2c/saa7115.c index 52c717d977c9..7fd766ec64c8 100644 --- a/drivers/media/i2c/saa7115.c +++ b/drivers/media/i2c/saa7115.c @@ -46,7 +46,6 @@ #include <linux/videodev2.h> #include <media/v4l2-device.h> #include <media/v4l2-ctrls.h> -#include <media/v4l2-chip-ident.h> #include <media/saa7115.h> #include <asm/div64.h> @@ -63,6 +62,16 @@ module_param(debug, bool, 0644); MODULE_PARM_DESC(debug, "Debug level (0-1)"); +enum saa711x_model { + SAA7111A, + SAA7111, + SAA7113, + GM7113C, + SAA7114, + SAA7115, + SAA7118, +}; + struct saa711x_state { struct v4l2_subdev sd; struct v4l2_ctrl_handler hdl; @@ -80,7 +89,7 @@ struct saa711x_state { int radio; int width; int height; - u32 ident; + enum saa711x_model ident; u32 audclk_freq; u32 crystal_freq; bool ucgc; @@ -111,10 +120,10 @@ static inline int saa711x_write(struct v4l2_subdev *sd, u8 reg, u8 value) /* Sanity routine to check if a register is present */ static int saa711x_has_reg(const int id, const u8 reg) { - if (id == V4L2_IDENT_SAA7111) + if (id == SAA7111) return reg < 0x20 && reg != 0x01 && reg != 0x0f && (reg < 0x13 || reg > 0x19) && reg != 0x1d && reg != 0x1e; - if (id == V4L2_IDENT_SAA7111A) + if (id == SAA7111A) return reg < 0x20 && reg != 0x01 && reg != 0x0f && reg != 0x14 && reg != 0x18 && reg != 0x19 && reg != 0x1d && reg != 0x1e; @@ -127,16 +136,18 @@ static int saa711x_has_reg(const int id, const u8 reg) return 0; switch (id) { - case V4L2_IDENT_SAA7113: + case GM7113C: + return reg != 0x14 && (reg < 0x18 || reg > 0x1e) && reg < 0x20; + case SAA7113: return reg != 0x14 && (reg < 0x18 || reg > 0x1e) && (reg < 0x20 || reg > 0x3f) && reg != 0x5d && reg < 0x63; - case V4L2_IDENT_SAA7114: + case SAA7114: return (reg < 0x1a || reg > 0x1e) && (reg < 0x20 || reg > 0x2f) && (reg < 0x63 || reg > 0x7f) && reg != 0x33 && reg != 0x37 && reg != 0x81 && reg < 0xf0; - case V4L2_IDENT_SAA7115: + case SAA7115: return (reg < 0x20 || reg > 0x2f) && reg != 0x65 && (reg < 0xfc || reg > 0xfe); - case V4L2_IDENT_SAA7118: + case SAA7118: return (reg < 0x1a || reg > 0x1d) && (reg < 0x20 || reg > 0x22) && (reg < 0x26 || reg > 0x28) && reg != 0x33 && reg != 0x37 && (reg < 0x63 || reg > 0x7f) && reg != 0x81 && reg < 0xf0; @@ -214,7 +225,10 @@ static const unsigned char saa7111_init[] = { 0x00, 0x00 }; -/* SAA7113 init codes */ +/* SAA7113/GM7113C init codes + * It's important that R_14... R_17 == 0x00 + * for the gm7113c chip to deliver stable video + */ static const unsigned char saa7113_init[] = { R_01_INC_DELAY, 0x08, R_02_INPUT_CNTL_1, 0xc2, @@ -448,6 +462,24 @@ static const unsigned char saa7115_cfg_50hz_video[] = { /* ============== SAA7715 VIDEO templates (end) ======= */ +/* ============== GM7113C VIDEO templates ============= */ +static const unsigned char gm7113c_cfg_60hz_video[] = { + R_08_SYNC_CNTL, 0x68, /* 0xBO: auto detection, 0x68 = NTSC */ + R_0E_CHROMA_CNTL_1, 0x07, /* video autodetection is on */ + + 0x00, 0x00 +}; + +static const unsigned char gm7113c_cfg_50hz_video[] = { + R_08_SYNC_CNTL, 0x28, /* 0x28 = PAL */ + R_0E_CHROMA_CNTL_1, 0x07, + + 0x00, 0x00 +}; + +/* ============== GM7113C VIDEO templates (end) ======= */ + + static const unsigned char saa7115_cfg_vbi_on[] = { R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */ R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */ @@ -932,11 +964,17 @@ static void saa711x_set_v4lstd(struct v4l2_subdev *sd, v4l2_std_id std) // This works for NTSC-M, SECAM-L and the 50Hz PAL variants. if (std & V4L2_STD_525_60) { v4l2_dbg(1, debug, sd, "decoder set standard 60 Hz\n"); - saa711x_writeregs(sd, saa7115_cfg_60hz_video); + if (state->ident == GM7113C) + saa711x_writeregs(sd, gm7113c_cfg_60hz_video); + else + saa711x_writeregs(sd, saa7115_cfg_60hz_video); saa711x_set_size(sd, 720, 480); } else { v4l2_dbg(1, debug, sd, "decoder set standard 50 Hz\n"); - saa711x_writeregs(sd, saa7115_cfg_50hz_video); + if (state->ident == GM7113C) + saa711x_writeregs(sd, gm7113c_cfg_50hz_video); + else + saa711x_writeregs(sd, saa7115_cfg_50hz_video); saa711x_set_size(sd, 720, 576); } @@ -949,7 +987,8 @@ static void saa711x_set_v4lstd(struct v4l2_subdev *sd, v4l2_std_id std) 011 NTSC N (3.58MHz) PAL M (3.58MHz) 100 reserved NTSC-Japan (3.58MHz) */ - if (state->ident <= V4L2_IDENT_SAA7113) { + if (state->ident <= SAA7113 || + state->ident == GM7113C) { u8 reg = saa711x_read(sd, R_0E_CHROMA_CNTL_1) & 0x8f; if (std == V4L2_STD_PAL_M) { @@ -968,9 +1007,8 @@ static void saa711x_set_v4lstd(struct v4l2_subdev *sd, v4l2_std_id std) /* restart task B if needed */ int taskb = saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10; - if (taskb && state->ident == V4L2_IDENT_SAA7114) { + if (taskb && state->ident == SAA7114) saa711x_writeregs(sd, saa7115_cfg_vbi_on); - } /* switch audio mode too! */ saa711x_s_clock_freq(sd, state->audclk_freq); @@ -992,7 +1030,7 @@ static void saa711x_set_lcr(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_forma #else /* SAA7113 and SAA7118 also should support VBI - Need testing */ - if (state->ident != V4L2_IDENT_SAA7115) + if (state->ident != SAA7115) return; #endif @@ -1214,13 +1252,14 @@ static int saa711x_s_routing(struct v4l2_subdev *sd, u32 input, u32 output, u32 config) { struct saa711x_state *state = to_state(sd); - u8 mask = (state->ident <= V4L2_IDENT_SAA7111A) ? 0xf8 : 0xf0; + u8 mask = (state->ident <= SAA7111A) ? 0xf8 : 0xf0; v4l2_dbg(1, debug, sd, "decoder set input %d output %d\n", input, output); /* saa7111/3 does not have these inputs */ - if (state->ident <= V4L2_IDENT_SAA7113 && + if ((state->ident <= SAA7113 || + state->ident == GM7113C) && (input == SAA7115_COMPOSITE4 || input == SAA7115_COMPOSITE5)) { return -EINVAL; @@ -1235,7 +1274,7 @@ static int saa711x_s_routing(struct v4l2_subdev *sd, state->input = input; /* saa7111 has slightly different input numbering */ - if (state->ident <= V4L2_IDENT_SAA7111A) { + if (state->ident <= SAA7111A) { if (input >= SAA7115_COMPOSITE4) input -= 2; /* saa7111 specific */ @@ -1258,13 +1297,13 @@ static int saa711x_s_routing(struct v4l2_subdev *sd, (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0)); state->output = output; - if (state->ident == V4L2_IDENT_SAA7114 || - state->ident == V4L2_IDENT_SAA7115) { + if (state->ident == SAA7114 || + state->ident == SAA7115) { saa711x_write(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK, (saa711x_read(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK) & 0xfe) | (state->output & 0x01)); } - if (state->ident > V4L2_IDENT_SAA7111A) { + if (state->ident > SAA7111A) { if (config & SAA7115_IDQ_IS_DEFAULT) saa711x_write(sd, R_85_I_PORT_SIGNAL_POLAR, 0x20); else @@ -1277,7 +1316,7 @@ static int saa711x_s_gpio(struct v4l2_subdev *sd, u32 val) { struct saa711x_state *state = to_state(sd); - if (state->ident > V4L2_IDENT_SAA7111A) + if (state->ident > SAA7111A) return -EINVAL; saa711x_write(sd, 0x11, (saa711x_read(sd, 0x11) & 0x7f) | (val ? 0x80 : 0)); @@ -1367,7 +1406,7 @@ static int saa711x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC); - if (state->ident == V4L2_IDENT_SAA7115) { + if (state->ident == SAA7115) { reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC); v4l2_dbg(1, debug, sd, "Status byte 1 (0x1e)=0x%02x\n", reg1e); @@ -1389,6 +1428,7 @@ static int saa711x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) *std &= V4L2_STD_SECAM; break; default: + *std = V4L2_STD_UNKNOWN; /* Can't detect anything */ break; } @@ -1397,8 +1437,10 @@ static int saa711x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) v4l2_dbg(1, debug, sd, "Status byte 2 (0x1f)=0x%02x\n", reg1f); /* horizontal/vertical not locked */ - if (reg1f & 0x40) + if (reg1f & 0x40) { + *std = V4L2_STD_UNKNOWN; goto ret; + } if (reg1f & 0x20) *std &= V4L2_STD_525_60; @@ -1418,7 +1460,7 @@ static int saa711x_g_input_status(struct v4l2_subdev *sd, u32 *status) int reg1f; *status = V4L2_IN_ST_NO_SIGNAL; - if (state->ident == V4L2_IDENT_SAA7115) + if (state->ident == SAA7115) reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC); reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC); if ((reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80) @@ -1429,12 +1471,6 @@ static int saa711x_g_input_status(struct v4l2_subdev *sd, u32 *status) #ifdef CONFIG_VIDEO_ADV_DEBUG static int saa711x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; reg->val = saa711x_read(sd, reg->reg & 0xff); reg->size = 1; return 0; @@ -1442,25 +1478,11 @@ static int saa711x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register * static int saa711x_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; saa711x_write(sd, reg->reg & 0xff, reg->val & 0xff); return 0; } #endif -static int saa711x_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct saa711x_state *state = to_state(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, state->ident, 0); -} - static int saa711x_log_status(struct v4l2_subdev *sd) { struct saa711x_state *state = to_state(sd); @@ -1469,7 +1491,7 @@ static int saa711x_log_status(struct v4l2_subdev *sd) int vcr; v4l2_info(sd, "Audio frequency: %d Hz\n", state->audclk_freq); - if (state->ident != V4L2_IDENT_SAA7115) { + if (state->ident != SAA7115) { /* status for the saa7114 */ reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC); signalOk = (reg1f & 0xc1) == 0x81; @@ -1520,7 +1542,6 @@ static const struct v4l2_ctrl_ops saa711x_ctrl_ops = { static const struct v4l2_subdev_core_ops saa711x_core_ops = { .log_status = saa711x_log_status, - .g_chip_ident = saa711x_g_chip_ident, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, @@ -1571,55 +1592,145 @@ static const struct v4l2_subdev_ops saa711x_ops = { .vbi = &saa711x_vbi_ops, }; +#define CHIP_VER_SIZE 16 + /* ----------------------------------------------------------------------- */ -static int saa711x_probe(struct i2c_client *client, - const struct i2c_device_id *id) +/** + * saa711x_detect_chip - Detects the saa711x (or clone) variant + * @client: I2C client structure. + * @id: I2C device ID structure. + * @name: Name of the device to be filled. + * + * Detects the Philips/NXP saa711x chip, or some clone of it. + * if 'id' is NULL or id->driver_data is equal to 1, it auto-probes + * the analog demod. + * If the tuner is not found, it returns -ENODEV. + * If auto-detection is disabled and the tuner doesn't match what it was + * requred, it returns -EINVAL and fills 'name'. + * If the chip is found, it returns the chip ID and fills 'name'. + */ +static int saa711x_detect_chip(struct i2c_client *client, + const struct i2c_device_id *id, + char *name) { - struct saa711x_state *state; - struct v4l2_subdev *sd; - struct v4l2_ctrl_handler *hdl; - int i; - char name[17]; + char chip_ver[CHIP_VER_SIZE]; char chip_id; - int autodetect = !id || id->driver_data == 1; + int i; + int autodetect; - /* Check if the adapter supports the needed features */ - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -EIO; + autodetect = !id || id->driver_data == 1; - for (i = 0; i < 0x0f; i++) { + /* Read the chip version register */ + for (i = 0; i < CHIP_VER_SIZE; i++) { i2c_smbus_write_byte_data(client, 0, i); - name[i] = (i2c_smbus_read_byte_data(client, 0) & 0x0f) + '0'; + chip_ver[i] = i2c_smbus_read_byte_data(client, 0); + name[i] = (chip_ver[i] & 0x0f) + '0'; if (name[i] > '9') name[i] += 'a' - '9' - 1; } name[i] = '\0'; - chip_id = name[5]; + /* Check if it is a Philips/NXP chip */ + if (!memcmp(name + 1, "f711", 4)) { + chip_id = name[5]; + snprintf(name, CHIP_VER_SIZE, "saa711%c", chip_id); - /* Check whether this chip is part of the saa711x series */ - if (memcmp(name + 1, "f711", 4)) { - v4l_dbg(1, debug, client, "chip found @ 0x%x (ID %s) does not match a known saa711x chip.\n", - client->addr << 1, name); - return -ENODEV; + if (!autodetect && strcmp(name, id->name)) + return -EINVAL; + + switch (chip_id) { + case '1': + if (chip_ver[0] & 0xf0) { + snprintf(name, CHIP_VER_SIZE, "saa711%ca", chip_id); + v4l_info(client, "saa7111a variant found\n"); + return SAA7111A; + } + return SAA7111; + case '3': + return SAA7113; + case '4': + return SAA7114; + case '5': + return SAA7115; + case '8': + return SAA7118; + default: + v4l2_info(client, + "WARNING: Philips/NXP chip unknown - Falling back to saa7111\n"); + return SAA7111; + } } - /* Safety check */ - if (!autodetect && id->name[6] != chip_id) { - v4l_warn(client, "found saa711%c while %s was expected\n", - chip_id, id->name); + /* Check if it is a gm7113c */ + if (!memcmp(name, "0000", 4)) { + chip_id = 0; + for (i = 0; i < 4; i++) { + chip_id = chip_id << 1; + chip_id |= (chip_ver[i] & 0x80) ? 1 : 0; + } + + /* + * Note: From the datasheet, only versions 1 and 2 + * exists. However, tests on a device labeled as: + * "GM7113C 1145" returned "10" on all 16 chip + * version (reg 0x00) reads. So, we need to also + * accept at least verion 0. For now, let's just + * assume that a device that returns "0000" for + * the lower nibble is a gm7113c. + */ + + strlcpy(name, "gm7113c", CHIP_VER_SIZE); + + if (!autodetect && strcmp(name, id->name)) + return -EINVAL; + + v4l_dbg(1, debug, client, + "It seems to be a %s chip (%*ph) @ 0x%x.\n", + name, 16, chip_ver, client->addr << 1); + + return GM7113C; } - snprintf(client->name, sizeof(client->name), "saa711%c", chip_id); - v4l_info(client, "saa711%c found (%s) @ 0x%x (%s)\n", chip_id, name, - client->addr << 1, client->adapter->name); - state = kzalloc(sizeof(struct saa711x_state), GFP_KERNEL); + /* Chip was not discovered. Return its ID and don't bind */ + v4l_dbg(1, debug, client, "chip %*ph @ 0x%x is unknown.\n", + 16, chip_ver, client->addr << 1); + return -ENODEV; +} + +static int saa711x_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct saa711x_state *state; + struct v4l2_subdev *sd; + struct v4l2_ctrl_handler *hdl; + int ident; + char name[CHIP_VER_SIZE + 1]; + + /* Check if the adapter supports the needed features */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -EIO; + + ident = saa711x_detect_chip(client, id, name); + if (ident == -EINVAL) { + /* Chip exists, but doesn't match */ + v4l_warn(client, "found %s while %s was expected\n", + name, id->name); + return -ENODEV; + } + if (ident < 0) + return ident; + + strlcpy(client->name, name, sizeof(client->name)); + + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (state == NULL) return -ENOMEM; sd = &state->sd; v4l2_i2c_subdev_init(sd, client, &saa711x_ops); + v4l_info(client, "%s found @ 0x%x (%s)\n", name, + client->addr << 1, client->adapter->name); hdl = &state->hdl; v4l2_ctrl_handler_init(hdl, 6); /* add in ascending ID order */ @@ -1640,7 +1751,6 @@ static int saa711x_probe(struct i2c_client *client, int err = hdl->error; v4l2_ctrl_handler_free(hdl); - kfree(state); return err; } v4l2_ctrl_auto_cluster(2, &state->agc, 0, true); @@ -1649,31 +1759,7 @@ static int saa711x_probe(struct i2c_client *client, state->output = SAA7115_IPORT_ON; state->enable = 1; state->radio = 0; - switch (chip_id) { - case '1': - state->ident = V4L2_IDENT_SAA7111; - if (saa711x_read(sd, R_00_CHIP_VERSION) & 0xf0) { - v4l_info(client, "saa7111a variant found\n"); - state->ident = V4L2_IDENT_SAA7111A; - } - break; - case '3': - state->ident = V4L2_IDENT_SAA7113; - break; - case '4': - state->ident = V4L2_IDENT_SAA7114; - break; - case '5': - state->ident = V4L2_IDENT_SAA7115; - break; - case '8': - state->ident = V4L2_IDENT_SAA7118; - break; - default: - state->ident = V4L2_IDENT_SAA7111; - v4l2_info(sd, "WARNING: Chip is not known - Falling back to saa7111\n"); - break; - } + state->ident = ident; state->audclk_freq = 48000; @@ -1682,18 +1768,19 @@ static int saa711x_probe(struct i2c_client *client, /* init to 60hz/48khz */ state->crystal_freq = SAA7115_FREQ_24_576_MHZ; switch (state->ident) { - case V4L2_IDENT_SAA7111: - case V4L2_IDENT_SAA7111A: + case SAA7111: + case SAA7111A: saa711x_writeregs(sd, saa7111_init); break; - case V4L2_IDENT_SAA7113: + case GM7113C: + case SAA7113: saa711x_writeregs(sd, saa7113_init); break; default: state->crystal_freq = SAA7115_FREQ_32_11_MHZ; saa711x_writeregs(sd, saa7115_init_auto_input); } - if (state->ident > V4L2_IDENT_SAA7111A) + if (state->ident > SAA7111A) saa711x_writeregs(sd, saa7115_init_misc); saa711x_set_v4lstd(sd, V4L2_STD_NTSC); v4l2_ctrl_handler_setup(hdl); @@ -1712,7 +1799,6 @@ static int saa711x_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(sd->ctrl_handler); - kfree(to_state(sd)); return 0; } @@ -1723,6 +1809,7 @@ static const struct i2c_device_id saa711x_id[] = { { "saa7114", 0 }, { "saa7115", 0 }, { "saa7118", 0 }, + { "gm7113c", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, saa711x_id); diff --git a/drivers/media/i2c/saa7127.c b/drivers/media/i2c/saa7127.c index 8a47ac10927f..264b755bedce 100644 --- a/drivers/media/i2c/saa7127.c +++ b/drivers/media/i2c/saa7127.c @@ -54,7 +54,6 @@ #include <linux/i2c.h> #include <linux/videodev2.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> #include <media/saa7127.h> static int debug; @@ -251,10 +250,15 @@ static struct i2c_reg_value saa7127_init_config_50hz_secam[] = { ********************************************************************** */ +enum saa712x_model { + SAA7127, + SAA7129, +}; + struct saa7127_state { struct v4l2_subdev sd; v4l2_std_id std; - u32 ident; + enum saa712x_model ident; enum saa7127_input_type input_type; enum saa7127_output_type output_type; int video_enable; @@ -482,7 +486,7 @@ static int saa7127_set_std(struct v4l2_subdev *sd, v4l2_std_id std) inittab = saa7127_init_config_60hz; state->reg_61 = SAA7127_60HZ_DAC_CONTROL; - } else if (state->ident == V4L2_IDENT_SAA7129 && + } else if (state->ident == SAA7129 && (std & V4L2_STD_SECAM) && !(std & (V4L2_STD_625_50 & ~V4L2_STD_SECAM))) { @@ -517,7 +521,7 @@ static int saa7127_set_output_type(struct v4l2_subdev *sd, int output) break; case SAA7127_OUTPUT_TYPE_COMPOSITE: - if (state->ident == V4L2_IDENT_SAA7129) + if (state->ident == SAA7129) state->reg_2d = 0x20; /* CVBS only */ else state->reg_2d = 0x08; /* 00001000 CVBS only, RGB DAC's off (high impedance mode) */ @@ -525,7 +529,7 @@ static int saa7127_set_output_type(struct v4l2_subdev *sd, int output) break; case SAA7127_OUTPUT_TYPE_SVIDEO: - if (state->ident == V4L2_IDENT_SAA7129) + if (state->ident == SAA7129) state->reg_2d = 0x18; /* Y + C */ else state->reg_2d = 0xff; /*11111111 croma -> R, luma -> CVBS + G + B */ @@ -543,7 +547,7 @@ static int saa7127_set_output_type(struct v4l2_subdev *sd, int output) break; case SAA7127_OUTPUT_TYPE_BOTH: - if (state->ident == V4L2_IDENT_SAA7129) + if (state->ident == SAA7129) state->reg_2d = 0x38; else state->reg_2d = 0xbf; @@ -661,12 +665,6 @@ static int saa7127_s_vbi_data(struct v4l2_subdev *sd, const struct v4l2_sliced_v #ifdef CONFIG_VIDEO_ADV_DEBUG static int saa7127_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; reg->val = saa7127_read(sd, reg->reg & 0xff); reg->size = 1; return 0; @@ -674,25 +672,11 @@ static int saa7127_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register * static int saa7127_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; saa7127_write(sd, reg->reg & 0xff, reg->val & 0xff); return 0; } #endif -static int saa7127_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct saa7127_state *state = to_state(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, state->ident, 0); -} - static int saa7127_log_status(struct v4l2_subdev *sd) { struct saa7127_state *state = to_state(sd); @@ -712,7 +696,6 @@ static int saa7127_log_status(struct v4l2_subdev *sd) static const struct v4l2_subdev_core_ops saa7127_core_ops = { .log_status = saa7127_log_status, - .g_chip_ident = saa7127_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = saa7127_g_register, .s_register = saa7127_s_register, @@ -752,7 +735,7 @@ static int saa7127_probe(struct i2c_client *client, v4l_dbg(1, debug, client, "detecting saa7127 client on address 0x%x\n", client->addr << 1); - state = kzalloc(sizeof(struct saa7127_state), GFP_KERNEL); + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (state == NULL) return -ENOMEM; @@ -767,7 +750,6 @@ static int saa7127_probe(struct i2c_client *client, if ((saa7127_read(sd, 0) & 0xe4) != 0 || (saa7127_read(sd, 0x29) & 0x3f) != 0x1d) { v4l2_dbg(1, debug, sd, "saa7127 not found\n"); - kfree(state); return -ENODEV; } @@ -782,10 +764,10 @@ static int saa7127_probe(struct i2c_client *client, if (saa7127_read(sd, SAA7129_REG_FADE_KEY_COL2) == 0xaa) { saa7127_write(sd, SAA7129_REG_FADE_KEY_COL2, read_result); - state->ident = V4L2_IDENT_SAA7129; + state->ident = SAA7129; strlcpy(client->name, "saa7129", I2C_NAME_SIZE); } else { - state->ident = V4L2_IDENT_SAA7127; + state->ident = SAA7127; strlcpy(client->name, "saa7127", I2C_NAME_SIZE); } } @@ -809,7 +791,7 @@ static int saa7127_probe(struct i2c_client *client, saa7127_set_input_type(sd, SAA7127_INPUT_TYPE_NORMAL); saa7127_set_video_enable(sd, 1); - if (state->ident == V4L2_IDENT_SAA7129) + if (state->ident == SAA7129) saa7127_write_inittab(sd, saa7129_init_config_extra); return 0; } @@ -823,7 +805,6 @@ static int saa7127_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); /* Turn off TV output */ saa7127_set_video_enable(sd, 0); - kfree(to_state(sd)); return 0; } @@ -831,10 +812,10 @@ static int saa7127_remove(struct i2c_client *client) static struct i2c_device_id saa7127_id[] = { { "saa7127_auto", 0 }, /* auto-detection */ - { "saa7126", V4L2_IDENT_SAA7127 }, - { "saa7127", V4L2_IDENT_SAA7127 }, - { "saa7128", V4L2_IDENT_SAA7129 }, - { "saa7129", V4L2_IDENT_SAA7129 }, + { "saa7126", SAA7127 }, + { "saa7127", SAA7127 }, + { "saa7128", SAA7129 }, + { "saa7129", SAA7129 }, { } }; MODULE_DEVICE_TABLE(i2c, saa7127_id); diff --git a/drivers/media/i2c/saa717x.c b/drivers/media/i2c/saa717x.c index cf3a0aa7e45e..401ca114ab99 100644 --- a/drivers/media/i2c/saa717x.c +++ b/drivers/media/i2c/saa717x.c @@ -977,12 +977,6 @@ static int saa717x_s_video_routing(struct v4l2_subdev *sd, #ifdef CONFIG_VIDEO_ADV_DEBUG static int saa717x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; reg->val = saa717x_read(sd, reg->reg); reg->size = 1; return 0; @@ -990,14 +984,9 @@ static int saa717x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register * static int saa717x_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); u16 addr = reg->reg & 0xffff; u8 val = reg->val & 0xff; - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; saa717x_write(sd, addr, val); return 0; } @@ -1262,7 +1251,7 @@ static int saa717x_probe(struct i2c_client *client, if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -EIO; - decoder = kzalloc(sizeof(struct saa717x_state), GFP_KERNEL); + decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL); if (decoder == NULL) return -ENOMEM; @@ -1276,7 +1265,6 @@ static int saa717x_probe(struct i2c_client *client, id = saa717x_read(sd, 0x5a0); if (id != 0xc2 && id != 0x32 && id != 0xf2 && id != 0x6c) { v4l2_dbg(1, debug, sd, "saa717x not found (id=%02x)\n", id); - kfree(decoder); return -ENODEV; } if (id == 0xc2) @@ -1316,7 +1304,6 @@ static int saa717x_probe(struct i2c_client *client, int err = hdl->error; v4l2_ctrl_handler_free(hdl); - kfree(decoder); return err; } @@ -1353,7 +1340,6 @@ static int saa717x_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(sd->ctrl_handler); - kfree(to_state(sd)); return 0; } diff --git a/drivers/media/i2c/saa7185.c b/drivers/media/i2c/saa7185.c index 2c6b65c76e2b..f56c1c88b27d 100644 --- a/drivers/media/i2c/saa7185.c +++ b/drivers/media/i2c/saa7185.c @@ -32,7 +32,6 @@ #include <linux/i2c.h> #include <linux/videodev2.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> MODULE_DESCRIPTION("Philips SAA7185 video encoder driver"); MODULE_AUTHOR("Dave Perks"); @@ -285,17 +284,9 @@ static int saa7185_s_routing(struct v4l2_subdev *sd, return 0; } -static int saa7185_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7185, 0); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops saa7185_core_ops = { - .g_chip_ident = saa7185_g_chip_ident, .init = saa7185_init, }; @@ -326,7 +317,7 @@ static int saa7185_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - encoder = kzalloc(sizeof(struct saa7185), GFP_KERNEL); + encoder = devm_kzalloc(&client->dev, sizeof(*encoder), GFP_KERNEL); if (encoder == NULL) return -ENOMEM; encoder->norm = V4L2_STD_NTSC; @@ -352,7 +343,6 @@ static int saa7185_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); /* SW: output off is active */ saa7185_write(sd, 0x61, (encoder->reg[0x61]) | 0x40); - kfree(encoder); return 0; } diff --git a/drivers/media/i2c/saa7191.c b/drivers/media/i2c/saa7191.c index d7d1670e0ca3..606a4baf944d 100644 --- a/drivers/media/i2c/saa7191.c +++ b/drivers/media/i2c/saa7191.c @@ -22,7 +22,6 @@ #include <linux/videodev2.h> #include <linux/i2c.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> #include "saa7191.h" @@ -272,7 +271,7 @@ static int saa7191_querystd(struct v4l2_subdev *sd, v4l2_std_id *norm) dprintk("SAA7191 extended signal auto-detection...\n"); - *norm = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM; + *norm &= V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM; stdc &= ~SAA7191_STDC_SECS; ctl3 &= ~(SAA7191_CTL3_FSEL); @@ -303,7 +302,7 @@ static int saa7191_querystd(struct v4l2_subdev *sd, v4l2_std_id *norm) if (status & SAA7191_STATUS_FIDT) { /* 60Hz signal -> NTSC */ dprintk("60Hz signal: NTSC\n"); - *norm = V4L2_STD_NTSC; + *norm &= V4L2_STD_NTSC; return 0; } @@ -325,12 +324,13 @@ static int saa7191_querystd(struct v4l2_subdev *sd, v4l2_std_id *norm) if (status & SAA7191_STATUS_FIDT) { dprintk("No 50Hz signal\n"); saa7191_s_std(sd, old_norm); - return -EAGAIN; + *norm = V4L2_STD_UNKNOWN; + return 0; } if (status & SAA7191_STATUS_CODE) { dprintk("PAL\n"); - *norm = V4L2_STD_PAL; + *norm &= V4L2_STD_PAL; return saa7191_s_std(sd, old_norm); } @@ -350,18 +350,19 @@ static int saa7191_querystd(struct v4l2_subdev *sd, v4l2_std_id *norm) /* not 50Hz ? */ if (status & SAA7191_STATUS_FIDT) { dprintk("No 50Hz signal\n"); - err = -EAGAIN; + *norm = V4L2_STD_UNKNOWN; goto out; } if (status & SAA7191_STATUS_CODE) { /* Color detected -> SECAM */ dprintk("SECAM\n"); - *norm = V4L2_STD_SECAM; + *norm &= V4L2_STD_SECAM; return saa7191_s_std(sd, old_norm); } dprintk("No color detected with SECAM - Going back to PAL.\n"); + *norm = V4L2_STD_UNKNOWN; out: return saa7191_s_std(sd, old_norm); @@ -567,18 +568,9 @@ static int saa7191_g_input_status(struct v4l2_subdev *sd, u32 *status) } -static int saa7191_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7191, 0); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops saa7191_core_ops = { - .g_chip_ident = saa7191_g_chip_ident, .g_ctrl = saa7191_g_ctrl, .s_ctrl = saa7191_s_ctrl, .s_std = saa7191_s_std, @@ -605,7 +597,7 @@ static int saa7191_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - decoder = kzalloc(sizeof(*decoder), GFP_KERNEL); + decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL); if (!decoder) return -ENOMEM; @@ -615,7 +607,6 @@ static int saa7191_probe(struct i2c_client *client, err = saa7191_write_block(sd, sizeof(initseq), initseq); if (err) { printk(KERN_ERR "SAA7191 initialization failed\n"); - kfree(decoder); return err; } @@ -636,7 +627,6 @@ static int saa7191_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); v4l2_device_unregister_subdev(sd); - kfree(to_saa7191(sd)); return 0; } diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c index cae4f4683851..7ac7580f85c9 100644 --- a/drivers/media/i2c/smiapp/smiapp-core.c +++ b/drivers/media/i2c/smiapp/smiapp-core.c @@ -2383,8 +2383,9 @@ static int smiapp_registered(struct v4l2_subdev *subdev) } if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN) { - if (gpio_request_one(sensor->platform_data->xshutdown, 0, - "SMIA++ xshutdown") != 0) { + if (devm_gpio_request_one(&client->dev, + sensor->platform_data->xshutdown, 0, + "SMIA++ xshutdown") != 0) { dev_err(&client->dev, "unable to acquire reset gpio %d\n", sensor->platform_data->xshutdown); @@ -2393,10 +2394,8 @@ static int smiapp_registered(struct v4l2_subdev *subdev) } rval = smiapp_power_on(sensor); - if (rval) { - rval = -ENODEV; - goto out_smiapp_power_on; - } + if (rval) + return -ENODEV; rval = smiapp_identify_module(subdev); if (rval) { @@ -2656,11 +2655,6 @@ out_ident_release: out_power_off: smiapp_power_off(sensor); - -out_smiapp_power_on: - if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN) - gpio_free(sensor->platform_data->xshutdown); - return rval; } @@ -2854,12 +2848,10 @@ static int smiapp_remove(struct i2c_client *client) device_remove_file(&client->dev, &dev_attr_nvm); for (i = 0; i < sensor->ssds_used; i++) { - media_entity_cleanup(&sensor->ssds[i].sd.entity); v4l2_device_unregister_subdev(&sensor->ssds[i].sd); + media_entity_cleanup(&sensor->ssds[i].sd.entity); } smiapp_free_controls(sensor); - if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN) - gpio_free(sensor->platform_data->xshutdown); return 0; } diff --git a/drivers/media/i2c/soc_camera/imx074.c b/drivers/media/i2c/soc_camera/imx074.c index a2a5cbbdbe28..1d384a371b41 100644 --- a/drivers/media/i2c/soc_camera/imx074.c +++ b/drivers/media/i2c/soc_camera/imx074.c @@ -18,8 +18,9 @@ #include <linux/module.h> #include <media/soc_camera.h> +#include <media/v4l2-async.h> +#include <media/v4l2-clk.h> #include <media/v4l2-subdev.h> -#include <media/v4l2-chip-ident.h> /* IMX074 registers */ @@ -77,6 +78,7 @@ struct imx074_datafmt { struct imx074 { struct v4l2_subdev subdev; const struct imx074_datafmt *fmt; + struct v4l2_clk *clk; }; static const struct imx074_datafmt imx074_colour_fmts[] = { @@ -251,29 +253,13 @@ static int imx074_s_stream(struct v4l2_subdev *sd, int enable) return reg_write(client, MODE_SELECT, !!enable); } -static int imx074_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *id) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) - return -EINVAL; - - if (id->match.addr != client->addr) - return -ENODEV; - - id->ident = V4L2_IDENT_IMX074; - id->revision = 0; - - return 0; -} - static int imx074_s_power(struct v4l2_subdev *sd, int on) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + struct imx074 *priv = to_imx074(client); - return soc_camera_set_power(&client->dev, ssdd, on); + return soc_camera_set_power(&client->dev, ssdd, priv->clk, on); } static int imx074_g_mbus_config(struct v4l2_subdev *sd, @@ -299,7 +285,6 @@ static struct v4l2_subdev_video_ops imx074_subdev_video_ops = { }; static struct v4l2_subdev_core_ops imx074_subdev_core_ops = { - .g_chip_ident = imx074_g_chip_ident, .s_power = imx074_s_power, }; @@ -431,6 +416,7 @@ static int imx074_probe(struct i2c_client *client, struct imx074 *priv; struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + int ret; if (!ssdd) { dev_err(&client->dev, "IMX074: missing platform data!\n"); @@ -451,12 +437,35 @@ static int imx074_probe(struct i2c_client *client, priv->fmt = &imx074_colour_fmts[0]; - return imx074_video_probe(client); + priv->clk = v4l2_clk_get(&client->dev, "mclk"); + if (IS_ERR(priv->clk)) { + dev_info(&client->dev, "Error %ld getting clock\n", PTR_ERR(priv->clk)); + return -EPROBE_DEFER; + } + + ret = soc_camera_power_init(&client->dev, ssdd); + if (ret < 0) + goto epwrinit; + + ret = imx074_video_probe(client); + if (ret < 0) + goto eprobe; + + return v4l2_async_register_subdev(&priv->subdev); + +epwrinit: +eprobe: + v4l2_clk_put(priv->clk); + return ret; } static int imx074_remove(struct i2c_client *client) { struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + struct imx074 *priv = to_imx074(client); + + v4l2_async_unregister_subdev(&priv->subdev); + v4l2_clk_put(priv->clk); if (ssdd->free_bus) ssdd->free_bus(ssdd); diff --git a/drivers/media/i2c/soc_camera/mt9m001.c b/drivers/media/i2c/soc_camera/mt9m001.c index dd9089805757..df97033fa6ef 100644 --- a/drivers/media/i2c/soc_camera/mt9m001.c +++ b/drivers/media/i2c/soc_camera/mt9m001.c @@ -16,8 +16,8 @@ #include <media/soc_camera.h> #include <media/soc_mediabus.h> +#include <media/v4l2-clk.h> #include <media/v4l2-subdev.h> -#include <media/v4l2-chip-ident.h> #include <media/v4l2-ctrls.h> /* @@ -94,10 +94,10 @@ struct mt9m001 { struct v4l2_ctrl *exposure; }; struct v4l2_rect rect; /* Sensor window */ + struct v4l2_clk *clk; const struct mt9m001_datafmt *fmt; const struct mt9m001_datafmt *fmts; int num_fmts; - int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */ unsigned int total_h; unsigned short y_skip_top; /* Lines to skip at the top */ }; @@ -320,36 +320,15 @@ static int mt9m001_try_fmt(struct v4l2_subdev *sd, return 0; } -static int mt9m001_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *id) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct mt9m001 *mt9m001 = to_mt9m001(client); - - if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) - return -EINVAL; - - if (id->match.addr != client->addr) - return -ENODEV; - - id->ident = mt9m001->model; - id->revision = 0; - - return 0; -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int mt9m001_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + if (reg->reg > 0xff) return -EINVAL; - if (reg->match.addr != client->addr) - return -ENODEV; - reg->size = 2; reg->val = reg_read(client, reg->reg); @@ -364,12 +343,9 @@ static int mt9m001_s_register(struct v4l2_subdev *sd, { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + if (reg->reg > 0xff) return -EINVAL; - if (reg->match.addr != client->addr) - return -ENODEV; - if (reg_write(client, reg->reg, reg->val) < 0) return -EIO; @@ -381,8 +357,9 @@ static int mt9m001_s_power(struct v4l2_subdev *sd, int on) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + struct mt9m001 *mt9m001 = to_mt9m001(client); - return soc_camera_set_power(&client->dev, ssdd, on); + return soc_camera_set_power(&client->dev, ssdd, mt9m001->clk, on); } static int mt9m001_g_volatile_ctrl(struct v4l2_ctrl *ctrl) @@ -505,11 +482,9 @@ static int mt9m001_video_probe(struct soc_camera_subdev_desc *ssdd, switch (data) { case 0x8411: case 0x8421: - mt9m001->model = V4L2_IDENT_MT9M001C12ST; mt9m001->fmts = mt9m001_colour_fmts; break; case 0x8431: - mt9m001->model = V4L2_IDENT_MT9M001C12STM; mt9m001->fmts = mt9m001_monochrome_fmts; break; default: @@ -580,7 +555,6 @@ static const struct v4l2_ctrl_ops mt9m001_ctrl_ops = { }; static struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = { - .g_chip_ident = mt9m001_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = mt9m001_g_register, .s_register = mt9m001_s_register, @@ -710,9 +684,18 @@ static int mt9m001_probe(struct i2c_client *client, mt9m001->rect.width = MT9M001_MAX_WIDTH; mt9m001->rect.height = MT9M001_MAX_HEIGHT; + mt9m001->clk = v4l2_clk_get(&client->dev, "mclk"); + if (IS_ERR(mt9m001->clk)) { + ret = PTR_ERR(mt9m001->clk); + goto eclkget; + } + ret = mt9m001_video_probe(ssdd, client); - if (ret) + if (ret) { + v4l2_clk_put(mt9m001->clk); +eclkget: v4l2_ctrl_handler_free(&mt9m001->hdl); + } return ret; } @@ -722,6 +705,7 @@ static int mt9m001_remove(struct i2c_client *client) struct mt9m001 *mt9m001 = to_mt9m001(client); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + v4l2_clk_put(mt9m001->clk); v4l2_device_unregister_subdev(&mt9m001->subdev); v4l2_ctrl_handler_free(&mt9m001->hdl); mt9m001_video_remove(ssdd); diff --git a/drivers/media/i2c/soc_camera/mt9m111.c b/drivers/media/i2c/soc_camera/mt9m111.c index 8bd4e0d2ea03..de3605df47c5 100644 --- a/drivers/media/i2c/soc_camera/mt9m111.c +++ b/drivers/media/i2c/soc_camera/mt9m111.c @@ -17,9 +17,9 @@ #include <linux/module.h> #include <media/soc_camera.h> +#include <media/v4l2-clk.h> #include <media/v4l2-common.h> #include <media/v4l2-ctrls.h> -#include <media/v4l2-chip-ident.h> /* * MT9M111, MT9M112 and MT9M131: @@ -205,10 +205,9 @@ struct mt9m111 { struct v4l2_subdev subdev; struct v4l2_ctrl_handler hdl; struct v4l2_ctrl *gain; - int model; /* V4L2_IDENT_MT9M111 or V4L2_IDENT_MT9M112 code - * from v4l2-chip-ident.h */ struct mt9m111_context *ctx; struct v4l2_rect rect; /* cropping rectangle */ + struct v4l2_clk *clk; int width; /* output */ int height; /* sizes */ struct mutex power_lock; /* lock to protect power_count */ @@ -600,24 +599,6 @@ static int mt9m111_s_fmt(struct v4l2_subdev *sd, return ret; } -static int mt9m111_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *id) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev); - - if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) - return -EINVAL; - - if (id->match.addr != client->addr) - return -ENODEV; - - id->ident = mt9m111->model; - id->revision = 0; - - return 0; -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int mt9m111_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) @@ -625,10 +606,8 @@ static int mt9m111_g_register(struct v4l2_subdev *sd, struct i2c_client *client = v4l2_get_subdevdata(sd); int val; - if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) + if (reg->reg > 0x2ff) return -EINVAL; - if (reg->match.addr != client->addr) - return -ENODEV; val = mt9m111_reg_read(client, reg->reg); reg->size = 2; @@ -645,12 +624,9 @@ static int mt9m111_s_register(struct v4l2_subdev *sd, { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) + if (reg->reg > 0x2ff) return -EINVAL; - if (reg->match.addr != client->addr) - return -ENODEV; - if (mt9m111_reg_write(client, reg->reg, reg->val) < 0) return -EIO; @@ -801,14 +777,14 @@ static int mt9m111_power_on(struct mt9m111 *mt9m111) struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); int ret; - ret = soc_camera_power_on(&client->dev, ssdd); + ret = soc_camera_power_on(&client->dev, ssdd, mt9m111->clk); if (ret < 0) return ret; ret = mt9m111_resume(mt9m111); if (ret < 0) { dev_err(&client->dev, "Failed to resume the sensor: %d\n", ret); - soc_camera_power_off(&client->dev, ssdd); + soc_camera_power_off(&client->dev, ssdd, mt9m111->clk); } return ret; @@ -820,7 +796,7 @@ static void mt9m111_power_off(struct mt9m111 *mt9m111) struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); mt9m111_suspend(mt9m111); - soc_camera_power_off(&client->dev, ssdd); + soc_camera_power_off(&client->dev, ssdd, mt9m111->clk); } static int mt9m111_s_power(struct v4l2_subdev *sd, int on) @@ -856,7 +832,6 @@ static const struct v4l2_ctrl_ops mt9m111_ctrl_ops = { }; static struct v4l2_subdev_core_ops mt9m111_subdev_core_ops = { - .g_chip_ident = mt9m111_g_chip_ident, .s_power = mt9m111_s_power, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = mt9m111_g_register, @@ -923,12 +898,10 @@ static int mt9m111_video_probe(struct i2c_client *client) switch (data) { case 0x143a: /* MT9M111 or MT9M131 */ - mt9m111->model = V4L2_IDENT_MT9M111; dev_info(&client->dev, "Detected a MT9M111/MT9M131 chip ID %x\n", data); break; case 0x148c: /* MT9M112 */ - mt9m111->model = V4L2_IDENT_MT9M112; dev_info(&client->dev, "Detected a MT9M112 chip ID %x\n", data); break; default: @@ -1002,9 +975,18 @@ static int mt9m111_probe(struct i2c_client *client, mt9m111->lastpage = -1; mutex_init(&mt9m111->power_lock); + mt9m111->clk = v4l2_clk_get(&client->dev, "mclk"); + if (IS_ERR(mt9m111->clk)) { + ret = PTR_ERR(mt9m111->clk); + goto eclkget; + } + ret = mt9m111_video_probe(client); - if (ret) + if (ret) { + v4l2_clk_put(mt9m111->clk); +eclkget: v4l2_ctrl_handler_free(&mt9m111->hdl); + } return ret; } @@ -1013,6 +995,7 @@ static int mt9m111_remove(struct i2c_client *client) { struct mt9m111 *mt9m111 = to_mt9m111(client); + v4l2_clk_put(mt9m111->clk); v4l2_device_unregister_subdev(&mt9m111->subdev); v4l2_ctrl_handler_free(&mt9m111->hdl); diff --git a/drivers/media/i2c/soc_camera/mt9t031.c b/drivers/media/i2c/soc_camera/mt9t031.c index 26a15b87a9a2..47d18d0bafe7 100644 --- a/drivers/media/i2c/soc_camera/mt9t031.c +++ b/drivers/media/i2c/soc_camera/mt9t031.c @@ -18,7 +18,7 @@ #include <linux/module.h> #include <media/soc_camera.h> -#include <media/v4l2-chip-ident.h> +#include <media/v4l2-clk.h> #include <media/v4l2-subdev.h> #include <media/v4l2-ctrls.h> @@ -76,7 +76,7 @@ struct mt9t031 { struct v4l2_ctrl *exposure; }; struct v4l2_rect rect; /* Sensor window */ - int model; /* V4L2_IDENT_MT9T031* codes from v4l2-chip-ident.h */ + struct v4l2_clk *clk; u16 xskip; u16 yskip; unsigned int total_h; @@ -391,36 +391,16 @@ static int mt9t031_try_fmt(struct v4l2_subdev *sd, return 0; } -static int mt9t031_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *id) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct mt9t031 *mt9t031 = to_mt9t031(client); - - if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) - return -EINVAL; - - if (id->match.addr != client->addr) - return -ENODEV; - - id->ident = mt9t031->model; - id->revision = 0; - - return 0; -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int mt9t031_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + if (reg->reg > 0xff) return -EINVAL; - if (reg->match.addr != client->addr) - return -ENODEV; - + reg->size = 1; reg->val = reg_read(client, reg->reg); if (reg->val > 0xffff) @@ -434,12 +414,9 @@ static int mt9t031_s_register(struct v4l2_subdev *sd, { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + if (reg->reg > 0xff) return -EINVAL; - if (reg->match.addr != client->addr) - return -ENODEV; - if (reg_write(client, reg->reg, reg->val) < 0) return -EIO; @@ -595,7 +572,7 @@ static int mt9t031_runtime_resume(struct device *dev) return 0; } -static struct dev_pm_ops mt9t031_dev_pm_ops = { +static const struct dev_pm_ops mt9t031_dev_pm_ops = { .runtime_suspend = mt9t031_runtime_suspend, .runtime_resume = mt9t031_runtime_resume, }; @@ -610,16 +587,17 @@ static int mt9t031_s_power(struct v4l2_subdev *sd, int on) struct i2c_client *client = v4l2_get_subdevdata(sd); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); struct video_device *vdev = soc_camera_i2c_to_vdev(client); + struct mt9t031 *mt9t031 = to_mt9t031(client); int ret; if (on) { - ret = soc_camera_power_on(&client->dev, ssdd); + ret = soc_camera_power_on(&client->dev, ssdd, mt9t031->clk); if (ret < 0) return ret; vdev->dev.type = &mt9t031_dev_type; } else { vdev->dev.type = NULL; - soc_camera_power_off(&client->dev, ssdd); + soc_camera_power_off(&client->dev, ssdd, mt9t031->clk); } return 0; @@ -650,7 +628,6 @@ static int mt9t031_video_probe(struct i2c_client *client) switch (data) { case 0x1621: - mt9t031->model = V4L2_IDENT_MT9T031; break; default: dev_err(&client->dev, @@ -685,7 +662,6 @@ static const struct v4l2_ctrl_ops mt9t031_ctrl_ops = { }; static struct v4l2_subdev_core_ops mt9t031_subdev_core_ops = { - .g_chip_ident = mt9t031_g_chip_ident, .s_power = mt9t031_s_power, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = mt9t031_g_register, @@ -812,9 +788,18 @@ static int mt9t031_probe(struct i2c_client *client, mt9t031->xskip = 1; mt9t031->yskip = 1; + mt9t031->clk = v4l2_clk_get(&client->dev, "mclk"); + if (IS_ERR(mt9t031->clk)) { + ret = PTR_ERR(mt9t031->clk); + goto eclkget; + } + ret = mt9t031_video_probe(client); - if (ret) + if (ret) { + v4l2_clk_put(mt9t031->clk); +eclkget: v4l2_ctrl_handler_free(&mt9t031->hdl); + } return ret; } @@ -823,6 +808,7 @@ static int mt9t031_remove(struct i2c_client *client) { struct mt9t031 *mt9t031 = to_mt9t031(client); + v4l2_clk_put(mt9t031->clk); v4l2_device_unregister_subdev(&mt9t031->subdev); v4l2_ctrl_handler_free(&mt9t031->hdl); diff --git a/drivers/media/i2c/soc_camera/mt9t112.c b/drivers/media/i2c/soc_camera/mt9t112.c index a7256b732804..46f431a13782 100644 --- a/drivers/media/i2c/soc_camera/mt9t112.c +++ b/drivers/media/i2c/soc_camera/mt9t112.c @@ -27,7 +27,7 @@ #include <media/mt9t112.h> #include <media/soc_camera.h> -#include <media/v4l2-chip-ident.h> +#include <media/v4l2-clk.h> #include <media/v4l2-common.h> /* you can check PLL/clock info */ @@ -90,8 +90,8 @@ struct mt9t112_priv { struct mt9t112_camera_info *info; struct i2c_client *client; struct v4l2_rect frame; + struct v4l2_clk *clk; const struct mt9t112_format *format; - int model; int num_formats; u32 flags; /* for flags */ @@ -738,17 +738,6 @@ static int mt9t112_init_camera(const struct i2c_client *client) /************************************************************************ v4l2_subdev_core_ops ************************************************************************/ -static int mt9t112_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *id) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct mt9t112_priv *priv = to_mt9t112(client); - - id->ident = priv->model; - id->revision = 0; - - return 0; -} #ifdef CONFIG_VIDEO_ADV_DEBUG static int mt9t112_g_register(struct v4l2_subdev *sd, @@ -781,12 +770,12 @@ static int mt9t112_s_power(struct v4l2_subdev *sd, int on) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + struct mt9t112_priv *priv = to_mt9t112(client); - return soc_camera_set_power(&client->dev, ssdd, on); + return soc_camera_set_power(&client->dev, ssdd, priv->clk, on); } static struct v4l2_subdev_core_ops mt9t112_subdev_core_ops = { - .g_chip_ident = mt9t112_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = mt9t112_g_register, .s_register = mt9t112_s_register, @@ -1061,12 +1050,10 @@ static int mt9t112_camera_probe(struct i2c_client *client) switch (chipid) { case 0x2680: devname = "mt9t111"; - priv->model = V4L2_IDENT_MT9T111; priv->num_formats = 1; break; case 0x2682: devname = "mt9t112"; - priv->model = V4L2_IDENT_MT9T112; priv->num_formats = ARRAY_SIZE(mt9t112_cfmts); break; default: @@ -1108,18 +1095,26 @@ static int mt9t112_probe(struct i2c_client *client, v4l2_i2c_subdev_init(&priv->subdev, client, &mt9t112_subdev_ops); + priv->clk = v4l2_clk_get(&client->dev, "mclk"); + if (IS_ERR(priv->clk)) + return PTR_ERR(priv->clk); + ret = mt9t112_camera_probe(client); - if (ret) - return ret; /* Cannot fail: using the default supported pixel code */ - mt9t112_set_params(priv, &rect, V4L2_MBUS_FMT_UYVY8_2X8); + if (!ret) + mt9t112_set_params(priv, &rect, V4L2_MBUS_FMT_UYVY8_2X8); + else + v4l2_clk_put(priv->clk); return ret; } static int mt9t112_remove(struct i2c_client *client) { + struct mt9t112_priv *priv = to_mt9t112(client); + + v4l2_clk_put(priv->clk); return 0; } diff --git a/drivers/media/i2c/soc_camera/mt9v022.c b/drivers/media/i2c/soc_camera/mt9v022.c index a295e598486f..f9f95f815b1a 100644 --- a/drivers/media/i2c/soc_camera/mt9v022.c +++ b/drivers/media/i2c/soc_camera/mt9v022.c @@ -19,7 +19,7 @@ #include <media/soc_camera.h> #include <media/soc_mediabus.h> #include <media/v4l2-subdev.h> -#include <media/v4l2-chip-ident.h> +#include <media/v4l2-clk.h> #include <media/v4l2-ctrls.h> /* @@ -133,6 +133,11 @@ static const struct mt9v02x_register mt9v024_register = { .pixclk_fv_lv = MT9V024_PIXCLK_FV_LV, }; +enum mt9v022_model { + MT9V022IX7ATM, + MT9V022IX7ATC, +}; + struct mt9v022 { struct v4l2_subdev subdev; struct v4l2_ctrl_handler hdl; @@ -149,11 +154,12 @@ struct mt9v022 { struct v4l2_ctrl *hblank; struct v4l2_ctrl *vblank; struct v4l2_rect rect; /* Sensor window */ + struct v4l2_clk *clk; const struct mt9v022_datafmt *fmt; const struct mt9v022_datafmt *fmts; const struct mt9v02x_register *reg; int num_fmts; - int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */ + enum mt9v022_model model; u16 chip_control; u16 chip_version; unsigned short y_skip_top; /* Lines to skip at the top */ @@ -406,12 +412,12 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd, switch (mf->code) { case V4L2_MBUS_FMT_Y8_1X8: case V4L2_MBUS_FMT_Y10_1X10: - if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATM) + if (mt9v022->model != MT9V022IX7ATM) return -EINVAL; break; case V4L2_MBUS_FMT_SBGGR8_1X8: case V4L2_MBUS_FMT_SBGGR10_1X10: - if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATC) + if (mt9v022->model != MT9V022IX7ATC) return -EINVAL; break; default: @@ -457,36 +463,15 @@ static int mt9v022_try_fmt(struct v4l2_subdev *sd, return 0; } -static int mt9v022_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *id) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct mt9v022 *mt9v022 = to_mt9v022(client); - - if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) - return -EINVAL; - - if (id->match.addr != client->addr) - return -ENODEV; - - id->ident = mt9v022->model; - id->revision = 0; - - return 0; -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int mt9v022_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + if (reg->reg > 0xff) return -EINVAL; - if (reg->match.addr != client->addr) - return -ENODEV; - reg->size = 2; reg->val = reg_read(client, reg->reg); @@ -501,12 +486,9 @@ static int mt9v022_s_register(struct v4l2_subdev *sd, { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) + if (reg->reg > 0xff) return -EINVAL; - if (reg->match.addr != client->addr) - return -ENODEV; - if (reg_write(client, reg->reg, reg->val) < 0) return -EIO; @@ -518,8 +500,9 @@ static int mt9v022_s_power(struct v4l2_subdev *sd, int on) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + struct mt9v022 *mt9v022 = to_mt9v022(client); - return soc_camera_set_power(&client->dev, ssdd, on); + return soc_camera_set_power(&client->dev, ssdd, mt9v022->clk, on); } static int mt9v022_g_volatile_ctrl(struct v4l2_ctrl *ctrl) @@ -706,11 +689,11 @@ static int mt9v022_video_probe(struct i2c_client *client) if (sensor_type && (!strcmp("colour", sensor_type) || !strcmp("color", sensor_type))) { ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11); - mt9v022->model = V4L2_IDENT_MT9V022IX7ATC; + mt9v022->model = MT9V022IX7ATC; mt9v022->fmts = mt9v022_colour_fmts; } else { ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 0x11); - mt9v022->model = V4L2_IDENT_MT9V022IX7ATM; + mt9v022->model = MT9V022IX7ATM; mt9v022->fmts = mt9v022_monochrome_fmts; } @@ -740,7 +723,7 @@ static int mt9v022_video_probe(struct i2c_client *client) mt9v022->fmt = &mt9v022->fmts[0]; dev_info(&client->dev, "Detected a MT9V022 chip ID %x, %s sensor\n", - data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ? + data, mt9v022->model == MT9V022IX7ATM ? "monochrome" : "colour"); ret = mt9v022_init(client); @@ -768,7 +751,6 @@ static const struct v4l2_ctrl_ops mt9v022_ctrl_ops = { }; static struct v4l2_subdev_core_ops mt9v022_subdev_core_ops = { - .g_chip_ident = mt9v022_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = mt9v022_g_register, .s_register = mt9v022_s_register, @@ -957,9 +939,18 @@ static int mt9v022_probe(struct i2c_client *client, mt9v022->rect.width = MT9V022_MAX_WIDTH; mt9v022->rect.height = MT9V022_MAX_HEIGHT; + mt9v022->clk = v4l2_clk_get(&client->dev, "mclk"); + if (IS_ERR(mt9v022->clk)) { + ret = PTR_ERR(mt9v022->clk); + goto eclkget; + } + ret = mt9v022_video_probe(client); - if (ret) + if (ret) { + v4l2_clk_put(mt9v022->clk); +eclkget: v4l2_ctrl_handler_free(&mt9v022->hdl); + } return ret; } @@ -969,6 +960,7 @@ static int mt9v022_remove(struct i2c_client *client) struct mt9v022 *mt9v022 = to_mt9v022(client); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + v4l2_clk_put(mt9v022->clk); v4l2_device_unregister_subdev(&mt9v022->subdev); if (ssdd->free_bus) ssdd->free_bus(ssdd); diff --git a/drivers/media/i2c/soc_camera/ov2640.c b/drivers/media/i2c/soc_camera/ov2640.c index e3168424f9ba..6c6b1c3b45e3 100644 --- a/drivers/media/i2c/soc_camera/ov2640.c +++ b/drivers/media/i2c/soc_camera/ov2640.c @@ -22,7 +22,7 @@ #include <linux/videodev2.h> #include <media/soc_camera.h> -#include <media/v4l2-chip-ident.h> +#include <media/v4l2-clk.h> #include <media/v4l2-subdev.h> #include <media/v4l2-ctrls.h> @@ -303,8 +303,8 @@ struct ov2640_priv { struct v4l2_subdev subdev; struct v4l2_ctrl_handler hdl; enum v4l2_mbus_pixelcode cfmt_code; + struct v4l2_clk *clk; const struct ov2640_win_size *win; - int model; }; /* @@ -723,18 +723,6 @@ static int ov2640_s_ctrl(struct v4l2_ctrl *ctrl) return -EINVAL; } -static int ov2640_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *id) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ov2640_priv *priv = to_ov2640(client); - - id->ident = priv->model; - id->revision = 0; - - return 0; -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int ov2640_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) @@ -772,8 +760,9 @@ static int ov2640_s_power(struct v4l2_subdev *sd, int on) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + struct ov2640_priv *priv = to_ov2640(client); - return soc_camera_set_power(&client->dev, ssdd, on); + return soc_camera_set_power(&client->dev, ssdd, priv->clk, on); } /* Select the nearest higher resolution for capture */ @@ -1009,7 +998,6 @@ static int ov2640_video_probe(struct i2c_client *client) switch (VERSION(pid, ver)) { case PID_OV2640: devname = "ov2640"; - priv->model = V4L2_IDENT_OV2640; break; default: dev_err(&client->dev, @@ -1034,7 +1022,6 @@ static const struct v4l2_ctrl_ops ov2640_ctrl_ops = { }; static struct v4l2_subdev_core_ops ov2640_subdev_core_ops = { - .g_chip_ident = ov2640_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = ov2640_g_register, .s_register = ov2640_s_register, @@ -1113,11 +1100,20 @@ static int ov2640_probe(struct i2c_client *client, if (priv->hdl.error) return priv->hdl.error; + priv->clk = v4l2_clk_get(&client->dev, "mclk"); + if (IS_ERR(priv->clk)) { + ret = PTR_ERR(priv->clk); + goto eclkget; + } + ret = ov2640_video_probe(client); - if (ret) + if (ret) { + v4l2_clk_put(priv->clk); +eclkget: v4l2_ctrl_handler_free(&priv->hdl); - else + } else { dev_info(&adapter->dev, "OV2640 Probed\n"); + } return ret; } @@ -1126,6 +1122,7 @@ static int ov2640_remove(struct i2c_client *client) { struct ov2640_priv *priv = to_ov2640(client); + v4l2_clk_put(priv->clk); v4l2_device_unregister_subdev(&priv->subdev); v4l2_ctrl_handler_free(&priv->hdl); return 0; diff --git a/drivers/media/i2c/soc_camera/ov5642.c b/drivers/media/i2c/soc_camera/ov5642.c index 9aa56de69eed..0a5c5d4fedd6 100644 --- a/drivers/media/i2c/soc_camera/ov5642.c +++ b/drivers/media/i2c/soc_camera/ov5642.c @@ -24,7 +24,7 @@ #include <linux/v4l2-mediabus.h> #include <media/soc_camera.h> -#include <media/v4l2-chip-ident.h> +#include <media/v4l2-clk.h> #include <media/v4l2-subdev.h> /* OV5642 registers */ @@ -610,6 +610,7 @@ struct ov5642 { struct v4l2_subdev subdev; const struct ov5642_datafmt *fmt; struct v4l2_rect crop_rect; + struct v4l2_clk *clk; /* blanking information */ int total_width; @@ -848,23 +849,6 @@ static int ov5642_enum_fmt(struct v4l2_subdev *sd, unsigned int index, return 0; } -static int ov5642_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *id) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) - return -EINVAL; - - if (id->match.addr != client->addr) - return -ENODEV; - - id->ident = V4L2_IDENT_OV5642; - id->revision = 0; - - return 0; -} - static int ov5642_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) { struct i2c_client *client = v4l2_get_subdevdata(sd); @@ -935,12 +919,13 @@ static int ov5642_s_power(struct v4l2_subdev *sd, int on) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + struct ov5642 *priv = to_ov5642(client); int ret; if (!on) - return soc_camera_power_off(&client->dev, ssdd); + return soc_camera_power_off(&client->dev, ssdd, priv->clk); - ret = soc_camera_power_on(&client->dev, ssdd); + ret = soc_camera_power_on(&client->dev, ssdd, priv->clk); if (ret < 0) return ret; @@ -966,7 +951,6 @@ static struct v4l2_subdev_video_ops ov5642_subdev_video_ops = { static struct v4l2_subdev_core_ops ov5642_subdev_core_ops = { .s_power = ov5642_s_power, - .g_chip_ident = ov5642_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = ov5642_get_register, .s_register = ov5642_set_register, @@ -1021,6 +1005,7 @@ static int ov5642_probe(struct i2c_client *client, { struct ov5642 *priv; struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + int ret; if (!ssdd) { dev_err(&client->dev, "OV5642: missing platform data!\n"); @@ -1042,13 +1027,23 @@ static int ov5642_probe(struct i2c_client *client, priv->total_width = OV5642_DEFAULT_WIDTH + BLANKING_EXTRA_WIDTH; priv->total_height = BLANKING_MIN_HEIGHT; - return ov5642_video_probe(client); + priv->clk = v4l2_clk_get(&client->dev, "mclk"); + if (IS_ERR(priv->clk)) + return PTR_ERR(priv->clk); + + ret = ov5642_video_probe(client); + if (ret < 0) + v4l2_clk_put(priv->clk); + + return ret; } static int ov5642_remove(struct i2c_client *client) { struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + struct ov5642 *priv = to_ov5642(client); + v4l2_clk_put(priv->clk); if (ssdd->free_bus) ssdd->free_bus(ssdd); diff --git a/drivers/media/i2c/soc_camera/ov6650.c b/drivers/media/i2c/soc_camera/ov6650.c index 991202d4bbae..ab01598ec83f 100644 --- a/drivers/media/i2c/soc_camera/ov6650.c +++ b/drivers/media/i2c/soc_camera/ov6650.c @@ -32,7 +32,7 @@ #include <linux/module.h> #include <media/soc_camera.h> -#include <media/v4l2-chip-ident.h> +#include <media/v4l2-clk.h> #include <media/v4l2-ctrls.h> /* Register definitions */ @@ -196,6 +196,7 @@ struct ov6650 { struct v4l2_ctrl *blue; struct v4l2_ctrl *red; }; + struct v4l2_clk *clk; bool half_scale; /* scale down output by 2 */ struct v4l2_rect rect; /* sensor cropping window */ unsigned long pclk_limit; /* from host */ @@ -390,16 +391,6 @@ static int ov6550_s_ctrl(struct v4l2_ctrl *ctrl) return -EINVAL; } -/* Get chip identification */ -static int ov6650_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *id) -{ - id->ident = V4L2_IDENT_OV6650; - id->revision = 0; - - return 0; -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int ov6650_get_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) @@ -436,8 +427,9 @@ static int ov6650_s_power(struct v4l2_subdev *sd, int on) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + struct ov6650 *priv = to_ov6650(client); - return soc_camera_set_power(&client->dev, ssdd, on); + return soc_camera_set_power(&client->dev, ssdd, priv->clk, on); } static int ov6650_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) @@ -879,7 +871,6 @@ static const struct v4l2_ctrl_ops ov6550_ctrl_ops = { }; static struct v4l2_subdev_core_ops ov6650_core_ops = { - .g_chip_ident = ov6650_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = ov6650_get_register, .s_register = ov6650_set_register, @@ -1025,9 +1016,18 @@ static int ov6650_probe(struct i2c_client *client, priv->code = V4L2_MBUS_FMT_YUYV8_2X8; priv->colorspace = V4L2_COLORSPACE_JPEG; + priv->clk = v4l2_clk_get(&client->dev, "mclk"); + if (IS_ERR(priv->clk)) { + ret = PTR_ERR(priv->clk); + goto eclkget; + } + ret = ov6650_video_probe(client); - if (ret) + if (ret) { + v4l2_clk_put(priv->clk); +eclkget: v4l2_ctrl_handler_free(&priv->hdl); + } return ret; } @@ -1036,6 +1036,7 @@ static int ov6650_remove(struct i2c_client *client) { struct ov6650 *priv = to_ov6650(client); + v4l2_clk_put(priv->clk); v4l2_device_unregister_subdev(&priv->subdev); v4l2_ctrl_handler_free(&priv->hdl); return 0; diff --git a/drivers/media/i2c/soc_camera/ov772x.c b/drivers/media/i2c/soc_camera/ov772x.c index 713d62e349f6..7f2b3c8926af 100644 --- a/drivers/media/i2c/soc_camera/ov772x.c +++ b/drivers/media/i2c/soc_camera/ov772x.c @@ -26,8 +26,8 @@ #include <media/ov772x.h> #include <media/soc_camera.h> +#include <media/v4l2-clk.h> #include <media/v4l2-ctrls.h> -#include <media/v4l2-chip-ident.h> #include <media/v4l2-subdev.h> /* @@ -396,10 +396,10 @@ struct ov772x_win_size { struct ov772x_priv { struct v4l2_subdev subdev; struct v4l2_ctrl_handler hdl; + struct v4l2_clk *clk; struct ov772x_camera_info *info; const struct ov772x_color_format *cfmt; const struct ov772x_win_size *win; - int model; unsigned short flag_vflip:1; unsigned short flag_hflip:1; /* band_filter = COM8[5] ? 256 - BDBASE : 0 */ @@ -620,17 +620,6 @@ static int ov772x_s_ctrl(struct v4l2_ctrl *ctrl) return -EINVAL; } -static int ov772x_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *id) -{ - struct ov772x_priv *priv = to_ov772x(sd); - - id->ident = priv->model; - id->revision = 0; - - return 0; -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int ov772x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) @@ -668,8 +657,9 @@ static int ov772x_s_power(struct v4l2_subdev *sd, int on) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + struct ov772x_priv *priv = to_ov772x(sd); - return soc_camera_set_power(&client->dev, ssdd, on); + return soc_camera_set_power(&client->dev, ssdd, priv->clk, on); } static const struct ov772x_win_size *ov772x_select_win(u32 width, u32 height) @@ -965,11 +955,9 @@ static int ov772x_video_probe(struct ov772x_priv *priv) switch (VERSION(pid, ver)) { case OV7720: devname = "ov7720"; - priv->model = V4L2_IDENT_OV7720; break; case OV7725: devname = "ov7725"; - priv->model = V4L2_IDENT_OV7725; break; default: dev_err(&client->dev, @@ -997,7 +985,6 @@ static const struct v4l2_ctrl_ops ov772x_ctrl_ops = { }; static struct v4l2_subdev_core_ops ov772x_subdev_core_ops = { - .g_chip_ident = ov772x_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = ov772x_g_register, .s_register = ov772x_s_register, @@ -1088,13 +1075,22 @@ static int ov772x_probe(struct i2c_client *client, if (priv->hdl.error) return priv->hdl.error; + priv->clk = v4l2_clk_get(&client->dev, "mclk"); + if (IS_ERR(priv->clk)) { + ret = PTR_ERR(priv->clk); + goto eclkget; + } + ret = ov772x_video_probe(priv); if (ret < 0) { + v4l2_clk_put(priv->clk); +eclkget: v4l2_ctrl_handler_free(&priv->hdl); } else { priv->cfmt = &ov772x_cfmts[0]; priv->win = &ov772x_win_sizes[0]; } + return ret; } @@ -1102,6 +1098,7 @@ static int ov772x_remove(struct i2c_client *client) { struct ov772x_priv *priv = to_ov772x(i2c_get_clientdata(client)); + v4l2_clk_put(priv->clk); v4l2_device_unregister_subdev(&priv->subdev); v4l2_ctrl_handler_free(&priv->hdl); return 0; diff --git a/drivers/media/i2c/soc_camera/ov9640.c b/drivers/media/i2c/soc_camera/ov9640.c index 20ca62d371c1..e968c3fdbd9e 100644 --- a/drivers/media/i2c/soc_camera/ov9640.c +++ b/drivers/media/i2c/soc_camera/ov9640.c @@ -28,7 +28,7 @@ #include <linux/videodev2.h> #include <media/soc_camera.h> -#include <media/v4l2-chip-ident.h> +#include <media/v4l2-clk.h> #include <media/v4l2-common.h> #include <media/v4l2-ctrls.h> @@ -61,7 +61,7 @@ static const struct ov9640_reg ov9640_regs_dflt[] = { /* Configurations * NOTE: for YUV, alter the following registers: - * COM12 |= OV9640_COM12_YUV_AVG + * COM12 |= OV9640_COM12_YUV_AVG * * for RGB, alter the following registers: * COM7 |= OV9640_COM7_RGB @@ -287,18 +287,6 @@ static int ov9640_s_ctrl(struct v4l2_ctrl *ctrl) return -EINVAL; } -/* Get chip identification */ -static int ov9640_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *id) -{ - struct ov9640_priv *priv = to_ov9640_sensor(sd); - - id->ident = priv->model; - id->revision = priv->revision; - - return 0; -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int ov9640_get_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) @@ -337,8 +325,9 @@ static int ov9640_s_power(struct v4l2_subdev *sd, int on) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + struct ov9640_priv *priv = to_ov9640_sensor(sd); - return soc_camera_set_power(&client->dev, ssdd, on); + return soc_camera_set_power(&client->dev, ssdd, priv->clk, on); } /* select nearest higher resolution for capture */ @@ -615,12 +604,10 @@ static int ov9640_video_probe(struct i2c_client *client) switch (VERSION(pid, ver)) { case OV9640_V2: devname = "ov9640"; - priv->model = V4L2_IDENT_OV9640; priv->revision = 2; break; case OV9640_V3: devname = "ov9640"; - priv->model = V4L2_IDENT_OV9640; priv->revision = 3; break; default: @@ -644,7 +631,6 @@ static const struct v4l2_ctrl_ops ov9640_ctrl_ops = { }; static struct v4l2_subdev_core_ops ov9640_core_ops = { - .g_chip_ident = ov9640_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = ov9640_get_register, .s_register = ov9640_set_register, @@ -716,10 +702,18 @@ static int ov9640_probe(struct i2c_client *client, if (priv->hdl.error) return priv->hdl.error; - ret = ov9640_video_probe(client); + priv->clk = v4l2_clk_get(&client->dev, "mclk"); + if (IS_ERR(priv->clk)) { + ret = PTR_ERR(priv->clk); + goto eclkget; + } - if (ret) + ret = ov9640_video_probe(client); + if (ret) { + v4l2_clk_put(priv->clk); +eclkget: v4l2_ctrl_handler_free(&priv->hdl); + } return ret; } @@ -729,6 +723,7 @@ static int ov9640_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); struct ov9640_priv *priv = to_ov9640_sensor(sd); + v4l2_clk_put(priv->clk); v4l2_device_unregister_subdev(&priv->subdev); v4l2_ctrl_handler_free(&priv->hdl); return 0; diff --git a/drivers/media/i2c/soc_camera/ov9640.h b/drivers/media/i2c/soc_camera/ov9640.h index 6b33a972c83c..65d13ff17536 100644 --- a/drivers/media/i2c/soc_camera/ov9640.h +++ b/drivers/media/i2c/soc_camera/ov9640.h @@ -199,6 +199,7 @@ struct ov9640_reg { struct ov9640_priv { struct v4l2_subdev subdev; struct v4l2_ctrl_handler hdl; + struct v4l2_clk *clk; int model; int revision; diff --git a/drivers/media/i2c/soc_camera/ov9740.c b/drivers/media/i2c/soc_camera/ov9740.c index 012bd6271124..ea76863dfdb4 100644 --- a/drivers/media/i2c/soc_camera/ov9740.c +++ b/drivers/media/i2c/soc_camera/ov9740.c @@ -17,7 +17,7 @@ #include <linux/v4l2-mediabus.h> #include <media/soc_camera.h> -#include <media/v4l2-chip-ident.h> +#include <media/v4l2-clk.h> #include <media/v4l2-ctrls.h> #define to_ov9740(sd) container_of(sd, struct ov9740_priv, subdev) @@ -196,8 +196,8 @@ struct ov9740_reg { struct ov9740_priv { struct v4l2_subdev subdev; struct v4l2_ctrl_handler hdl; + struct v4l2_clk *clk; - int ident; u16 model; u8 revision; u8 manid; @@ -772,18 +772,6 @@ static int ov9740_s_ctrl(struct v4l2_ctrl *ctrl) return 0; } -/* Get chip identification */ -static int ov9740_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *id) -{ - struct ov9740_priv *priv = to_ov9740(sd); - - id->ident = priv->ident; - id->revision = priv->revision; - - return 0; -} - static int ov9740_s_power(struct v4l2_subdev *sd, int on) { struct i2c_client *client = v4l2_get_subdevdata(sd); @@ -792,7 +780,7 @@ static int ov9740_s_power(struct v4l2_subdev *sd, int on) int ret; if (on) { - ret = soc_camera_power_on(&client->dev, ssdd); + ret = soc_camera_power_on(&client->dev, ssdd, priv->clk); if (ret < 0) return ret; @@ -806,7 +794,7 @@ static int ov9740_s_power(struct v4l2_subdev *sd, int on) priv->current_enable = true; } - soc_camera_power_off(&client->dev, ssdd); + soc_camera_power_off(&client->dev, ssdd, priv->clk); } return 0; @@ -887,8 +875,6 @@ static int ov9740_video_probe(struct i2c_client *client) goto done; } - priv->ident = V4L2_IDENT_OV9740; - dev_info(&client->dev, "ov9740 Model ID 0x%04x, Revision 0x%02x, " "Manufacturer 0x%02x, SMIA Version 0x%02x\n", priv->model, priv->revision, priv->manid, priv->smiaver); @@ -927,7 +913,6 @@ static struct v4l2_subdev_video_ops ov9740_video_ops = { }; static struct v4l2_subdev_core_ops ov9740_core_ops = { - .g_chip_ident = ov9740_g_chip_ident, .s_power = ov9740_s_power, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = ov9740_get_register, @@ -975,9 +960,18 @@ static int ov9740_probe(struct i2c_client *client, if (priv->hdl.error) return priv->hdl.error; + priv->clk = v4l2_clk_get(&client->dev, "mclk"); + if (IS_ERR(priv->clk)) { + ret = PTR_ERR(priv->clk); + goto eclkget; + } + ret = ov9740_video_probe(client); - if (ret < 0) + if (ret < 0) { + v4l2_clk_put(priv->clk); +eclkget: v4l2_ctrl_handler_free(&priv->hdl); + } return ret; } @@ -986,6 +980,7 @@ static int ov9740_remove(struct i2c_client *client) { struct ov9740_priv *priv = i2c_get_clientdata(client); + v4l2_clk_put(priv->clk); v4l2_device_unregister_subdev(&priv->subdev); v4l2_ctrl_handler_free(&priv->hdl); return 0; diff --git a/drivers/media/i2c/soc_camera/rj54n1cb0c.c b/drivers/media/i2c/soc_camera/rj54n1cb0c.c index 1f9ec3b06b4e..7e6d97847874 100644 --- a/drivers/media/i2c/soc_camera/rj54n1cb0c.c +++ b/drivers/media/i2c/soc_camera/rj54n1cb0c.c @@ -17,8 +17,8 @@ #include <media/rj54n1cb0c.h> #include <media/soc_camera.h> +#include <media/v4l2-clk.h> #include <media/v4l2-subdev.h> -#include <media/v4l2-chip-ident.h> #include <media/v4l2-ctrls.h> #define RJ54N1_DEV_CODE 0x0400 @@ -151,6 +151,7 @@ struct rj54n1_clock_div { struct rj54n1 { struct v4l2_subdev subdev; struct v4l2_ctrl_handler hdl; + struct v4l2_clk *clk; struct rj54n1_clock_div clk_div; const struct rj54n1_datafmt *fmt; struct v4l2_rect rect; /* Sensor window */ @@ -1120,37 +1121,16 @@ static int rj54n1_s_fmt(struct v4l2_subdev *sd, return 0; } -static int rj54n1_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *id) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) - return -EINVAL; - - if (id->match.addr != client->addr) - return -ENODEV; - - id->ident = V4L2_IDENT_RJ54N1CB0C; - id->revision = 0; - - return 0; -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int rj54n1_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || - reg->reg < 0x400 || reg->reg > 0x1fff) + if (reg->reg < 0x400 || reg->reg > 0x1fff) /* Registers > 0x0800 are only available from Sharp support */ return -EINVAL; - if (reg->match.addr != client->addr) - return -ENODEV; - reg->size = 1; reg->val = reg_read(client, reg->reg); @@ -1165,14 +1145,10 @@ static int rj54n1_s_register(struct v4l2_subdev *sd, { struct i2c_client *client = v4l2_get_subdevdata(sd); - if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || - reg->reg < 0x400 || reg->reg > 0x1fff) + if (reg->reg < 0x400 || reg->reg > 0x1fff) /* Registers >= 0x0800 are only available from Sharp support */ return -EINVAL; - if (reg->match.addr != client->addr) - return -ENODEV; - if (reg_write(client, reg->reg, reg->val) < 0) return -EIO; @@ -1184,8 +1160,9 @@ static int rj54n1_s_power(struct v4l2_subdev *sd, int on) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + struct rj54n1 *rj54n1 = to_rj54n1(client); - return soc_camera_set_power(&client->dev, ssdd, on); + return soc_camera_set_power(&client->dev, ssdd, rj54n1->clk, on); } static int rj54n1_s_ctrl(struct v4l2_ctrl *ctrl) @@ -1233,7 +1210,6 @@ static const struct v4l2_ctrl_ops rj54n1_ctrl_ops = { }; static struct v4l2_subdev_core_ops rj54n1_subdev_core_ops = { - .g_chip_ident = rj54n1_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = rj54n1_g_register, .s_register = rj54n1_s_register, @@ -1382,9 +1358,18 @@ static int rj54n1_probe(struct i2c_client *client, rj54n1->tgclk_mhz = (rj54n1_priv->mclk_freq / PLL_L * PLL_N) / (clk_div.ratio_tg + 1) / (clk_div.ratio_t + 1); + rj54n1->clk = v4l2_clk_get(&client->dev, "mclk"); + if (IS_ERR(rj54n1->clk)) { + ret = PTR_ERR(rj54n1->clk); + goto eclkget; + } + ret = rj54n1_video_probe(client, rj54n1_priv); - if (ret < 0) + if (ret < 0) { + v4l2_clk_put(rj54n1->clk); +eclkget: v4l2_ctrl_handler_free(&rj54n1->hdl); + } return ret; } @@ -1394,6 +1379,7 @@ static int rj54n1_remove(struct i2c_client *client) struct rj54n1 *rj54n1 = to_rj54n1(client); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + v4l2_clk_put(rj54n1->clk); v4l2_device_unregister_subdev(&rj54n1->subdev); if (ssdd->free_bus) ssdd->free_bus(ssdd); diff --git a/drivers/media/i2c/soc_camera/tw9910.c b/drivers/media/i2c/soc_camera/tw9910.c index bad90b16a6dd..ab54628d9411 100644 --- a/drivers/media/i2c/soc_camera/tw9910.c +++ b/drivers/media/i2c/soc_camera/tw9910.c @@ -27,7 +27,7 @@ #include <media/soc_camera.h> #include <media/tw9910.h> -#include <media/v4l2-chip-ident.h> +#include <media/v4l2-clk.h> #include <media/v4l2-subdev.h> #define GET_ID(val) ((val & 0xF8) >> 3) @@ -228,6 +228,7 @@ struct tw9910_scale_ctrl { struct tw9910_priv { struct v4l2_subdev subdev; + struct v4l2_clk *clk; struct tw9910_video_info *info; const struct tw9910_scale_ctrl *scale; v4l2_std_id norm; @@ -518,18 +519,6 @@ static int tw9910_s_std(struct v4l2_subdev *sd, v4l2_std_id norm) return 0; } -static int tw9910_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *id) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct tw9910_priv *priv = to_tw9910(client); - - id->ident = V4L2_IDENT_TW9910; - id->revision = priv->revision; - - return 0; -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int tw9910_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) @@ -540,6 +529,7 @@ static int tw9910_g_register(struct v4l2_subdev *sd, if (reg->reg > 0xff) return -EINVAL; + reg->size = 1; ret = i2c_smbus_read_byte_data(client, reg->reg); if (ret < 0) return ret; @@ -570,8 +560,9 @@ static int tw9910_s_power(struct v4l2_subdev *sd, int on) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + struct tw9910_priv *priv = to_tw9910(client); - return soc_camera_set_power(&client->dev, ssdd, on); + return soc_camera_set_power(&client->dev, ssdd, priv->clk, on); } static int tw9910_set_frame(struct v4l2_subdev *sd, u32 *width, u32 *height) @@ -823,7 +814,6 @@ done: } static struct v4l2_subdev_core_ops tw9910_subdev_core_ops = { - .g_chip_ident = tw9910_g_chip_ident, .s_std = tw9910_s_std, .g_std = tw9910_g_std, #ifdef CONFIG_VIDEO_ADV_DEBUG @@ -912,6 +902,7 @@ static int tw9910_probe(struct i2c_client *client, struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + int ret; if (!ssdd || !ssdd->drv_priv) { dev_err(&client->dev, "TW9910: missing platform data!\n"); @@ -935,11 +926,21 @@ static int tw9910_probe(struct i2c_client *client, v4l2_i2c_subdev_init(&priv->subdev, client, &tw9910_subdev_ops); - return tw9910_video_probe(client); + priv->clk = v4l2_clk_get(&client->dev, "mclk"); + if (IS_ERR(priv->clk)) + return PTR_ERR(priv->clk); + + ret = tw9910_video_probe(client); + if (ret < 0) + v4l2_clk_put(priv->clk); + + return ret; } static int tw9910_remove(struct i2c_client *client) { + struct tw9910_priv *priv = to_tw9910(client); + v4l2_clk_put(priv->clk); return 0; } diff --git a/drivers/media/i2c/sony-btf-mpx.c b/drivers/media/i2c/sony-btf-mpx.c index 38cbea98764c..32d82320b485 100644 --- a/drivers/media/i2c/sony-btf-mpx.c +++ b/drivers/media/i2c/sony-btf-mpx.c @@ -30,7 +30,7 @@ MODULE_LICENSE("GPL v2"); static int debug; module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "debug level 0=off(default) 1=on\n"); +MODULE_PARM_DESC(debug, "debug level 0=off(default) 1=on"); /* #define MPX_DEBUG */ @@ -355,7 +355,7 @@ static int sony_btf_mpx_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - t = kzalloc(sizeof(struct sony_btf_mpx), GFP_KERNEL); + t = devm_kzalloc(&client->dev, sizeof(*t), GFP_KERNEL); if (t == NULL) return -ENOMEM; @@ -374,7 +374,6 @@ static int sony_btf_mpx_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); v4l2_device_unregister_subdev(sd); - kfree(to_state(sd)); return 0; } diff --git a/drivers/media/i2c/sr030pc30.c b/drivers/media/i2c/sr030pc30.c index e9d95bda2ab1..ae9432637fcb 100644 --- a/drivers/media/i2c/sr030pc30.c +++ b/drivers/media/i2c/sr030pc30.c @@ -23,6 +23,7 @@ #include <media/v4l2-device.h> #include <media/v4l2-subdev.h> #include <media/v4l2-mediabus.h> +#include <media/v4l2-ctrls.h> #include <media/sr030pc30.h> static int debug; @@ -142,17 +143,24 @@ module_param(debug, int, 0644); struct sr030pc30_info { struct v4l2_subdev sd; + struct v4l2_ctrl_handler hdl; const struct sr030pc30_platform_data *pdata; const struct sr030pc30_format *curr_fmt; const struct sr030pc30_frmsize *curr_win; - unsigned int auto_wb:1; - unsigned int auto_exp:1; unsigned int hflip:1; unsigned int vflip:1; unsigned int sleep:1; - unsigned int exposure; - u8 blue_balance; - u8 red_balance; + struct { + /* auto whitebalance control cluster */ + struct v4l2_ctrl *awb; + struct v4l2_ctrl *red; + struct v4l2_ctrl *blue; + }; + struct { + /* auto exposure control cluster */ + struct v4l2_ctrl *autoexp; + struct v4l2_ctrl *exp; + }; u8 i2c_reg_page; }; @@ -173,52 +181,6 @@ struct i2c_regval { u16 val; }; -static const struct v4l2_queryctrl sr030pc30_ctrl[] = { - { - .id = V4L2_CID_AUTO_WHITE_BALANCE, - .type = V4L2_CTRL_TYPE_BOOLEAN, - .name = "Auto White Balance", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 1, - }, { - .id = V4L2_CID_RED_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Red Balance", - .minimum = 0, - .maximum = 127, - .step = 1, - .default_value = 64, - .flags = 0, - }, { - .id = V4L2_CID_BLUE_BALANCE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Blue Balance", - .minimum = 0, - .maximum = 127, - .step = 1, - .default_value = 64, - }, { - .id = V4L2_CID_EXPOSURE_AUTO, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Auto Exposure", - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 1, - }, { - .id = V4L2_CID_EXPOSURE, - .type = V4L2_CTRL_TYPE_INTEGER, - .name = "Exposure", - .minimum = EXPOS_MIN_MS, - .maximum = EXPOS_MAX_MS, - .step = 1, - .default_value = 1, - }, { - } -}; - /* supported resolutions */ static const struct sr030pc30_frmsize sr030pc30_sizes[] = { { @@ -394,48 +356,6 @@ static int sr030pc30_pwr_ctrl(struct v4l2_subdev *sd, return ret; } -static inline int sr030pc30_enable_autoexposure(struct v4l2_subdev *sd, int on) -{ - struct sr030pc30_info *info = to_sr030pc30(sd); - /* auto anti-flicker is also enabled here */ - int ret = cam_i2c_write(sd, AE_CTL1_REG, on ? 0xDC : 0x0C); - if (!ret) - info->auto_exp = on; - return ret; -} - -static int sr030pc30_set_exposure(struct v4l2_subdev *sd, int value) -{ - struct sr030pc30_info *info = to_sr030pc30(sd); - - unsigned long expos = value * info->pdata->clk_rate / (8 * 1000); - - int ret = cam_i2c_write(sd, EXP_TIMEH_REG, expos >> 16 & 0xFF); - if (!ret) - ret = cam_i2c_write(sd, EXP_TIMEM_REG, expos >> 8 & 0xFF); - if (!ret) - ret = cam_i2c_write(sd, EXP_TIMEL_REG, expos & 0xFF); - if (!ret) { /* Turn off AE */ - info->exposure = value; - ret = sr030pc30_enable_autoexposure(sd, 0); - } - return ret; -} - -/* Automatic white balance control */ -static int sr030pc30_enable_autowhitebalance(struct v4l2_subdev *sd, int on) -{ - struct sr030pc30_info *info = to_sr030pc30(sd); - - int ret = cam_i2c_write(sd, AWB_CTL2_REG, on ? 0x2E : 0x2F); - if (!ret) - ret = cam_i2c_write(sd, AWB_CTL1_REG, on ? 0xFB : 0x7B); - if (!ret) - info->auto_wb = on; - - return ret; -} - static int sr030pc30_set_flip(struct v4l2_subdev *sd) { struct sr030pc30_info *info = to_sr030pc30(sd); @@ -498,107 +418,56 @@ static int sr030pc30_try_frame_size(struct v4l2_mbus_framefmt *mf) return -EINVAL; } -static int sr030pc30_queryctrl(struct v4l2_subdev *sd, - struct v4l2_queryctrl *qc) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(sr030pc30_ctrl); i++) - if (qc->id == sr030pc30_ctrl[i].id) { - *qc = sr030pc30_ctrl[i]; - v4l2_dbg(1, debug, sd, "%s id: %d\n", - __func__, qc->id); - return 0; - } - - return -EINVAL; -} - -static inline int sr030pc30_set_bluebalance(struct v4l2_subdev *sd, int value) +static int sr030pc30_s_ctrl(struct v4l2_ctrl *ctrl) { - int ret = cam_i2c_write(sd, MWB_BGAIN_REG, value); - if (!ret) - to_sr030pc30(sd)->blue_balance = value; - return ret; -} - -static inline int sr030pc30_set_redbalance(struct v4l2_subdev *sd, int value) -{ - int ret = cam_i2c_write(sd, MWB_RGAIN_REG, value); - if (!ret) - to_sr030pc30(sd)->red_balance = value; - return ret; -} - -static int sr030pc30_s_ctrl(struct v4l2_subdev *sd, - struct v4l2_control *ctrl) -{ - int i, ret = 0; - - for (i = 0; i < ARRAY_SIZE(sr030pc30_ctrl); i++) - if (ctrl->id == sr030pc30_ctrl[i].id) - break; - - if (i == ARRAY_SIZE(sr030pc30_ctrl)) - return -EINVAL; - - if (ctrl->value < sr030pc30_ctrl[i].minimum || - ctrl->value > sr030pc30_ctrl[i].maximum) - return -ERANGE; + struct sr030pc30_info *info = + container_of(ctrl->handler, struct sr030pc30_info, hdl); + struct v4l2_subdev *sd = &info->sd; + int ret = 0; v4l2_dbg(1, debug, sd, "%s: ctrl_id: %d, value: %d\n", - __func__, ctrl->id, ctrl->value); + __func__, ctrl->id, ctrl->val); switch (ctrl->id) { case V4L2_CID_AUTO_WHITE_BALANCE: - sr030pc30_enable_autowhitebalance(sd, ctrl->value); - break; - case V4L2_CID_BLUE_BALANCE: - ret = sr030pc30_set_bluebalance(sd, ctrl->value); - break; - case V4L2_CID_RED_BALANCE: - ret = sr030pc30_set_redbalance(sd, ctrl->value); - break; - case V4L2_CID_EXPOSURE_AUTO: - sr030pc30_enable_autoexposure(sd, - ctrl->value == V4L2_EXPOSURE_AUTO); - break; - case V4L2_CID_EXPOSURE: - ret = sr030pc30_set_exposure(sd, ctrl->value); - break; - default: - return -EINVAL; - } - - return ret; -} - -static int sr030pc30_g_ctrl(struct v4l2_subdev *sd, - struct v4l2_control *ctrl) -{ - struct sr030pc30_info *info = to_sr030pc30(sd); - - v4l2_dbg(1, debug, sd, "%s: id: %d\n", __func__, ctrl->id); + if (ctrl->is_new) { + ret = cam_i2c_write(sd, AWB_CTL2_REG, + ctrl->val ? 0x2E : 0x2F); + if (!ret) + ret = cam_i2c_write(sd, AWB_CTL1_REG, + ctrl->val ? 0xFB : 0x7B); + } + if (!ret && info->blue->is_new) + ret = cam_i2c_write(sd, MWB_BGAIN_REG, info->blue->val); + if (!ret && info->red->is_new) + ret = cam_i2c_write(sd, MWB_RGAIN_REG, info->red->val); + return ret; - switch (ctrl->id) { - case V4L2_CID_AUTO_WHITE_BALANCE: - ctrl->value = info->auto_wb; - break; - case V4L2_CID_BLUE_BALANCE: - ctrl->value = info->blue_balance; - break; - case V4L2_CID_RED_BALANCE: - ctrl->value = info->red_balance; - break; case V4L2_CID_EXPOSURE_AUTO: - ctrl->value = info->auto_exp; - break; - case V4L2_CID_EXPOSURE: - ctrl->value = info->exposure; - break; + /* auto anti-flicker is also enabled here */ + if (ctrl->is_new) + ret = cam_i2c_write(sd, AE_CTL1_REG, + ctrl->val == V4L2_EXPOSURE_AUTO ? 0xDC : 0x0C); + if (info->exp->is_new) { + unsigned long expos = info->exp->val; + + expos = expos * info->pdata->clk_rate / (8 * 1000); + + if (!ret) + ret = cam_i2c_write(sd, EXP_TIMEH_REG, + expos >> 16 & 0xFF); + if (!ret) + ret = cam_i2c_write(sd, EXP_TIMEM_REG, + expos >> 8 & 0xFF); + if (!ret) + ret = cam_i2c_write(sd, EXP_TIMEL_REG, + expos & 0xFF); + } + return ret; default: return -EINVAL; } + return 0; } @@ -752,11 +621,19 @@ static int sr030pc30_s_power(struct v4l2_subdev *sd, int on) return ret; } +static const struct v4l2_ctrl_ops sr030pc30_ctrl_ops = { + .s_ctrl = sr030pc30_s_ctrl, +}; + static const struct v4l2_subdev_core_ops sr030pc30_core_ops = { .s_power = sr030pc30_s_power, - .queryctrl = sr030pc30_queryctrl, - .s_ctrl = sr030pc30_s_ctrl, - .g_ctrl = sr030pc30_g_ctrl, + .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, + .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, + .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, + .g_ctrl = v4l2_subdev_g_ctrl, + .s_ctrl = v4l2_subdev_s_ctrl, + .queryctrl = v4l2_subdev_queryctrl, + .querymenu = v4l2_subdev_querymenu, }; static const struct v4l2_subdev_video_ops sr030pc30_video_ops = { @@ -807,6 +684,7 @@ static int sr030pc30_probe(struct i2c_client *client, { struct sr030pc30_info *info; struct v4l2_subdev *sd; + struct v4l2_ctrl_handler *hdl; const struct sr030pc30_platform_data *pdata = client->dev.platform_data; int ret; @@ -820,7 +698,7 @@ static int sr030pc30_probe(struct i2c_client *client, if (ret) return ret; - info = kzalloc(sizeof(*info), GFP_KERNEL); + info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; @@ -830,10 +708,31 @@ static int sr030pc30_probe(struct i2c_client *client, v4l2_i2c_subdev_init(sd, client, &sr030pc30_ops); + hdl = &info->hdl; + v4l2_ctrl_handler_init(hdl, 6); + info->awb = v4l2_ctrl_new_std(hdl, &sr030pc30_ctrl_ops, + V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1); + info->red = v4l2_ctrl_new_std(hdl, &sr030pc30_ctrl_ops, + V4L2_CID_RED_BALANCE, 0, 127, 1, 64); + info->blue = v4l2_ctrl_new_std(hdl, &sr030pc30_ctrl_ops, + V4L2_CID_BLUE_BALANCE, 0, 127, 1, 64); + info->autoexp = v4l2_ctrl_new_std(hdl, &sr030pc30_ctrl_ops, + V4L2_CID_EXPOSURE_AUTO, 0, 1, 1, 1); + info->exp = v4l2_ctrl_new_std(hdl, &sr030pc30_ctrl_ops, + V4L2_CID_EXPOSURE, EXPOS_MIN_MS, EXPOS_MAX_MS, 1, 30); + sd->ctrl_handler = hdl; + if (hdl->error) { + int err = hdl->error; + + v4l2_ctrl_handler_free(hdl); + return err; + } + v4l2_ctrl_auto_cluster(3, &info->awb, 0, false); + v4l2_ctrl_auto_cluster(2, &info->autoexp, V4L2_EXPOSURE_MANUAL, false); + v4l2_ctrl_handler_setup(hdl); + info->i2c_reg_page = -1; info->hflip = 1; - info->auto_exp = 1; - info->exposure = 30; return 0; } @@ -841,10 +740,9 @@ static int sr030pc30_probe(struct i2c_client *client, static int sr030pc30_remove(struct i2c_client *client) { struct v4l2_subdev *sd = i2c_get_clientdata(client); - struct sr030pc30_info *info = to_sr030pc30(sd); v4l2_device_unregister_subdev(sd); - kfree(info); + v4l2_ctrl_handler_free(sd->ctrl_handler); return 0; } diff --git a/drivers/media/i2c/tda7432.c b/drivers/media/i2c/tda7432.c index 28b5121881f5..72af644fa051 100644 --- a/drivers/media/i2c/tda7432.c +++ b/drivers/media/i2c/tda7432.c @@ -359,7 +359,7 @@ static int tda7432_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%02x (%s)\n", client->addr << 1, client->adapter->name); - t = kzalloc(sizeof(*t), GFP_KERNEL); + t = devm_kzalloc(&client->dev, sizeof(*t), GFP_KERNEL); if (!t) return -ENOMEM; sd = &t->sd; @@ -380,7 +380,6 @@ static int tda7432_probe(struct i2c_client *client, int err = t->hdl.error; v4l2_ctrl_handler_free(&t->hdl); - kfree(t); return err; } v4l2_ctrl_cluster(2, &t->bass); @@ -406,7 +405,6 @@ static int tda7432_remove(struct i2c_client *client) tda7432_set(sd); v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&t->hdl); - kfree(t); return 0; } diff --git a/drivers/media/i2c/tda9840.c b/drivers/media/i2c/tda9840.c index 01441e35d88b..fbdff8b24eec 100644 --- a/drivers/media/i2c/tda9840.c +++ b/drivers/media/i2c/tda9840.c @@ -31,7 +31,6 @@ #include <linux/slab.h> #include <linux/i2c.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> MODULE_AUTHOR("Michael Hunold <michael@mihu.de>"); MODULE_DESCRIPTION("tda9840 driver"); @@ -145,26 +144,14 @@ static int tda9840_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *t) return 0; } -static int tda9840_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TDA9840, 0); -} - /* ----------------------------------------------------------------------- */ -static const struct v4l2_subdev_core_ops tda9840_core_ops = { - .g_chip_ident = tda9840_g_chip_ident, -}; - static const struct v4l2_subdev_tuner_ops tda9840_tuner_ops = { .s_tuner = tda9840_s_tuner, .g_tuner = tda9840_g_tuner, }; static const struct v4l2_subdev_ops tda9840_ops = { - .core = &tda9840_core_ops, .tuner = &tda9840_tuner_ops, }; @@ -184,7 +171,7 @@ static int tda9840_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); + sd = devm_kzalloc(&client->dev, sizeof(*sd), GFP_KERNEL); if (sd == NULL) return -ENOMEM; v4l2_i2c_subdev_init(sd, client, &tda9840_ops); @@ -201,7 +188,6 @@ static int tda9840_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); v4l2_device_unregister_subdev(sd); - kfree(sd); return 0; } diff --git a/drivers/media/i2c/tea6415c.c b/drivers/media/i2c/tea6415c.c index 3d5b06a5c308..bbe1a99fda36 100644 --- a/drivers/media/i2c/tea6415c.c +++ b/drivers/media/i2c/tea6415c.c @@ -33,7 +33,6 @@ #include <linux/slab.h> #include <linux/i2c.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> #include "tea6415c.h" MODULE_AUTHOR("Michael Hunold <michael@mihu.de>"); @@ -119,25 +118,13 @@ static int tea6415c_s_routing(struct v4l2_subdev *sd, return ret; } -static int tea6415c_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TEA6415C, 0); -} - /* ----------------------------------------------------------------------- */ -static const struct v4l2_subdev_core_ops tea6415c_core_ops = { - .g_chip_ident = tea6415c_g_chip_ident, -}; - static const struct v4l2_subdev_video_ops tea6415c_video_ops = { .s_routing = tea6415c_s_routing, }; static const struct v4l2_subdev_ops tea6415c_ops = { - .core = &tea6415c_core_ops, .video = &tea6415c_video_ops, }; @@ -152,7 +139,7 @@ static int tea6415c_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); + sd = devm_kzalloc(&client->dev, sizeof(*sd), GFP_KERNEL); if (sd == NULL) return -ENOMEM; v4l2_i2c_subdev_init(sd, client, &tea6415c_ops); @@ -164,7 +151,6 @@ static int tea6415c_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); v4l2_device_unregister_subdev(sd); - kfree(sd); return 0; } diff --git a/drivers/media/i2c/tea6420.c b/drivers/media/i2c/tea6420.c index 38757217a074..30a8d75771af 100644 --- a/drivers/media/i2c/tea6420.c +++ b/drivers/media/i2c/tea6420.c @@ -33,7 +33,6 @@ #include <linux/slab.h> #include <linux/i2c.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> #include "tea6420.h" MODULE_AUTHOR("Michael Hunold <michael@mihu.de>"); @@ -90,25 +89,13 @@ static int tea6420_s_routing(struct v4l2_subdev *sd, return 0; } -static int tea6420_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TEA6420, 0); -} - /* ----------------------------------------------------------------------- */ -static const struct v4l2_subdev_core_ops tea6420_core_ops = { - .g_chip_ident = tea6420_g_chip_ident, -}; - static const struct v4l2_subdev_audio_ops tea6420_audio_ops = { .s_routing = tea6420_s_routing, }; static const struct v4l2_subdev_ops tea6420_ops = { - .core = &tea6420_core_ops, .audio = &tea6420_audio_ops, }; @@ -125,7 +112,7 @@ static int tea6420_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); + sd = devm_kzalloc(&client->dev, sizeof(*sd), GFP_KERNEL); if (sd == NULL) return -ENOMEM; v4l2_i2c_subdev_init(sd, client, &tea6420_ops); @@ -146,7 +133,6 @@ static int tea6420_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); v4l2_device_unregister_subdev(sd); - kfree(sd); return 0; } diff --git a/drivers/media/i2c/ths7303.c b/drivers/media/i2c/ths7303.c index c4339556a2ea..0a2dacbd7a63 100644 --- a/drivers/media/i2c/ths7303.c +++ b/drivers/media/i2c/ths7303.c @@ -26,7 +26,6 @@ #include <linux/slab.h> #include <media/ths7303.h> -#include <media/v4l2-chip-ident.h> #include <media/v4l2-device.h> #define THS7303_CHANNEL_1 1 @@ -35,11 +34,10 @@ struct ths7303_state { struct v4l2_subdev sd; - struct ths7303_platform_data pdata; + const struct ths7303_platform_data *pdata; struct v4l2_bt_timings bt; int std_id; int stream_on; - int driver_data; }; enum ths7303_filter_mode { @@ -89,7 +87,7 @@ int ths7303_setval(struct v4l2_subdev *sd, enum ths7303_filter_mode mode) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct ths7303_state *state = to_state(sd); - struct ths7303_platform_data *pdata = &state->pdata; + const struct ths7303_platform_data *pdata = state->pdata; u8 val, sel = 0; int err, disable = 0; @@ -212,15 +210,6 @@ static int ths7303_s_dv_timings(struct v4l2_subdev *sd, return ths7303_config(sd); } -static int ths7303_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct ths7303_state *state = to_state(sd); - - return v4l2_chip_ident_i2c_client(client, chip, state->driver_data, 0); -} - static const struct v4l2_subdev_video_ops ths7303_video_ops = { .s_stream = ths7303_s_stream, .s_std_output = ths7303_s_std_output, @@ -232,13 +221,6 @@ static const struct v4l2_subdev_video_ops ths7303_video_ops = { static int ths7303_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - reg->size = 1; reg->val = ths7303_read(sd, reg->reg); return 0; @@ -247,13 +229,6 @@ static int ths7303_g_register(struct v4l2_subdev *sd, static int ths7303_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - ths7303_write(sd, reg->reg, reg->val); return 0; } @@ -340,7 +315,6 @@ static int ths7303_log_status(struct v4l2_subdev *sd) } static const struct v4l2_subdev_core_ops ths7303_core_ops = { - .g_chip_ident = ths7303_g_chip_ident, .log_status = ths7303_log_status, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = ths7303_g_register, @@ -353,32 +327,6 @@ static const struct v4l2_subdev_ops ths7303_ops = { .video = &ths7303_video_ops, }; -static int ths7303_setup(struct v4l2_subdev *sd) -{ - struct ths7303_state *state = to_state(sd); - struct ths7303_platform_data *pdata = &state->pdata; - int ret; - u8 mask; - - state->stream_on = pdata->init_enable; - - mask = state->stream_on ? 0xff : 0xf8; - - ret = ths7303_write(sd, THS7303_CHANNEL_1, pdata->ch_1 & mask); - if (ret) - return ret; - - ret = ths7303_write(sd, THS7303_CHANNEL_2, pdata->ch_2 & mask); - if (ret) - return ret; - - ret = ths7303_write(sd, THS7303_CHANNEL_3, pdata->ch_3 & mask); - if (ret) - return ret; - - return 0; -} - static int ths7303_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -386,6 +334,11 @@ static int ths7303_probe(struct i2c_client *client, struct ths7303_state *state; struct v4l2_subdev *sd; + if (pdata == NULL) { + dev_err(&client->dev, "No platform data\n"); + return -EINVAL; + } + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -ENODEV; @@ -397,20 +350,14 @@ static int ths7303_probe(struct i2c_client *client, if (!state) return -ENOMEM; - if (!pdata) - v4l_warn(client, "No platform data, using default data!\n"); - else - state->pdata = *pdata; - + state->pdata = pdata; sd = &state->sd; v4l2_i2c_subdev_init(sd, client, &ths7303_ops); - /* store the driver data to differntiate the chip */ - state->driver_data = (int)id->driver_data; - - if (ths7303_setup(sd) < 0) { - v4l_err(client, "init failed\n"); - return -EIO; + /* set to default 480I_576I filter mode */ + if (ths7303_setval(sd, THS7303_FILTER_MODE_480I_576I) < 0) { + v4l_err(client, "Setting to 480I_576I filter mode failed!\n"); + return -EINVAL; } return 0; @@ -426,8 +373,8 @@ static int ths7303_remove(struct i2c_client *client) } static const struct i2c_device_id ths7303_id[] = { - {"ths7303", V4L2_IDENT_THS7303}, - {"ths7353", V4L2_IDENT_THS7353}, + {"ths7303", 0}, + {"ths7353", 0}, {}, }; diff --git a/drivers/media/i2c/ths8200.c b/drivers/media/i2c/ths8200.c new file mode 100644 index 000000000000..a24f90c5261c --- /dev/null +++ b/drivers/media/i2c/ths8200.c @@ -0,0 +1,556 @@ +/* + * ths8200 - Texas Instruments THS8200 video encoder driver + * + * Copyright 2013 Cisco Systems, Inc. and/or its affiliates. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/v4l2-dv-timings.h> + +#include <media/v4l2-device.h> + +#include "ths8200_regs.h" + +static int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "debug level (0-2)"); + +MODULE_DESCRIPTION("Texas Instruments THS8200 video encoder driver"); +MODULE_AUTHOR("Mats Randgaard <mats.randgaard@cisco.com>"); +MODULE_AUTHOR("Martin Bugge <martin.bugge@cisco.com>"); +MODULE_LICENSE("GPL v2"); + +struct ths8200_state { + struct v4l2_subdev sd; + uint8_t chip_version; + /* Is the ths8200 powered on? */ + bool power_on; + struct v4l2_dv_timings dv_timings; +}; + +static const struct v4l2_dv_timings ths8200_timings[] = { + V4L2_DV_BT_CEA_720X480P59_94, + V4L2_DV_BT_CEA_1280X720P24, + V4L2_DV_BT_CEA_1280X720P25, + V4L2_DV_BT_CEA_1280X720P30, + V4L2_DV_BT_CEA_1280X720P50, + V4L2_DV_BT_CEA_1280X720P60, + V4L2_DV_BT_CEA_1920X1080P24, + V4L2_DV_BT_CEA_1920X1080P25, + V4L2_DV_BT_CEA_1920X1080P30, + V4L2_DV_BT_CEA_1920X1080P50, + V4L2_DV_BT_CEA_1920X1080P60, +}; + +static inline struct ths8200_state *to_state(struct v4l2_subdev *sd) +{ + return container_of(sd, struct ths8200_state, sd); +} + +static inline unsigned hblanking(const struct v4l2_bt_timings *t) +{ + return t->hfrontporch + t->hsync + t->hbackporch; +} + +static inline unsigned htotal(const struct v4l2_bt_timings *t) +{ + return t->width + t->hfrontporch + t->hsync + t->hbackporch; +} + +static inline unsigned vblanking(const struct v4l2_bt_timings *t) +{ + return t->vfrontporch + t->vsync + t->vbackporch; +} + +static inline unsigned vtotal(const struct v4l2_bt_timings *t) +{ + return t->height + t->vfrontporch + t->vsync + t->vbackporch; +} + +static int ths8200_read(struct v4l2_subdev *sd, u8 reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + + return i2c_smbus_read_byte_data(client, reg); +} + +static int ths8200_write(struct v4l2_subdev *sd, u8 reg, u8 val) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); + int ret; + int i; + + for (i = 0; i < 3; i++) { + ret = i2c_smbus_write_byte_data(client, reg, val); + if (ret == 0) + return 0; + } + v4l2_err(sd, "I2C Write Problem\n"); + return ret; +} + +/* To set specific bits in the register, a clear-mask is given (to be AND-ed), + * and then the value-mask (to be OR-ed). + */ +static inline void +ths8200_write_and_or(struct v4l2_subdev *sd, u8 reg, + uint8_t clr_mask, uint8_t val_mask) +{ + ths8200_write(sd, reg, (ths8200_read(sd, reg) & clr_mask) | val_mask); +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG + +static int ths8200_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + reg->val = ths8200_read(sd, reg->reg & 0xff); + reg->size = 1; + + return 0; +} + +static int ths8200_s_register(struct v4l2_subdev *sd, + const struct v4l2_dbg_register *reg) +{ + ths8200_write(sd, reg->reg & 0xff, reg->val & 0xff); + + return 0; +} +#endif + +static void ths8200_print_timings(struct v4l2_subdev *sd, + struct v4l2_dv_timings *timings, + const char *txt, bool detailed) +{ + struct v4l2_bt_timings *bt = &timings->bt; + u32 htot, vtot; + + if (timings->type != V4L2_DV_BT_656_1120) + return; + + htot = htotal(bt); + vtot = vtotal(bt); + + v4l2_info(sd, "%s %dx%d%s%d (%dx%d)", + txt, bt->width, bt->height, bt->interlaced ? "i" : "p", + (htot * vtot) > 0 ? ((u32)bt->pixelclock / (htot * vtot)) : 0, + htot, vtot); + + if (detailed) { + v4l2_info(sd, " horizontal: fp = %d, %ssync = %d, bp = %d\n", + bt->hfrontporch, + (bt->polarities & V4L2_DV_HSYNC_POS_POL) ? "+" : "-", + bt->hsync, bt->hbackporch); + v4l2_info(sd, " vertical: fp = %d, %ssync = %d, bp = %d\n", + bt->vfrontporch, + (bt->polarities & V4L2_DV_VSYNC_POS_POL) ? "+" : "-", + bt->vsync, bt->vbackporch); + v4l2_info(sd, + " pixelclock: %lld, flags: 0x%x, standards: 0x%x\n", + bt->pixelclock, bt->flags, bt->standards); + } +} + +static int ths8200_log_status(struct v4l2_subdev *sd) +{ + struct ths8200_state *state = to_state(sd); + uint8_t reg_03 = ths8200_read(sd, THS8200_CHIP_CTL); + + v4l2_info(sd, "----- Chip status -----\n"); + v4l2_info(sd, "version: %u\n", state->chip_version); + v4l2_info(sd, "power: %s\n", (reg_03 & 0x0c) ? "off" : "on"); + v4l2_info(sd, "reset: %s\n", (reg_03 & 0x01) ? "off" : "on"); + v4l2_info(sd, "test pattern: %s\n", + (reg_03 & 0x20) ? "enabled" : "disabled"); + v4l2_info(sd, "format: %ux%u\n", + ths8200_read(sd, THS8200_DTG2_PIXEL_CNT_MSB) * 256 + + ths8200_read(sd, THS8200_DTG2_PIXEL_CNT_LSB), + (ths8200_read(sd, THS8200_DTG2_LINE_CNT_MSB) & 0x07) * 256 + + ths8200_read(sd, THS8200_DTG2_LINE_CNT_LSB)); + ths8200_print_timings(sd, &state->dv_timings, + "Configured format:", true); + + return 0; +} + +/* Power up/down ths8200 */ +static int ths8200_s_power(struct v4l2_subdev *sd, int on) +{ + struct ths8200_state *state = to_state(sd); + + v4l2_dbg(1, debug, sd, "%s: power %s\n", __func__, on ? "on" : "off"); + + state->power_on = on; + + /* Power up/down - leave in reset state until input video is present */ + ths8200_write_and_or(sd, THS8200_CHIP_CTL, 0xf2, (on ? 0x00 : 0x0c)); + + return 0; +} + +static const struct v4l2_subdev_core_ops ths8200_core_ops = { + .log_status = ths8200_log_status, + .s_power = ths8200_s_power, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = ths8200_g_register, + .s_register = ths8200_s_register, +#endif +}; + +/* ----------------------------------------------------------------------------- + * V4L2 subdev video operations + */ + +static int ths8200_s_stream(struct v4l2_subdev *sd, int enable) +{ + struct ths8200_state *state = to_state(sd); + + if (enable && !state->power_on) + ths8200_s_power(sd, true); + + ths8200_write_and_or(sd, THS8200_CHIP_CTL, 0xfe, + (enable ? 0x01 : 0x00)); + + v4l2_dbg(1, debug, sd, "%s: %sable\n", + __func__, (enable ? "en" : "dis")); + + return 0; +} + +static void ths8200_core_init(struct v4l2_subdev *sd) +{ + /* setup clocks */ + ths8200_write_and_or(sd, THS8200_CHIP_CTL, 0x3f, 0xc0); + + /**** Data path control (DATA) ****/ + /* Set FSADJ 700 mV, + * bypass 422-444 interpolation, + * input format 30 bit RGB444 + */ + ths8200_write(sd, THS8200_DATA_CNTL, 0x70); + + /* DTG Mode (Video blocked during blanking + * VESA slave + */ + ths8200_write(sd, THS8200_DTG1_MODE, 0x87); + + /**** Display Timing Generator Control, Part 1 (DTG1). ****/ + + /* Disable embedded syncs on the output by setting + * the amplitude to zero for all channels. + */ + ths8200_write(sd, THS8200_DTG1_Y_SYNC_MSB, 0x2a); + ths8200_write(sd, THS8200_DTG1_CBCR_SYNC_MSB, 0x2a); +} + +static void ths8200_setup(struct v4l2_subdev *sd, struct v4l2_bt_timings *bt) +{ + uint8_t polarity = 0; + uint16_t line_start_active_video = (bt->vsync + bt->vbackporch); + uint16_t line_start_front_porch = (vtotal(bt) - bt->vfrontporch); + + /*** System ****/ + /* Set chip in reset while it is configured */ + ths8200_s_stream(sd, false); + + /* configure video output timings */ + ths8200_write(sd, THS8200_DTG1_SPEC_A, bt->hsync); + ths8200_write(sd, THS8200_DTG1_SPEC_B, bt->hfrontporch); + + /* Zero for progressive scan formats.*/ + if (!bt->interlaced) + ths8200_write(sd, THS8200_DTG1_SPEC_C, 0x00); + + /* Distance from leading edge of h sync to start of active video. + * MSB in 0x2b + */ + ths8200_write(sd, THS8200_DTG1_SPEC_D_LSB, + (bt->hbackporch + bt->hsync) & 0xff); + /* Zero for SDTV-mode. MSB in 0x2b */ + ths8200_write(sd, THS8200_DTG1_SPEC_E_LSB, 0x00); + /* + * MSB for dtg1_spec(d/e/h). See comment for + * corresponding LSB registers. + */ + ths8200_write(sd, THS8200_DTG1_SPEC_DEH_MSB, + ((bt->hbackporch + bt->hsync) & 0x100) >> 1); + + /* h front porch */ + ths8200_write(sd, THS8200_DTG1_SPEC_K_LSB, (bt->hfrontporch) & 0xff); + ths8200_write(sd, THS8200_DTG1_SPEC_K_MSB, + ((bt->hfrontporch) & 0x700) >> 8); + + /* Half the line length. Used to calculate SDTV line types. */ + ths8200_write(sd, THS8200_DTG1_SPEC_G_LSB, (htotal(bt)/2) & 0xff); + ths8200_write(sd, THS8200_DTG1_SPEC_G_MSB, + ((htotal(bt)/2) >> 8) & 0x0f); + + /* Total pixels per line (ex. 720p: 1650) */ + ths8200_write(sd, THS8200_DTG1_TOT_PIXELS_MSB, htotal(bt) >> 8); + ths8200_write(sd, THS8200_DTG1_TOT_PIXELS_LSB, htotal(bt) & 0xff); + + /* Frame height and field height */ + /* Field height should be programmed higher than frame_size for + * progressive scan formats + */ + ths8200_write(sd, THS8200_DTG1_FRAME_FIELD_SZ_MSB, + ((vtotal(bt) >> 4) & 0xf0) + 0x7); + ths8200_write(sd, THS8200_DTG1_FRAME_SZ_LSB, vtotal(bt) & 0xff); + + /* Should be programmed higher than frame_size + * for progressive formats + */ + if (!bt->interlaced) + ths8200_write(sd, THS8200_DTG1_FIELD_SZ_LSB, 0xff); + + /**** Display Timing Generator Control, Part 2 (DTG2). ****/ + /* Set breakpoint line numbers and types + * THS8200 generates line types with different properties. A line type + * that sets all the RGB-outputs to zero is used in the blanking areas, + * while a line type that enable the RGB-outputs is used in active video + * area. The line numbers for start of active video, start of front + * porch and after the last line in the frame must be set with the + * corresponding line types. + * + * Line types: + * 0x9 - Full normal sync pulse: Blocks data when dtg1_pass is off. + * Used in blanking area. + * 0x0 - Active video: Video data is always passed. Used in active + * video area. + */ + ths8200_write_and_or(sd, THS8200_DTG2_BP1_2_MSB, 0x88, + ((line_start_active_video >> 4) & 0x70) + + ((line_start_front_porch >> 8) & 0x07)); + ths8200_write(sd, THS8200_DTG2_BP3_4_MSB, ((vtotal(bt)) >> 4) & 0x70); + ths8200_write(sd, THS8200_DTG2_BP1_LSB, line_start_active_video & 0xff); + ths8200_write(sd, THS8200_DTG2_BP2_LSB, line_start_front_porch & 0xff); + ths8200_write(sd, THS8200_DTG2_BP3_LSB, (vtotal(bt)) & 0xff); + + /* line types */ + ths8200_write(sd, THS8200_DTG2_LINETYPE1, 0x90); + ths8200_write(sd, THS8200_DTG2_LINETYPE2, 0x90); + + /* h sync width transmitted */ + ths8200_write(sd, THS8200_DTG2_HLENGTH_LSB, bt->hsync & 0xff); + ths8200_write_and_or(sd, THS8200_DTG2_HLENGTH_LSB_HDLY_MSB, 0x3f, + (bt->hsync >> 2) & 0xc0); + + /* The pixel value h sync is asserted on */ + ths8200_write_and_or(sd, THS8200_DTG2_HLENGTH_LSB_HDLY_MSB, 0xe0, + (htotal(bt) >> 8) & 0x1f); + ths8200_write(sd, THS8200_DTG2_HLENGTH_HDLY_LSB, htotal(bt)); + + /* v sync width transmitted */ + ths8200_write(sd, THS8200_DTG2_VLENGTH1_LSB, (bt->vsync) & 0xff); + ths8200_write_and_or(sd, THS8200_DTG2_VLENGTH1_MSB_VDLY1_MSB, 0x3f, + ((bt->vsync) >> 2) & 0xc0); + + /* The pixel value v sync is asserted on */ + ths8200_write_and_or(sd, THS8200_DTG2_VLENGTH1_MSB_VDLY1_MSB, 0xf8, + (vtotal(bt)>>8) & 0x7); + ths8200_write(sd, THS8200_DTG2_VDLY1_LSB, vtotal(bt)); + + /* For progressive video vlength2 must be set to all 0 and vdly2 must + * be set to all 1. + */ + ths8200_write(sd, THS8200_DTG2_VLENGTH2_LSB, 0x00); + ths8200_write(sd, THS8200_DTG2_VLENGTH2_MSB_VDLY2_MSB, 0x07); + ths8200_write(sd, THS8200_DTG2_VDLY2_LSB, 0xff); + + /* Internal delay factors to synchronize the sync pulses and the data */ + /* Experimental values delays (hor 4, ver 1) */ + ths8200_write(sd, THS8200_DTG2_HS_IN_DLY_MSB, (htotal(bt)>>8) & 0x1f); + ths8200_write(sd, THS8200_DTG2_HS_IN_DLY_LSB, (htotal(bt) - 4) & 0xff); + ths8200_write(sd, THS8200_DTG2_VS_IN_DLY_MSB, 0); + ths8200_write(sd, THS8200_DTG2_VS_IN_DLY_LSB, 1); + + /* Polarity of received and transmitted sync signals */ + if (bt->polarities & V4L2_DV_HSYNC_POS_POL) { + polarity |= 0x01; /* HS_IN */ + polarity |= 0x08; /* HS_OUT */ + } + if (bt->polarities & V4L2_DV_VSYNC_POS_POL) { + polarity |= 0x02; /* VS_IN */ + polarity |= 0x10; /* VS_OUT */ + } + + /* RGB mode, no embedded timings */ + /* Timing of video input bus is derived from HS, VS, and FID dedicated + * inputs + */ + ths8200_write(sd, THS8200_DTG2_CNTL, 0x47 | polarity); + + /* leave reset */ + ths8200_s_stream(sd, true); + + v4l2_dbg(1, debug, sd, "%s: frame %dx%d, polarity %d\n" + "horizontal: front porch %d, back porch %d, sync %d\n" + "vertical: sync %d\n", __func__, htotal(bt), vtotal(bt), + polarity, bt->hfrontporch, bt->hbackporch, + bt->hsync, bt->vsync); +} + +static int ths8200_s_dv_timings(struct v4l2_subdev *sd, + struct v4l2_dv_timings *timings) +{ + struct ths8200_state *state = to_state(sd); + int i; + + v4l2_dbg(1, debug, sd, "%s:\n", __func__); + + if (timings->type != V4L2_DV_BT_656_1120) + return -EINVAL; + + /* TODO Support interlaced formats */ + if (timings->bt.interlaced) { + v4l2_dbg(1, debug, sd, "TODO Support interlaced formats\n"); + return -EINVAL; + } + + for (i = 0; i < ARRAY_SIZE(ths8200_timings); i++) { + if (v4l_match_dv_timings(&ths8200_timings[i], timings, 10)) + break; + } + + if (i == ARRAY_SIZE(ths8200_timings)) { + v4l2_dbg(1, debug, sd, "Unsupported format\n"); + return -EINVAL; + } + + timings->bt.flags &= ~V4L2_DV_FL_REDUCED_FPS; + + /* save timings */ + state->dv_timings = *timings; + + ths8200_setup(sd, &timings->bt); + + return 0; +} + +static int ths8200_g_dv_timings(struct v4l2_subdev *sd, + struct v4l2_dv_timings *timings) +{ + struct ths8200_state *state = to_state(sd); + + v4l2_dbg(1, debug, sd, "%s:\n", __func__); + + *timings = state->dv_timings; + + return 0; +} + +static int ths8200_enum_dv_timings(struct v4l2_subdev *sd, + struct v4l2_enum_dv_timings *timings) +{ + /* Check requested format index is within range */ + if (timings->index >= ARRAY_SIZE(ths8200_timings)) + return -EINVAL; + + timings->timings = ths8200_timings[timings->index]; + + return 0; +} + +static int ths8200_dv_timings_cap(struct v4l2_subdev *sd, + struct v4l2_dv_timings_cap *cap) +{ + cap->type = V4L2_DV_BT_656_1120; + cap->bt.max_width = 1920; + cap->bt.max_height = 1080; + cap->bt.min_pixelclock = 27000000; + cap->bt.max_pixelclock = 148500000; + cap->bt.standards = V4L2_DV_BT_STD_CEA861; + cap->bt.capabilities = V4L2_DV_BT_CAP_PROGRESSIVE; + + return 0; +} + +/* Specific video subsystem operation handlers */ +static const struct v4l2_subdev_video_ops ths8200_video_ops = { + .s_stream = ths8200_s_stream, + .s_dv_timings = ths8200_s_dv_timings, + .g_dv_timings = ths8200_g_dv_timings, + .enum_dv_timings = ths8200_enum_dv_timings, + .dv_timings_cap = ths8200_dv_timings_cap, +}; + +/* V4L2 top level operation handlers */ +static const struct v4l2_subdev_ops ths8200_ops = { + .core = &ths8200_core_ops, + .video = &ths8200_video_ops, +}; + +static int ths8200_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct ths8200_state *state; + struct v4l2_subdev *sd; + + /* Check if the adapter supports the needed features */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -EIO; + + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); + if (!state) + return -ENOMEM; + + sd = &state->sd; + v4l2_i2c_subdev_init(sd, client, &ths8200_ops); + + state->chip_version = ths8200_read(sd, THS8200_VERSION); + v4l2_dbg(1, debug, sd, "chip version 0x%x\n", state->chip_version); + + ths8200_core_init(sd); + + v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name, + client->addr << 1, client->adapter->name); + + return 0; +} + +static int ths8200_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + + v4l2_dbg(1, debug, sd, "%s removed @ 0x%x (%s)\n", client->name, + client->addr << 1, client->adapter->name); + + ths8200_s_power(sd, false); + + v4l2_device_unregister_subdev(sd); + + return 0; +} + +static struct i2c_device_id ths8200_id[] = { + { "ths8200", 0 }, + {}, +}; +MODULE_DEVICE_TABLE(i2c, ths8200_id); + +static struct i2c_driver ths8200_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "ths8200", + }, + .probe = ths8200_probe, + .remove = ths8200_remove, + .id_table = ths8200_id, +}; + +module_i2c_driver(ths8200_driver); diff --git a/drivers/media/i2c/ths8200_regs.h b/drivers/media/i2c/ths8200_regs.h new file mode 100644 index 000000000000..6bc9fd1111db --- /dev/null +++ b/drivers/media/i2c/ths8200_regs.h @@ -0,0 +1,161 @@ +/* + * ths8200 - Texas Instruments THS8200 video encoder driver + * + * Copyright 2013 Cisco Systems, Inc. and/or its affiliates. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 version 2. + * + * This program is distributed .as is. WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef THS8200_REGS_H +#define THS8200_REGS_H + +/* Register offset macros */ +#define THS8200_VERSION 0x02 +#define THS8200_CHIP_CTL 0x03 +#define THS8200_CSC_R11 0x04 +#define THS8200_CSC_R12 0x05 +#define THS8200_CSC_R21 0x06 +#define THS8200_CSC_R22 0x07 +#define THS8200_CSC_R31 0x08 +#define THS8200_CSC_R32 0x09 +#define THS8200_CSC_G11 0x0a +#define THS8200_CSC_G12 0x0b +#define THS8200_CSC_G21 0x0c +#define THS8200_CSC_G22 0x0d +#define THS8200_CSC_G31 0x0e +#define THS8200_CSC_G32 0x0f +#define THS8200_CSC_B11 0x10 +#define THS8200_CSC_B12 0x11 +#define THS8200_CSC_B21 0x12 +#define THS8200_CSC_B22 0x13 +#define THS8200_CSC_B31 0x14 +#define THS8200_CSC_B32 0x15 +#define THS8200_CSC_OFFS1 0x16 +#define THS8200_CSC_OFFS12 0x17 +#define THS8200_CSC_OFFS23 0x18 +#define THS8200_CSC_OFFS3 0x19 +#define THS8200_TST_CNTL1 0x1a +#define THS8200_TST_CNTL2 0x1b +#define THS8200_DATA_CNTL 0x1c +#define THS8200_DTG1_Y_SYNC1_LSB 0x1d +#define THS8200_DTG1_Y_SYNC2_LSB 0x1e +#define THS8200_DTG1_Y_SYNC3_LSB 0x1f +#define THS8200_DTG1_CBCR_SYNC1_LSB 0x20 +#define THS8200_DTG1_CBCR_SYNC2_LSB 0x21 +#define THS8200_DTG1_CBCR_SYNC3_LSB 0x22 +#define THS8200_DTG1_Y_SYNC_MSB 0x23 +#define THS8200_DTG1_CBCR_SYNC_MSB 0x24 +#define THS8200_DTG1_SPEC_A 0x25 +#define THS8200_DTG1_SPEC_B 0x26 +#define THS8200_DTG1_SPEC_C 0x27 +#define THS8200_DTG1_SPEC_D_LSB 0x28 +#define THS8200_DTG1_SPEC_D1 0x29 +#define THS8200_DTG1_SPEC_E_LSB 0x2a +#define THS8200_DTG1_SPEC_DEH_MSB 0x2b +#define THS8200_DTG1_SPEC_H_LSB 0x2c +#define THS8200_DTG1_SPEC_I_MSB 0x2d +#define THS8200_DTG1_SPEC_I_LSB 0x2e +#define THS8200_DTG1_SPEC_K_LSB 0x2f +#define THS8200_DTG1_SPEC_K_MSB 0x30 +#define THS8200_DTG1_SPEC_K1 0x31 +#define THS8200_DTG1_SPEC_G_LSB 0x32 +#define THS8200_DTG1_SPEC_G_MSB 0x33 +#define THS8200_DTG1_TOT_PIXELS_MSB 0x34 +#define THS8200_DTG1_TOT_PIXELS_LSB 0x35 +#define THS8200_DTG1_FLD_FLIP_LINECNT_MSB 0x36 +#define THS8200_DTG1_LINECNT_LSB 0x37 +#define THS8200_DTG1_MODE 0x38 +#define THS8200_DTG1_FRAME_FIELD_SZ_MSB 0x39 +#define THS8200_DTG1_FRAME_SZ_LSB 0x3a +#define THS8200_DTG1_FIELD_SZ_LSB 0x3b +#define THS8200_DTG1_VESA_CBAR_SIZE 0x3c +#define THS8200_DAC_CNTL_MSB 0x3d +#define THS8200_DAC1_CNTL_LSB 0x3e +#define THS8200_DAC2_CNTL_LSB 0x3f +#define THS8200_DAC3_CNTL_LSB 0x40 +#define THS8200_CSM_CLIP_GY_LOW 0x41 +#define THS8200_CSM_CLIP_BCB_LOW 0x42 +#define THS8200_CSM_CLIP_RCR_LOW 0x43 +#define THS8200_CSM_CLIP_GY_HIGH 0x44 +#define THS8200_CSM_CLIP_BCB_HIGH 0x45 +#define THS8200_CSM_CLIP_RCR_HIGH 0x46 +#define THS8200_CSM_SHIFT_GY 0x47 +#define THS8200_CSM_SHIFT_BCB 0x48 +#define THS8200_CSM_SHIFT_RCR 0x49 +#define THS8200_CSM_GY_CNTL_MULT_MSB 0x4a +#define THS8200_CSM_MULT_BCB_RCR_MSB 0x4b +#define THS8200_CSM_MULT_GY_LSB 0x4c +#define THS8200_CSM_MULT_BCB_LSB 0x4d +#define THS8200_CSM_MULT_RCR_LSB 0x4e +#define THS8200_CSM_MULT_RCR_BCB_CNTL 0x4f +#define THS8200_CSM_MULT_RCR_LSB 0x4e +#define THS8200_DTG2_BP1_2_MSB 0x50 +#define THS8200_DTG2_BP3_4_MSB 0x51 +#define THS8200_DTG2_BP5_6_MSB 0x52 +#define THS8200_DTG2_BP7_8_MSB 0x53 +#define THS8200_DTG2_BP9_10_MSB 0x54 +#define THS8200_DTG2_BP11_12_MSB 0x55 +#define THS8200_DTG2_BP13_14_MSB 0x56 +#define THS8200_DTG2_BP15_16_MSB 0x57 +#define THS8200_DTG2_BP1_LSB 0x58 +#define THS8200_DTG2_BP2_LSB 0x59 +#define THS8200_DTG2_BP3_LSB 0x5a +#define THS8200_DTG2_BP4_LSB 0x5b +#define THS8200_DTG2_BP5_LSB 0x5c +#define THS8200_DTG2_BP6_LSB 0x5d +#define THS8200_DTG2_BP7_LSB 0x5e +#define THS8200_DTG2_BP8_LSB 0x5f +#define THS8200_DTG2_BP9_LSB 0x60 +#define THS8200_DTG2_BP10_LSB 0x61 +#define THS8200_DTG2_BP11_LSB 0x62 +#define THS8200_DTG2_BP12_LSB 0x63 +#define THS8200_DTG2_BP13_LSB 0x64 +#define THS8200_DTG2_BP14_LSB 0x65 +#define THS8200_DTG2_BP15_LSB 0x66 +#define THS8200_DTG2_BP16_LSB 0x67 +#define THS8200_DTG2_LINETYPE1 0x68 +#define THS8200_DTG2_LINETYPE2 0x69 +#define THS8200_DTG2_LINETYPE3 0x6a +#define THS8200_DTG2_LINETYPE4 0x6b +#define THS8200_DTG2_LINETYPE5 0x6c +#define THS8200_DTG2_LINETYPE6 0x6d +#define THS8200_DTG2_LINETYPE7 0x6e +#define THS8200_DTG2_LINETYPE8 0x6f +#define THS8200_DTG2_HLENGTH_LSB 0x70 +#define THS8200_DTG2_HLENGTH_LSB_HDLY_MSB 0x71 +#define THS8200_DTG2_HLENGTH_HDLY_LSB 0x72 +#define THS8200_DTG2_VLENGTH1_LSB 0x73 +#define THS8200_DTG2_VLENGTH1_MSB_VDLY1_MSB 0x74 +#define THS8200_DTG2_VDLY1_LSB 0x75 +#define THS8200_DTG2_VLENGTH2_LSB 0x76 +#define THS8200_DTG2_VLENGTH2_MSB_VDLY2_MSB 0x77 +#define THS8200_DTG2_VDLY2_LSB 0x78 +#define THS8200_DTG2_HS_IN_DLY_MSB 0x79 +#define THS8200_DTG2_HS_IN_DLY_LSB 0x7a +#define THS8200_DTG2_VS_IN_DLY_MSB 0x7b +#define THS8200_DTG2_VS_IN_DLY_LSB 0x7c +#define THS8200_DTG2_PIXEL_CNT_MSB 0x7d +#define THS8200_DTG2_PIXEL_CNT_LSB 0x7e +#define THS8200_DTG2_LINE_CNT_MSB 0x7f +#define THS8200_DTG2_LINE_CNT_LSB 0x80 +#define THS8200_DTG2_CNTL 0x82 +#define THS8200_CGMS_CNTL_HEADER 0x83 +#define THS8200_CGMS_PAYLOAD_MSB 0x84 +#define THS8200_CGMS_PAYLOAD_LSB 0x85 +#define THS8200_MISC_PPL_LSB 0x86 +#define THS8200_MISC_PPL_MSB 0x87 +#define THS8200_MISC_LPF_MSB 0x88 +#define THS8200_MISC_LPF_LSB 0x89 + +#endif /* THS8200_REGS_H */ diff --git a/drivers/media/i2c/tlv320aic23b.c b/drivers/media/i2c/tlv320aic23b.c index 809a75a558ee..ef87f7b09ea2 100644 --- a/drivers/media/i2c/tlv320aic23b.c +++ b/drivers/media/i2c/tlv320aic23b.c @@ -162,7 +162,7 @@ static int tlv320aic23b_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - state = kzalloc(sizeof(struct tlv320aic23b_state), GFP_KERNEL); + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (state == NULL) return -ENOMEM; sd = &state->sd; @@ -191,7 +191,6 @@ static int tlv320aic23b_probe(struct i2c_client *client, int err = state->hdl.error; v4l2_ctrl_handler_free(&state->hdl); - kfree(state); return err; } v4l2_ctrl_handler_setup(&state->hdl); @@ -205,7 +204,6 @@ static int tlv320aic23b_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&state->hdl); - kfree(state); return 0; } diff --git a/drivers/media/i2c/tvaudio.c b/drivers/media/i2c/tvaudio.c index e0634c8b7e0b..d76c53a8f027 100644 --- a/drivers/media/i2c/tvaudio.c +++ b/drivers/media/i2c/tvaudio.c @@ -38,7 +38,6 @@ #include <media/tvaudio.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> #include <media/v4l2-ctrls.h> #include <media/i2c-addr.h> @@ -1838,13 +1837,6 @@ static int tvaudio_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequen return 0; } -static int tvaudio_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TVAUDIO, 0); -} - static int tvaudio_log_status(struct v4l2_subdev *sd) { struct CHIPSTATE *chip = to_state(sd); @@ -1863,7 +1855,6 @@ static const struct v4l2_ctrl_ops tvaudio_ctrl_ops = { static const struct v4l2_subdev_core_ops tvaudio_core_ops = { .log_status = tvaudio_log_status, - .g_chip_ident = tvaudio_g_chip_ident, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, @@ -1910,7 +1901,7 @@ static int tvaudio_probe(struct i2c_client *client, const struct i2c_device_id * printk("\n"); } - chip = kzalloc(sizeof(*chip), GFP_KERNEL); + chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); if (!chip) return -ENOMEM; sd = &chip->sd; @@ -1930,7 +1921,6 @@ static int tvaudio_probe(struct i2c_client *client, const struct i2c_device_id * } if (desc->name == NULL) { v4l2_dbg(1, debug, sd, "no matching chip description found\n"); - kfree(chip); return -EIO; } v4l2_info(sd, "%s found @ 0x%x (%s)\n", desc->name, client->addr<<1, client->adapter->name); @@ -2001,7 +1991,6 @@ static int tvaudio_probe(struct i2c_client *client, const struct i2c_device_id * int err = chip->hdl.error; v4l2_ctrl_handler_free(&chip->hdl); - kfree(chip); return err; } /* set controls to the default values */ @@ -2044,7 +2033,6 @@ static int tvaudio_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&chip->hdl); - kfree(chip); return 0; } diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c index ab8f3fee7e94..9c6d66a9868f 100644 --- a/drivers/media/i2c/tvp514x.c +++ b/drivers/media/i2c/tvp514x.c @@ -39,7 +39,7 @@ #include <media/v4l2-device.h> #include <media/v4l2-common.h> #include <media/v4l2-mediabus.h> -#include <media/v4l2-chip-ident.h> +#include <media/v4l2-of.h> #include <media/v4l2-ctrls.h> #include <media/tvp514x.h> #include <media/media-entity.h> @@ -123,6 +123,8 @@ struct tvp514x_decoder { /* mc related members */ struct media_pad pad; struct v4l2_mbus_framefmt format; + + struct tvp514x_reg *int_seq; }; /* TVP514x default register values */ @@ -543,8 +545,6 @@ static int tvp514x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id) if (std_id == NULL) return -EINVAL; - *std_id = V4L2_STD_UNKNOWN; - /* To query the standard the TVP514x must power on the ADCs. */ if (!decoder->streaming) { tvp514x_s_stream(sd, 1); @@ -553,8 +553,10 @@ static int tvp514x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id) /* query the current standard */ current_std = tvp514x_query_current_std(sd); - if (current_std == STD_INVALID) + if (current_std == STD_INVALID) { + *std_id = V4L2_STD_UNKNOWN; return 0; + } input_sel = decoder->input; @@ -595,10 +597,12 @@ static int tvp514x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id) } /* check whether signal is locked */ sync_lock_status = tvp514x_read_reg(sd, REG_STATUS1); - if (lock_mask != (sync_lock_status & lock_mask)) + if (lock_mask != (sync_lock_status & lock_mask)) { + *std_id = V4L2_STD_UNKNOWN; return 0; /* No input detected */ + } - *std_id = decoder->std_list[current_std].standard.id; + *std_id &= decoder->std_list[current_std].standard.id; v4l2_dbg(1, debug, sd, "Current STD: %s\n", decoder->std_list[current_std].standard.name); @@ -862,7 +866,6 @@ tvp514x_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a) static int tvp514x_s_stream(struct v4l2_subdev *sd, int enable) { int err = 0; - struct i2c_client *client = v4l2_get_subdevdata(sd); struct tvp514x_decoder *decoder = to_decoder(sd); if (decoder->streaming == enable) @@ -882,11 +885,8 @@ static int tvp514x_s_stream(struct v4l2_subdev *sd, int enable) } case 1: { - struct tvp514x_reg *int_seq = (struct tvp514x_reg *) - client->driver->id_table->driver_data; - /* Power Up Sequence */ - err = tvp514x_write_regs(sd, int_seq); + err = tvp514x_write_regs(sd, decoder->int_seq); if (err) { v4l2_err(sd, "Unable to turn on decoder\n"); return err; @@ -1055,6 +1055,42 @@ static struct tvp514x_decoder tvp514x_dev = { }; +static struct tvp514x_platform_data * +tvp514x_get_pdata(struct i2c_client *client) +{ + struct tvp514x_platform_data *pdata; + struct v4l2_of_endpoint bus_cfg; + struct device_node *endpoint; + unsigned int flags; + + if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node) + return client->dev.platform_data; + + endpoint = v4l2_of_get_next_endpoint(client->dev.of_node, NULL); + if (!endpoint) + return NULL; + + pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + goto done; + + v4l2_of_parse_endpoint(endpoint, &bus_cfg); + flags = bus_cfg.bus.parallel.flags; + + if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) + pdata->hs_polarity = 1; + + if (flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) + pdata->vs_polarity = 1; + + if (flags & V4L2_MBUS_PCLK_SAMPLE_RISING) + pdata->clk_polarity = 1; + +done: + of_node_put(endpoint); + return pdata; +} + /** * tvp514x_probe() - decoder driver i2c probe handler * @client: i2c driver client device structure @@ -1066,19 +1102,20 @@ static struct tvp514x_decoder tvp514x_dev = { static int tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct tvp514x_platform_data *pdata = tvp514x_get_pdata(client); struct tvp514x_decoder *decoder; struct v4l2_subdev *sd; int ret; + if (pdata == NULL) { + dev_err(&client->dev, "No platform data\n"); + return -EINVAL; + } + /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -EIO; - if (!client->dev.platform_data) { - v4l2_err(client, "No platform data!!\n"); - return -ENODEV; - } - decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL); if (!decoder) return -ENOMEM; @@ -1089,8 +1126,10 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id) memcpy(decoder->tvp514x_regs, tvp514x_reg_list_default, sizeof(tvp514x_reg_list_default)); + decoder->int_seq = (struct tvp514x_reg *)id->driver_data; + /* Copy board specific information here */ - decoder->pdata = client->dev.platform_data; + decoder->pdata = pdata; /** * Fetch platform specific data, and configure the @@ -1109,7 +1148,6 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id) /* Register with V4L2 layer as slave device */ sd = &decoder->sd; v4l2_i2c_subdev_init(sd, client, &tvp514x_ops); - strlcpy(sd->name, TVP514X_MODULE_NAME, sizeof(sd->name)); #if defined(CONFIG_MEDIA_CONTROLLER) decoder->pad.flags = MEDIA_PAD_FL_SOURCE; @@ -1120,7 +1158,6 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id) if (ret < 0) { v4l2_err(sd, "%s decoder driver failed to register !!\n", sd->name); - kfree(decoder); return ret; } #endif @@ -1231,8 +1268,20 @@ static const struct i2c_device_id tvp514x_id[] = { MODULE_DEVICE_TABLE(i2c, tvp514x_id); +#if IS_ENABLED(CONFIG_OF) +static const struct of_device_id tvp514x_of_match[] = { + { .compatible = "ti,tvp5146", }, + { .compatible = "ti,tvp5146m2", }, + { .compatible = "ti,tvp5147", }, + { .compatible = "ti,tvp5147m1", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, tvp514x_of_match); +#endif + static struct i2c_driver tvp514x_driver = { .driver = { + .of_match_table = of_match_ptr(tvp514x_of_match), .owner = THIS_MODULE, .name = TVP514X_MODULE_NAME, }, diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 485159a3c0b7..89c0b13463b7 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -12,7 +12,6 @@ #include <linux/module.h> #include <media/v4l2-device.h> #include <media/tvp5150.h> -#include <media/v4l2-chip-ident.h> #include <media/v4l2-ctrls.h> #include "tvp5150_reg.h" @@ -727,13 +726,11 @@ static int tvp5150_set_std(struct v4l2_subdev *sd, v4l2_std_id std) /* First tests should be against specific std */ - if (std == V4L2_STD_ALL) { - fmt = VIDEO_STD_AUTO_SWITCH_BIT; /* Autodetect mode */ - } else if (std & V4L2_STD_NTSC_443) { + if (std == V4L2_STD_NTSC_443) { fmt = VIDEO_STD_NTSC_4_43_BIT; - } else if (std & V4L2_STD_PAL_M) { + } else if (std == V4L2_STD_PAL_M) { fmt = VIDEO_STD_PAL_M_BIT; - } else if (std & (V4L2_STD_PAL_N | V4L2_STD_PAL_Nc)) { + } else if (std == V4L2_STD_PAL_N || std == V4L2_STD_PAL_Nc) { fmt = VIDEO_STD_PAL_COMBINATION_N_BIT; } else { /* Then, test against generic ones */ @@ -1031,31 +1028,11 @@ static int tvp5150_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f return 0; } -static int tvp5150_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - int rev; - struct i2c_client *client = v4l2_get_subdevdata(sd); - - rev = tvp5150_read(sd, TVP5150_ROM_MAJOR_VER) << 8 | - tvp5150_read(sd, TVP5150_ROM_MINOR_VER); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TVP5150, - rev); -} - - #ifdef CONFIG_VIDEO_ADV_DEBUG static int tvp5150_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { int res; - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; res = tvp5150_read(sd, reg->reg & 0xff); if (res < 0) { v4l2_err(sd, "%s: failed with error = %d\n", __func__, res); @@ -1069,12 +1046,6 @@ 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) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; tvp5150_write(sd, reg->reg & 0xff, reg->val & 0xff); return 0; } @@ -1098,7 +1069,6 @@ static const struct v4l2_subdev_core_ops tvp5150_core_ops = { .log_status = tvp5150_log_status, .s_std = tvp5150_s_std, .reset = tvp5150_reset, - .g_chip_ident = tvp5150_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = tvp5150_g_register, .s_register = tvp5150_s_register, @@ -1152,10 +1122,9 @@ static int tvp5150_probe(struct i2c_client *c, I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) return -EIO; - core = kzalloc(sizeof(struct tvp5150), GFP_KERNEL); - if (!core) { + core = devm_kzalloc(&c->dev, sizeof(*core), GFP_KERNEL); + if (!core) return -ENOMEM; - } sd = &core->sd; v4l2_i2c_subdev_init(sd, c, &tvp5150_ops); @@ -1166,7 +1135,7 @@ static int tvp5150_probe(struct i2c_client *c, for (i = 0; i < 4; i++) { res = tvp5150_read(sd, TVP5150_MSB_DEV_ID + i); if (res < 0) - goto free_core; + return res; tvp5150_id[i] = res; } @@ -1209,7 +1178,7 @@ static int tvp5150_probe(struct i2c_client *c, if (core->hdl.error) { res = core->hdl.error; v4l2_ctrl_handler_free(&core->hdl); - goto free_core; + return res; } v4l2_ctrl_handler_setup(&core->hdl); @@ -1225,10 +1194,6 @@ static int tvp5150_probe(struct i2c_client *c, if (debug > 1) tvp5150_log_status(sd); return 0; - -free_core: - kfree(core); - return res; } static int tvp5150_remove(struct i2c_client *c) @@ -1242,7 +1207,6 @@ static int tvp5150_remove(struct i2c_client *c) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&decoder->hdl); - kfree(to_tvp5150(sd)); return 0; } diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c index 027809cca5f5..a4e49483de6a 100644 --- a/drivers/media/i2c/tvp7002.c +++ b/drivers/media/i2c/tvp7002.c @@ -32,7 +32,6 @@ #include <linux/v4l2-dv-timings.h> #include <media/tvp7002.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> #include <media/v4l2-common.h> #include <media/v4l2-ctrls.h> #include "tvp7002_reg.h" @@ -41,9 +40,6 @@ MODULE_DESCRIPTION("TI TVP7002 Video and Graphics Digitizer driver"); MODULE_AUTHOR("Santiago Nunez-Corrales <santiago.nunez@ridgerun.com>"); MODULE_LICENSE("GPL"); -/* Module Name */ -#define TVP7002_MODULE_NAME "tvp7002" - /* I2C retry attempts */ #define I2C_RETRY_COUNT (5) @@ -424,6 +420,7 @@ struct tvp7002 { int streaming; const struct tvp7002_timings_definition *current_timings; + struct media_pad pad; }; /* @@ -535,29 +532,6 @@ static inline void tvp7002_write_err(struct v4l2_subdev *sd, u8 reg, } /* - * tvp7002_g_chip_ident() - Get chip identification number - * @sd: ptr to v4l2_subdev struct - * @chip: ptr to v4l2_dbg_chip_ident struct - * - * Obtains the chip's identification number. - * Returns zero or -EINVAL if read operation fails. - */ -static int tvp7002_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - u8 rev; - int error; - struct i2c_client *client = v4l2_get_subdevdata(sd); - - error = tvp7002_read(sd, TVP7002_CHIP_REV, &rev); - - if (error < 0) - return error; - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TVP7002, rev); -} - -/* * tvp7002_write_inittab() - Write initialization values * @sd: ptr to v4l2_subdev struct * @regs: ptr to i2c_reg_value struct @@ -738,23 +712,17 @@ static int tvp7002_query_dv_timings(struct v4l2_subdev *sd, * * Get the value of a TVP7002 decoder device register. * Returns zero when successful, -EINVAL if register read fails or - * access to I2C client fails, -EPERM if the call is not allowed - * by disabled CAP_SYS_ADMIN. + * access to I2C client fails. */ static int tvp7002_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); u8 val; int ret; - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - ret = tvp7002_read(sd, reg->reg & 0xff, &val); reg->val = val; + reg->size = 1; return ret; } @@ -764,19 +732,11 @@ static int tvp7002_g_register(struct v4l2_subdev *sd, * @reg: ptr to v4l2_dbg_register struct * * Get the value of a TVP7002 decoder device register. - * Returns zero when successful, -EINVAL if register read fails or - * -EPERM if call not allowed. + * Returns zero when successful, -EINVAL if register read fails. */ static int tvp7002_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - return tvp7002_write(sd, reg->reg & 0xff, reg->val & 0xff); } #endif @@ -880,9 +840,67 @@ static const struct v4l2_ctrl_ops tvp7002_ctrl_ops = { .s_ctrl = tvp7002_s_ctrl, }; +/* + * tvp7002_enum_mbus_code() - Enum supported digital video format on pad + * @sd: pointer to standard V4L2 sub-device structure + * @fh: file handle for the subdev + * @code: pointer to subdev enum mbus code struct + * + * Enumerate supported digital video formats for pad. + */ +static int +tvp7002_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_mbus_code_enum *code) +{ + /* Check requested format index is within range */ + if (code->index != 0) + return -EINVAL; + + code->code = V4L2_MBUS_FMT_YUYV10_1X20; + + return 0; +} + +/* + * tvp7002_get_pad_format() - get video format on pad + * @sd: pointer to standard V4L2 sub-device structure + * @fh: file handle for the subdev + * @fmt: pointer to subdev format struct + * + * get video format for pad. + */ +static int +tvp7002_get_pad_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_format *fmt) +{ + struct tvp7002 *tvp7002 = to_tvp7002(sd); + + fmt->format.code = V4L2_MBUS_FMT_YUYV10_1X20; + fmt->format.width = tvp7002->current_timings->timings.bt.width; + fmt->format.height = tvp7002->current_timings->timings.bt.height; + fmt->format.field = tvp7002->current_timings->scanmode; + fmt->format.colorspace = tvp7002->current_timings->color_space; + + return 0; +} + +/* + * tvp7002_set_pad_format() - set video format on pad + * @sd: pointer to standard V4L2 sub-device structure + * @fh: file handle for the subdev + * @fmt: pointer to subdev format struct + * + * set video format for pad. + */ +static int +tvp7002_set_pad_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_format *fmt) +{ + return tvp7002_get_pad_format(sd, fh, fmt); +} + /* V4L2 core operation handlers */ static const struct v4l2_subdev_core_ops tvp7002_core_ops = { - .g_chip_ident = tvp7002_g_chip_ident, .log_status = tvp7002_log_status, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, @@ -910,10 +928,18 @@ static const struct v4l2_subdev_video_ops tvp7002_video_ops = { .enum_mbus_fmt = tvp7002_enum_mbus_fmt, }; +/* media pad related operation handlers */ +static const struct v4l2_subdev_pad_ops tvp7002_pad_ops = { + .enum_mbus_code = tvp7002_enum_mbus_code, + .get_fmt = tvp7002_get_pad_format, + .set_fmt = tvp7002_set_pad_format, +}; + /* V4L2 top level operation handlers */ static const struct v4l2_subdev_ops tvp7002_ops = { .core = &tvp7002_core_ops, .video = &tvp7002_video_ops, + .pad = &tvp7002_pad_ops, }; /* @@ -993,19 +1019,34 @@ static int tvp7002_probe(struct i2c_client *c, const struct i2c_device_id *id) timings = device->current_timings->timings; error = tvp7002_s_dv_timings(sd, &timings); +#if defined(CONFIG_MEDIA_CONTROLLER) + device->pad.flags = MEDIA_PAD_FL_SOURCE; + device->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + device->sd.entity.flags |= MEDIA_ENT_T_V4L2_SUBDEV_DECODER; + + error = media_entity_init(&device->sd.entity, 1, &device->pad, 0); + if (error < 0) + return error; +#endif + v4l2_ctrl_handler_init(&device->hdl, 1); v4l2_ctrl_new_std(&device->hdl, &tvp7002_ctrl_ops, V4L2_CID_GAIN, 0, 255, 1, 0); sd->ctrl_handler = &device->hdl; if (device->hdl.error) { - int err = device->hdl.error; - - v4l2_ctrl_handler_free(&device->hdl); - return err; + error = device->hdl.error; + goto error; } v4l2_ctrl_handler_setup(&device->hdl); return 0; + +error: + v4l2_ctrl_handler_free(&device->hdl); +#if defined(CONFIG_MEDIA_CONTROLLER) + media_entity_cleanup(&device->sd.entity); +#endif + return error; } /* @@ -1022,7 +1063,9 @@ static int tvp7002_remove(struct i2c_client *c) v4l2_dbg(1, debug, sd, "Removing tvp7002 adapter" "on address 0x%x\n", c->addr); - +#if defined(CONFIG_MEDIA_CONTROLLER) + media_entity_cleanup(&device->sd.entity); +#endif v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&device->hdl); return 0; diff --git a/drivers/media/i2c/tw2804.c b/drivers/media/i2c/tw2804.c index c5dc2c3bf2d7..f58607df6193 100644 --- a/drivers/media/i2c/tw2804.c +++ b/drivers/media/i2c/tw2804.c @@ -23,7 +23,6 @@ #include <linux/slab.h> #include <media/v4l2-subdev.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> #include <media/v4l2-ctrls.h> #define TW2804_REG_AUTOGAIN 0x02 @@ -368,8 +367,7 @@ static int tw2804_probe(struct i2c_client *client, if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -ENODEV; - state = kzalloc(sizeof(struct tw2804), GFP_KERNEL); - + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (state == NULL) return -ENOMEM; sd = &state->sd; @@ -410,7 +408,6 @@ static int tw2804_probe(struct i2c_client *client, err = state->hdl.error; if (err) { v4l2_ctrl_handler_free(&state->hdl); - kfree(state); return err; } @@ -427,7 +424,6 @@ static int tw2804_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&state->hdl); - kfree(state); return 0; } diff --git a/drivers/media/i2c/tw9903.c b/drivers/media/i2c/tw9903.c index 87880b19d8c3..285b759a5f7f 100644 --- a/drivers/media/i2c/tw9903.c +++ b/drivers/media/i2c/tw9903.c @@ -215,7 +215,7 @@ static int tw9903_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%02x (%s)\n", client->addr << 1, client->adapter->name); - dec = kzalloc(sizeof(struct tw9903), GFP_KERNEL); + dec = devm_kzalloc(&client->dev, sizeof(*dec), GFP_KERNEL); if (dec == NULL) return -ENOMEM; sd = &dec->sd; @@ -233,7 +233,6 @@ static int tw9903_probe(struct i2c_client *client, int err = hdl->error; v4l2_ctrl_handler_free(hdl); - kfree(dec); return err; } @@ -242,7 +241,6 @@ static int tw9903_probe(struct i2c_client *client, if (write_regs(sd, initial_registers) < 0) { v4l2_err(client, "error initializing TW9903\n"); - kfree(dec); return -EINVAL; } @@ -255,7 +253,6 @@ static int tw9903_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&to_state(sd)->hdl); - kfree(to_state(sd)); return 0; } diff --git a/drivers/media/i2c/tw9906.c b/drivers/media/i2c/tw9906.c index accd79e5a7fd..f6bef25bd9ce 100644 --- a/drivers/media/i2c/tw9906.c +++ b/drivers/media/i2c/tw9906.c @@ -183,7 +183,7 @@ static int tw9906_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%02x (%s)\n", client->addr << 1, client->adapter->name); - dec = kzalloc(sizeof(struct tw9906), GFP_KERNEL); + dec = devm_kzalloc(&client->dev, sizeof(*dec), GFP_KERNEL); if (dec == NULL) return -ENOMEM; sd = &dec->sd; @@ -201,7 +201,6 @@ static int tw9906_probe(struct i2c_client *client, int err = hdl->error; v4l2_ctrl_handler_free(hdl); - kfree(dec); return err; } @@ -210,7 +209,6 @@ static int tw9906_probe(struct i2c_client *client, if (write_regs(sd, initial_registers) < 0) { v4l2_err(client, "error initializing TW9906\n"); - kfree(dec); return -EINVAL; } @@ -223,7 +221,6 @@ static int tw9906_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&to_state(sd)->hdl); - kfree(to_state(sd)); return 0; } diff --git a/drivers/media/i2c/uda1342.c b/drivers/media/i2c/uda1342.c index 3af408556d27..081786d176d0 100644 --- a/drivers/media/i2c/uda1342.c +++ b/drivers/media/i2c/uda1342.c @@ -69,7 +69,7 @@ static int uda1342_probe(struct i2c_client *client, dev_dbg(&client->dev, "initializing UDA1342 at address %d on %s\n", client->addr, adapter->name); - sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); + sd = devm_kzalloc(&client->dev, sizeof(*sd), GFP_KERNEL); if (sd == NULL) return -ENOMEM; @@ -89,7 +89,6 @@ static int uda1342_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); v4l2_device_unregister_subdev(sd); - kfree(sd); return 0; } diff --git a/drivers/media/i2c/upd64031a.c b/drivers/media/i2c/upd64031a.c index f0a09214c519..d248e6a12b8e 100644 --- a/drivers/media/i2c/upd64031a.c +++ b/drivers/media/i2c/upd64031a.c @@ -27,7 +27,6 @@ #include <linux/videodev2.h> #include <linux/slab.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> #include <media/upd64031a.h> /* --------------------- read registers functions define -------------------- */ @@ -147,13 +146,6 @@ static int upd64031a_s_routing(struct v4l2_subdev *sd, return upd64031a_s_frequency(sd, NULL); } -static int upd64031a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_UPD64031A, 0); -} - static int upd64031a_log_status(struct v4l2_subdev *sd) { v4l2_info(sd, "Status: SA00=0x%02x SA01=0x%02x\n", @@ -164,12 +156,6 @@ static int upd64031a_log_status(struct v4l2_subdev *sd) #ifdef CONFIG_VIDEO_ADV_DEBUG static int upd64031a_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; reg->val = upd64031a_read(sd, reg->reg & 0xff); reg->size = 1; return 0; @@ -177,12 +163,6 @@ static int upd64031a_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register static int upd64031a_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; upd64031a_write(sd, reg->reg & 0xff, reg->val & 0xff); return 0; } @@ -192,7 +172,6 @@ static int upd64031a_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_re static const struct v4l2_subdev_core_ops upd64031a_core_ops = { .log_status = upd64031a_log_status, - .g_chip_ident = upd64031a_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = upd64031a_g_register, .s_register = upd64031a_s_register, @@ -230,7 +209,7 @@ static int upd64031a_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - state = kzalloc(sizeof(struct upd64031a_state), GFP_KERNEL); + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (state == NULL) return -ENOMEM; sd = &state->sd; @@ -249,7 +228,6 @@ static int upd64031a_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); v4l2_device_unregister_subdev(sd); - kfree(to_state(sd)); return 0; } diff --git a/drivers/media/i2c/upd64083.c b/drivers/media/i2c/upd64083.c index 343e0215f74c..3a152ce7258a 100644 --- a/drivers/media/i2c/upd64083.c +++ b/drivers/media/i2c/upd64083.c @@ -27,7 +27,6 @@ #include <linux/videodev2.h> #include <linux/slab.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> #include <media/upd64083.h> MODULE_DESCRIPTION("uPD64083 driver"); @@ -122,12 +121,6 @@ static int upd64083_s_routing(struct v4l2_subdev *sd, #ifdef CONFIG_VIDEO_ADV_DEBUG static int upd64083_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; reg->val = upd64083_read(sd, reg->reg & 0xff); reg->size = 1; return 0; @@ -135,24 +128,11 @@ static int upd64083_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register static int upd64083_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; upd64083_write(sd, reg->reg & 0xff, reg->val & 0xff); return 0; } #endif -static int upd64083_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_UPD64083, 0); -} - static int upd64083_log_status(struct v4l2_subdev *sd) { struct i2c_client *client = v4l2_get_subdevdata(sd); @@ -169,7 +149,6 @@ static int upd64083_log_status(struct v4l2_subdev *sd) static const struct v4l2_subdev_core_ops upd64083_core_ops = { .log_status = upd64083_log_status, - .g_chip_ident = upd64083_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = upd64083_g_register, .s_register = upd64083_s_register, @@ -202,7 +181,7 @@ static int upd64083_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - state = kzalloc(sizeof(struct upd64083_state), GFP_KERNEL); + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (state == NULL) return -ENOMEM; sd = &state->sd; @@ -221,7 +200,6 @@ static int upd64083_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); v4l2_device_unregister_subdev(sd); - kfree(to_state(sd)); return 0; } diff --git a/drivers/media/i2c/vp27smpx.c b/drivers/media/i2c/vp27smpx.c index e71f139695af..6a3a3ff7ee6a 100644 --- a/drivers/media/i2c/vp27smpx.c +++ b/drivers/media/i2c/vp27smpx.c @@ -29,7 +29,6 @@ #include <linux/i2c.h> #include <linux/videodev2.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> MODULE_DESCRIPTION("vp27smpx driver"); MODULE_AUTHOR("Hans Verkuil"); @@ -112,13 +111,6 @@ static int vp27smpx_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) return 0; } -static int vp27smpx_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_VP27SMPX, 0); -} - static int vp27smpx_log_status(struct v4l2_subdev *sd) { struct vp27smpx_state *state = to_state(sd); @@ -132,7 +124,6 @@ static int vp27smpx_log_status(struct v4l2_subdev *sd) static const struct v4l2_subdev_core_ops vp27smpx_core_ops = { .log_status = vp27smpx_log_status, - .g_chip_ident = vp27smpx_g_chip_ident, .s_std = vp27smpx_s_std, }; @@ -169,7 +160,7 @@ static int vp27smpx_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - state = kzalloc(sizeof(struct vp27smpx_state), GFP_KERNEL); + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (state == NULL) return -ENOMEM; sd = &state->sd; @@ -186,7 +177,6 @@ static int vp27smpx_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); v4l2_device_unregister_subdev(sd); - kfree(to_state(sd)); return 0; } diff --git a/drivers/media/i2c/vpx3220.c b/drivers/media/i2c/vpx3220.c index 2f67b4c5c823..ece90df6a043 100644 --- a/drivers/media/i2c/vpx3220.c +++ b/drivers/media/i2c/vpx3220.c @@ -27,7 +27,6 @@ #include <linux/i2c.h> #include <linux/videodev2.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> #include <media/v4l2-ctrls.h> MODULE_DESCRIPTION("vpx3220a/vpx3216b/vpx3214c video decoder driver"); @@ -49,7 +48,6 @@ struct vpx3220 { unsigned char reg[255]; v4l2_std_id norm; - int ident; int input; int enable; }; @@ -297,7 +295,7 @@ static int vpx3220_init(struct v4l2_subdev *sd, u32 val) static int vpx3220_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pstd) { int res = V4L2_IN_ST_NO_SIGNAL, status; - v4l2_std_id std = 0; + v4l2_std_id std = pstd ? *pstd : V4L2_STD_ALL; status = vpx3220_fp_read(sd, 0x0f3); @@ -314,19 +312,21 @@ static int vpx3220_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pst case 0x10: case 0x14: case 0x18: - std = V4L2_STD_PAL; + std &= V4L2_STD_PAL; break; case 0x08: - std = V4L2_STD_SECAM; + std &= V4L2_STD_SECAM; break; case 0x04: case 0x0c: case 0x1c: - std = V4L2_STD_NTSC; + std &= V4L2_STD_NTSC; break; } + } else { + std = V4L2_STD_UNKNOWN; } if (pstd) *pstd = std; @@ -442,14 +442,6 @@ static int vpx3220_s_ctrl(struct v4l2_ctrl *ctrl) return -EINVAL; } -static int vpx3220_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct vpx3220 *decoder = to_vpx3220(sd); - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, decoder->ident, 0); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_ctrl_ops vpx3220_ctrl_ops = { @@ -457,7 +449,6 @@ static const struct v4l2_ctrl_ops vpx3220_ctrl_ops = { }; static const struct v4l2_subdev_core_ops vpx3220_core_ops = { - .g_chip_ident = vpx3220_g_chip_ident, .init = vpx3220_init, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, @@ -499,7 +490,7 @@ static int vpx3220_probe(struct i2c_client *client, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) return -ENODEV; - decoder = kzalloc(sizeof(struct vpx3220), GFP_KERNEL); + decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL); if (decoder == NULL) return -ENOMEM; sd = &decoder->sd; @@ -521,7 +512,6 @@ static int vpx3220_probe(struct i2c_client *client, int err = decoder->hdl.error; v4l2_ctrl_handler_free(&decoder->hdl); - kfree(decoder); return err; } v4l2_ctrl_handler_setup(&decoder->hdl); @@ -529,7 +519,6 @@ static int vpx3220_probe(struct i2c_client *client, ver = i2c_smbus_read_byte_data(client, 0x00); pn = (i2c_smbus_read_byte_data(client, 0x02) << 8) + i2c_smbus_read_byte_data(client, 0x01); - decoder->ident = V4L2_IDENT_VPX3220A; if (ver == 0xec) { switch (pn) { case 0x4680: @@ -537,11 +526,9 @@ static int vpx3220_probe(struct i2c_client *client, break; case 0x4260: name = "vpx3216b"; - decoder->ident = V4L2_IDENT_VPX3216B; break; case 0x4280: name = "vpx3214c"; - decoder->ident = V4L2_IDENT_VPX3214C; break; } } @@ -566,7 +553,7 @@ static int vpx3220_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&decoder->hdl); - kfree(decoder); + return 0; } diff --git a/drivers/media/i2c/vs6624.c b/drivers/media/i2c/vs6624.c index f366fad6269e..25bdd9312fea 100644 --- a/drivers/media/i2c/vs6624.c +++ b/drivers/media/i2c/vs6624.c @@ -27,7 +27,6 @@ #include <linux/types.h> #include <linux/videodev2.h> -#include <media/v4l2-chip-ident.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-mediabus.h> @@ -722,27 +721,9 @@ static int vs6624_s_stream(struct v4l2_subdev *sd, int enable) return 0; } -static int vs6624_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - int rev; - struct i2c_client *client = v4l2_get_subdevdata(sd); - - rev = (vs6624_read(sd, VS6624_FW_VSN_MAJOR) << 8) - | vs6624_read(sd, VS6624_FW_VSN_MINOR); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_VS6624, rev); -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int vs6624_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; reg->val = vs6624_read(sd, reg->reg & 0xffff); reg->size = 1; return 0; @@ -750,12 +731,6 @@ static int vs6624_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *r static int vs6624_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) { - struct i2c_client *client = v4l2_get_subdevdata(sd); - - if (!v4l2_chip_match_i2c_client(client, ®->match)) - return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; vs6624_write(sd, reg->reg & 0xffff, reg->val & 0xff); return 0; } @@ -766,7 +741,6 @@ static const struct v4l2_ctrl_ops vs6624_ctrl_ops = { }; static const struct v4l2_subdev_core_ops vs6624_core_ops = { - .g_chip_ident = vs6624_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = vs6624_g_register, .s_register = vs6624_s_register, @@ -805,20 +779,18 @@ static int vs6624_probe(struct i2c_client *client, if (ce == NULL) return -EINVAL; - ret = gpio_request(*ce, "VS6624 Chip Enable"); + ret = devm_gpio_request_one(&client->dev, *ce, GPIOF_OUT_INIT_HIGH, + "VS6624 Chip Enable"); if (ret) { v4l_err(client, "failed to request GPIO %d\n", *ce); return ret; } - gpio_direction_output(*ce, 1); /* wait 100ms before any further i2c writes are performed */ mdelay(100); - sensor = kzalloc(sizeof(*sensor), GFP_KERNEL); - if (sensor == NULL) { - gpio_free(*ce); + sensor = devm_kzalloc(&client->dev, sizeof(*sensor), GFP_KERNEL); + if (sensor == NULL) return -ENOMEM; - } sd = &sensor->sd; v4l2_i2c_subdev_init(sd, client, &vs6624_ops); @@ -866,30 +838,22 @@ static int vs6624_probe(struct i2c_client *client, int err = hdl->error; v4l2_ctrl_handler_free(hdl); - kfree(sensor); - gpio_free(*ce); return err; } /* initialize the hardware to the default control values */ ret = v4l2_ctrl_handler_setup(hdl); - if (ret) { + if (ret) v4l2_ctrl_handler_free(hdl); - kfree(sensor); - gpio_free(*ce); - } return ret; } static int vs6624_remove(struct i2c_client *client) { struct v4l2_subdev *sd = i2c_get_clientdata(client); - struct vs6624 *sensor = to_vs6624(sd); v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(sd->ctrl_handler); - gpio_free(sensor->ce_pin); - kfree(sensor); return 0; } diff --git a/drivers/media/i2c/wm8739.c b/drivers/media/i2c/wm8739.c index 3bb99e93febe..3be73f6a40e9 100644 --- a/drivers/media/i2c/wm8739.c +++ b/drivers/media/i2c/wm8739.c @@ -29,7 +29,6 @@ #include <linux/i2c.h> #include <linux/videodev2.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> #include <media/v4l2-ctrls.h> MODULE_DESCRIPTION("wm8739 driver"); @@ -160,13 +159,6 @@ static int wm8739_s_clock_freq(struct v4l2_subdev *sd, u32 audiofreq) return 0; } -static int wm8739_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_WM8739, 0); -} - static int wm8739_log_status(struct v4l2_subdev *sd) { struct wm8739_state *state = to_state(sd); @@ -184,7 +176,6 @@ static const struct v4l2_ctrl_ops wm8739_ctrl_ops = { static const struct v4l2_subdev_core_ops wm8739_core_ops = { .log_status = wm8739_log_status, - .g_chip_ident = wm8739_g_chip_ident, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, @@ -220,7 +211,7 @@ static int wm8739_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%x (%s)\n", client->addr << 1, client->adapter->name); - state = kzalloc(sizeof(struct wm8739_state), GFP_KERNEL); + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (state == NULL) return -ENOMEM; sd = &state->sd; @@ -237,7 +228,6 @@ static int wm8739_probe(struct i2c_client *client, int err = state->hdl.error; v4l2_ctrl_handler_free(&state->hdl); - kfree(state); return err; } v4l2_ctrl_cluster(3, &state->volume); @@ -271,7 +261,6 @@ static int wm8739_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&state->hdl); - kfree(to_state(sd)); return 0; } diff --git a/drivers/media/i2c/wm8775.c b/drivers/media/i2c/wm8775.c index 27c27b4ae238..3f584a7d0781 100644 --- a/drivers/media/i2c/wm8775.c +++ b/drivers/media/i2c/wm8775.c @@ -33,7 +33,6 @@ #include <linux/i2c.h> #include <linux/videodev2.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> #include <media/v4l2-ctrls.h> #include <media/wm8775.h> @@ -158,13 +157,6 @@ static int wm8775_s_ctrl(struct v4l2_ctrl *ctrl) return -EINVAL; } -static int wm8775_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_WM8775, 0); -} - static int wm8775_log_status(struct v4l2_subdev *sd) { struct wm8775_state *state = to_state(sd); @@ -188,7 +180,6 @@ static const struct v4l2_ctrl_ops wm8775_ctrl_ops = { static const struct v4l2_subdev_core_ops wm8775_core_ops = { .log_status = wm8775_log_status, - .g_chip_ident = wm8775_g_chip_ident, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, @@ -241,7 +232,7 @@ static int wm8775_probe(struct i2c_client *client, v4l_info(client, "chip found @ 0x%02x (%s)\n", client->addr << 1, client->adapter->name); - state = kzalloc(sizeof(struct wm8775_state), GFP_KERNEL); + state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL); if (state == NULL) return -ENOMEM; sd = &state->sd; @@ -261,7 +252,6 @@ static int wm8775_probe(struct i2c_client *client, err = state->hdl.error; if (err) { v4l2_ctrl_handler_free(&state->hdl); - kfree(state); return err; } @@ -319,7 +309,6 @@ static int wm8775_remove(struct i2c_client *client) v4l2_device_unregister_subdev(sd); v4l2_ctrl_handler_free(&state->hdl); - kfree(state); return 0; } diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c index 1957c0df08fd..d5a7a135f75d 100644 --- a/drivers/media/media-device.c +++ b/drivers/media/media-device.c @@ -142,6 +142,8 @@ static long __media_device_enum_links(struct media_device *mdev, for (p = 0; p < entity->num_pads; p++) { struct media_pad_desc pad; + + memset(&pad, 0, sizeof(pad)); media_device_kpad_to_upad(&entity->pads[p], &pad); if (copy_to_user(&links->pads[p], &pad, sizeof(pad))) return -EFAULT; @@ -159,6 +161,7 @@ static long __media_device_enum_links(struct media_device *mdev, if (entity->links[l].source->entity != entity) continue; + memset(&link, 0, sizeof(link)); media_device_kpad_to_upad(entity->links[l].source, &link.source); media_device_kpad_to_upad(entity->links[l].sink, diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c index e1cd13283407..cb30ffbd5ba8 100644 --- a/drivers/media/media-entity.c +++ b/drivers/media/media-entity.c @@ -429,6 +429,56 @@ media_entity_create_link(struct media_entity *source, u16 source_pad, } EXPORT_SYMBOL_GPL(media_entity_create_link); +void __media_entity_remove_links(struct media_entity *entity) +{ + unsigned int i; + + for (i = 0; i < entity->num_links; i++) { + struct media_link *link = &entity->links[i]; + struct media_entity *remote; + unsigned int r = 0; + + if (link->source->entity == entity) + remote = link->sink->entity; + else + remote = link->source->entity; + + while (r < remote->num_links) { + struct media_link *rlink = &remote->links[r]; + + if (rlink != link->reverse) { + r++; + continue; + } + + if (link->source->entity == entity) + remote->num_backlinks--; + + if (--remote->num_links == 0) + break; + + /* Insert last entry in place of the dropped link. */ + *rlink = remote->links[remote->num_links]; + } + } + + entity->num_links = 0; + entity->num_backlinks = 0; +} +EXPORT_SYMBOL_GPL(__media_entity_remove_links); + +void media_entity_remove_links(struct media_entity *entity) +{ + /* Do nothing if the entity is not registered. */ + if (entity->parent == NULL) + return; + + mutex_lock(&entity->parent->graph_mutex); + __media_entity_remove_links(entity); + mutex_unlock(&entity->parent->graph_mutex); +} +EXPORT_SYMBOL_GPL(media_entity_remove_links); + static int __media_entity_setup_link_notify(struct media_link *link, u32 flags) { int ret; @@ -496,25 +546,17 @@ int __media_entity_setup_link(struct media_link *link, u32 flags) mdev = source->parent; - if ((flags & MEDIA_LNK_FL_ENABLED) && mdev->link_notify) { - ret = mdev->link_notify(link->source, link->sink, - MEDIA_LNK_FL_ENABLED); + if (mdev->link_notify) { + ret = mdev->link_notify(link, flags, + MEDIA_DEV_NOTIFY_PRE_LINK_CH); if (ret < 0) return ret; } ret = __media_entity_setup_link_notify(link, flags); - if (ret < 0) - goto err; - - if (!(flags & MEDIA_LNK_FL_ENABLED) && mdev->link_notify) - mdev->link_notify(link->source, link->sink, 0); - - return 0; -err: - if ((flags & MEDIA_LNK_FL_ENABLED) && mdev->link_notify) - mdev->link_notify(link->source, link->sink, 0); + if (mdev->link_notify) + mdev->link_notify(link, flags, MEDIA_DEV_NOTIFY_POST_LINK_CH); return ret; } @@ -560,17 +602,16 @@ media_entity_find_link(struct media_pad *source, struct media_pad *sink) EXPORT_SYMBOL_GPL(media_entity_find_link); /** - * media_entity_remote_source - Find the source pad at the remote end of a link - * @pad: Sink pad at the local end of the link + * media_entity_remote_pad - Find the pad at the remote end of a link + * @pad: Pad at the local end of the link * - * Search for a remote source pad connected to the given sink pad by iterating - * over all links originating or terminating at that pad until an enabled link - * is found. + * Search for a remote pad connected to the given pad by iterating over all + * links originating or terminating at that pad until an enabled link is found. * * Return a pointer to the pad at the remote end of the first found enabled * link, or NULL if no enabled link has been found. */ -struct media_pad *media_entity_remote_source(struct media_pad *pad) +struct media_pad *media_entity_remote_pad(struct media_pad *pad) { unsigned int i; @@ -590,4 +631,4 @@ struct media_pad *media_entity_remote_source(struct media_pad *pad) return NULL; } -EXPORT_SYMBOL_GPL(media_entity_remote_source); +EXPORT_SYMBOL_GPL(media_entity_remote_pad); diff --git a/drivers/media/parport/bw-qcam.c b/drivers/media/parport/bw-qcam.c index 06231b85e1a9..d12bd33f39cb 100644 --- a/drivers/media/parport/bw-qcam.c +++ b/drivers/media/parport/bw-qcam.c @@ -687,6 +687,7 @@ static int buffer_finish(struct vb2_buffer *vb) parport_release(qcam->pdev); mutex_unlock(&qcam->lock); + v4l2_get_timestamp(&vb->v4l2_buf.timestamp); if (len != size) vb->state = VB2_BUF_STATE_ERROR; vb2_set_plane_payload(vb, 0, len); @@ -964,6 +965,7 @@ static struct qcam *qcam_init(struct parport *port) q->drv_priv = qcam; q->ops = &qcam_video_qops; q->mem_ops = &vb2_vmalloc_memops; + q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; err = vb2_queue_init(q); if (err < 0) { v4l2_err(v4l2_dev, "couldn't init vb2_queue for %s.\n", port->name); diff --git a/drivers/media/pci/Kconfig b/drivers/media/pci/Kconfig index d4e2ed3f27e5..53196f1366f3 100644 --- a/drivers/media/pci/Kconfig +++ b/drivers/media/pci/Kconfig @@ -1,6 +1,7 @@ +if PCI && MEDIA_SUPPORT + menuconfig MEDIA_PCI_SUPPORT bool "Media PCI Adapters" - depends on PCI && MEDIA_SUPPORT help Enable media drivers for PCI/PCIe bus. If you have such devices, say Y. @@ -45,3 +46,4 @@ source "drivers/media/pci/ddbridge/Kconfig" endif endif #MEDIA_PCI_SUPPORT +endif #PCI diff --git a/drivers/media/pci/b2c2/flexcop-pci.c b/drivers/media/pci/b2c2/flexcop-pci.c index 44f8fb5f17ff..447afbd904a4 100644 --- a/drivers/media/pci/b2c2/flexcop-pci.c +++ b/drivers/media/pci/b2c2/flexcop-pci.c @@ -432,18 +432,7 @@ static struct pci_driver flexcop_pci_driver = { .remove = flexcop_pci_remove, }; -static int __init flexcop_pci_module_init(void) -{ - return pci_register_driver(&flexcop_pci_driver); -} - -static void __exit flexcop_pci_module_exit(void) -{ - pci_unregister_driver(&flexcop_pci_driver); -} - -module_init(flexcop_pci_module_init); -module_exit(flexcop_pci_module_exit); +module_pci_driver(flexcop_pci_driver); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_NAME); diff --git a/drivers/media/pci/bt8xx/bttv-cards.c b/drivers/media/pci/bt8xx/bttv-cards.c index b7dc921e1b91..e564aac0aa30 100644 --- a/drivers/media/pci/bt8xx/bttv-cards.c +++ b/drivers/media/pci/bt8xx/bttv-cards.c @@ -131,7 +131,7 @@ MODULE_PARM_DESC(vsfx,"set VSFX pci config bit " "[yet another chipset flaw workaround]"); MODULE_PARM_DESC(latency,"pci latency timer"); MODULE_PARM_DESC(card,"specify TV/grabber card model, see CARDLIST file for a list"); -MODULE_PARM_DESC(pll,"specify installed crystal (0=none, 28=28 MHz, 35=35 MHz)"); +MODULE_PARM_DESC(pll, "specify installed crystal (0=none, 28=28 MHz, 35=35 MHz, 14=14 MHz)"); MODULE_PARM_DESC(tuner,"specify installed tuner type"); MODULE_PARM_DESC(autoload, "obsolete option, please do not use anymore"); MODULE_PARM_DESC(audiodev, "specify audio device:\n" @@ -2705,7 +2705,7 @@ struct tvcard bttv_tvcards[] = { .has_radio = 1, .has_remote = 1, }, - [BTTV_BOARD_VD012] = { + [BTTV_BOARD_VD012] = { /* D.Heer@Phytec.de */ .name = "PHYTEC VD-012 (bt878)", .video_inputs = 4, @@ -2718,7 +2718,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, }, - [BTTV_BOARD_VD012_X1] = { + [BTTV_BOARD_VD012_X1] = { /* D.Heer@Phytec.de */ .name = "PHYTEC VD-012-X1 (bt878)", .video_inputs = 4, @@ -2731,7 +2731,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, }, - [BTTV_BOARD_VD012_X2] = { + [BTTV_BOARD_VD012_X2] = { /* D.Heer@Phytec.de */ .name = "PHYTEC VD-012-X2 (bt878)", .video_inputs = 4, @@ -2744,7 +2744,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, }, - [BTTV_BOARD_GEOVISION_GV800S] = { + [BTTV_BOARD_GEOVISION_GV800S] = { /* Bruno Christo <bchristo@inf.ufsm.br> * * GeoVision GV-800(S) has 4 Conexant Fusion 878A: @@ -2771,7 +2771,7 @@ struct tvcard bttv_tvcards[] = { .no_tda7432 = 1, .muxsel_hook = gv800s_muxsel, }, - [BTTV_BOARD_GEOVISION_GV800S_SL] = { + [BTTV_BOARD_GEOVISION_GV800S_SL] = { /* Bruno Christo <bchristo@inf.ufsm.br> * * GeoVision GV-800(S) has 4 Conexant Fusion 878A: @@ -2808,6 +2808,7 @@ struct tvcard bttv_tvcards[] = { .tuner_type = TUNER_ABSENT, .tuner_addr = ADDR_UNSET, }, + /* ---- card 0xa0---------------------------------- */ [BTTV_BOARD_TVT_TD3116] = { .name = "Tongwei Video Technology TD-3116", .video_inputs = 16, @@ -2825,6 +2826,35 @@ struct tvcard bttv_tvcards[] = { .muxsel = MUXSEL(2, 3, 1, 0), .tuner_type = TUNER_ABSENT, }, + [BTTV_BOARD_ADLINK_MPG24] = { + /* Adlink MPG24 */ + .name = "Adlink MPG24", + .video_inputs = 1, + /* .audio_inputs= 1, */ + .svhs = NO_SVHS, + .muxsel = MUXSEL(2, 2, 2, 2), + .tuner_type = UNSET, + .tuner_addr = ADDR_UNSET, + .pll = PLL_28, + }, + [BTTV_BOARD_BT848_CAP_14] = { + .name = "Bt848 Capture 14MHz", + .video_inputs = 4, + .svhs = 2, + .muxsel = MUXSEL(2, 3, 1, 0), + .pll = PLL_14, + .tuner_type = TUNER_ABSENT, + }, + [BTTV_BOARD_CYBERVISION_CV06] = { + .name = "CyberVision CV06 (SV)", + .video_inputs = 4, + /* .audio_inputs= 0, */ + .svhs = NO_SVHS, + .muxsel = MUXSEL(2, 3, 1, 0), + .pll = PLL_28, + .tuner_type = TUNER_ABSENT, + .tuner_addr = ADDR_UNSET, + }, }; @@ -3390,6 +3420,10 @@ void bttv_init_card2(struct bttv *btv) btv->pll.pll_ifreq=35468950; btv->pll.pll_crystal=BT848_IFORM_XT1; } + if (PLL_14 == bttv_tvcards[btv->c.type].pll) { + btv->pll.pll_ifreq = 14318181; + btv->pll.pll_crystal = BT848_IFORM_XT0; + } /* insmod options can override */ switch (pll[btv->c.nr]) { case 0: /* none */ @@ -3409,6 +3443,12 @@ void bttv_init_card2(struct bttv *btv) btv->pll.pll_ofreq = 0; btv->pll.pll_crystal = BT848_IFORM_XT1; break; + case 3: /* 14 MHz */ + case 14: + btv->pll.pll_ifreq = 14318181; + btv->pll.pll_ofreq = 0; + btv->pll.pll_crystal = BT848_IFORM_XT0; + break; } } btv->pll.pll_current = -1; diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c index e7d088413411..c6532de0eac7 100644 --- a/drivers/media/pci/bt8xx/bttv-driver.c +++ b/drivers/media/pci/bt8xx/bttv-driver.c @@ -50,7 +50,6 @@ #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-event.h> -#include <media/v4l2-chip-ident.h> #include <media/tvaudio.h> #include <media/msp3400.h> @@ -1761,9 +1760,9 @@ static int bttv_querystd(struct file *file, void *f, v4l2_std_id *id) struct bttv *btv = fh->btv; if (btread(BT848_DSTATUS) & BT848_DSTATUS_NUML) - *id = V4L2_STD_625_50; + *id &= V4L2_STD_625_50; else - *id = V4L2_STD_525_60; + *id &= V4L2_STD_525_60; return 0; } @@ -1907,28 +1906,6 @@ static int bttv_log_status(struct file *file, void *f) return 0; } -static int bttv_g_chip_ident(struct file *file, void *f, struct v4l2_dbg_chip_ident *chip) -{ - struct bttv_fh *fh = f; - struct bttv *btv = fh->btv; - - chip->ident = V4L2_IDENT_NONE; - chip->revision = 0; - if (chip->match.type == V4L2_CHIP_MATCH_HOST) { - if (v4l2_chip_match_host(&chip->match)) { - chip->ident = btv->id; - if (chip->ident == PCI_DEVICE_ID_FUSION879) - chip->ident = V4L2_IDENT_BT879; - } - return 0; - } - if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER && - chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR) - return -EINVAL; - /* TODO: is this correct? */ - return bttv_call_all_err(btv, core, g_chip_ident, chip); -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int bttv_g_register(struct file *file, void *f, struct v4l2_dbg_register *reg) @@ -1936,16 +1913,6 @@ static int bttv_g_register(struct file *file, void *f, struct bttv_fh *fh = f; struct bttv *btv = fh->btv; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - if (!v4l2_chip_match_host(®->match)) { - /* TODO: subdev errors should not be ignored, this should become a - subdev helper function. */ - bttv_call_all(btv, core, g_register, reg); - return 0; - } - /* bt848 has a 12-bit register space */ reg->reg &= 0xfff; reg->val = btread(reg->reg); @@ -1960,16 +1927,6 @@ static int bttv_s_register(struct file *file, void *f, struct bttv_fh *fh = f; struct bttv *btv = fh->btv; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - if (!v4l2_chip_match_host(®->match)) { - /* TODO: subdev errors should not be ignored, this should become a - subdev helper function. */ - bttv_call_all(btv, core, s_register, reg); - return 0; - } - /* bt848 has a 12-bit register space */ btwrite(reg->val, reg->reg & 0xfff); @@ -3209,7 +3166,6 @@ static const struct v4l2_ioctl_ops bttv_ioctl_ops = { .vidioc_querystd = bttv_querystd, .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, - .vidioc_g_chip_ident = bttv_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = bttv_g_register, .vidioc_s_register = bttv_s_register, diff --git a/drivers/media/pci/bt8xx/bttv.h b/drivers/media/pci/bt8xx/bttv.h index 6139ce26dc2c..df578efe03c9 100644 --- a/drivers/media/pci/bt8xx/bttv.h +++ b/drivers/media/pci/bt8xx/bttv.h @@ -185,6 +185,9 @@ #define BTTV_BOARD_PV183 0x9f #define BTTV_BOARD_TVT_TD3116 0xa0 #define BTTV_BOARD_APOSONIC_WDVR 0xa1 +#define BTTV_BOARD_ADLINK_MPG24 0xa2 +#define BTTV_BOARD_BT848_CAP_14 0xa3 +#define BTTV_BOARD_CYBERVISION_CV06 0xa4 /* more card-specific defines */ #define PT2254_L_CHANNEL 0x10 @@ -232,6 +235,7 @@ struct tvcard { #define PLL_NONE 0 #define PLL_28 1 #define PLL_35 2 +#define PLL_14 3 /* i2c audio flags */ unsigned int no_msp34xx:1; diff --git a/drivers/media/pci/cx18/cx18-av-core.c b/drivers/media/pci/cx18/cx18-av-core.c index 38b1d64ffc27..c4890a430dc6 100644 --- a/drivers/media/pci/cx18/cx18-av-core.c +++ b/drivers/media/pci/cx18/cx18-av-core.c @@ -22,7 +22,6 @@ * 02110-1301, USA. */ -#include <media/v4l2-chip-ident.h> #include "cx18-driver.h" #include "cx18-io.h" #include "cx18-cards.h" @@ -1231,35 +1230,14 @@ static int cx18_av_log_status(struct v4l2_subdev *sd) return 0; } -static inline int cx18_av_dbg_match(const struct v4l2_dbg_match *match) -{ - return match->type == V4L2_CHIP_MATCH_HOST && match->addr == 1; -} - -static int cx18_av_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - struct cx18_av_state *state = to_cx18_av_state(sd); - - if (cx18_av_dbg_match(&chip->match)) { - chip->ident = state->id; - chip->revision = state->rev; - } - return 0; -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int cx18_av_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) { struct cx18 *cx = v4l2_get_subdevdata(sd); - if (!cx18_av_dbg_match(®->match)) - return -EINVAL; if ((reg->reg & 0x3) != 0) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; reg->size = 4; reg->val = cx18_av_read4(cx, reg->reg & 0x00000ffc); return 0; @@ -1270,12 +1248,8 @@ static int cx18_av_s_register(struct v4l2_subdev *sd, { struct cx18 *cx = v4l2_get_subdevdata(sd); - if (!cx18_av_dbg_match(®->match)) - return -EINVAL; if ((reg->reg & 0x3) != 0) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; cx18_av_write4(cx, reg->reg & 0x00000ffc, reg->val); return 0; } @@ -1286,17 +1260,9 @@ static const struct v4l2_ctrl_ops cx18_av_ctrl_ops = { }; static const struct v4l2_subdev_core_ops cx18_av_general_ops = { - .g_chip_ident = cx18_av_g_chip_ident, .log_status = cx18_av_log_status, .load_fw = cx18_av_load_fw, .reset = cx18_av_reset, - .g_ctrl = v4l2_subdev_g_ctrl, - .s_ctrl = v4l2_subdev_s_ctrl, - .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, - .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, - .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, - .queryctrl = v4l2_subdev_queryctrl, - .querymenu = v4l2_subdev_querymenu, .s_std = cx18_av_s_std, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = cx18_av_g_register, @@ -1344,8 +1310,6 @@ int cx18_av_probe(struct cx18 *cx) int err; state->rev = cx18_av_read4(cx, CXADEC_CHIP_CTRL) & 0xffff; - state->id = ((state->rev >> 4) == CXADEC_CHIP_TYPE_MAKO) - ? V4L2_IDENT_CX23418_843 : V4L2_IDENT_UNKNOWN; state->vid_input = CX18_AV_COMPOSITE7; state->aud_input = CX18_AV_AUDIO8; diff --git a/drivers/media/pci/cx18/cx18-av-core.h b/drivers/media/pci/cx18/cx18-av-core.h index e9c69d9c9e4a..4c559e86e340 100644 --- a/drivers/media/pci/cx18/cx18-av-core.h +++ b/drivers/media/pci/cx18/cx18-av-core.h @@ -104,7 +104,6 @@ struct cx18_av_state { enum cx18_av_audio_input aud_input; u32 audclk_freq; int audmode; - u32 id; u32 rev; int is_initialized; diff --git a/drivers/media/pci/cx18/cx18-ioctl.c b/drivers/media/pci/cx18/cx18-ioctl.c index aee7b6dacbfe..1110bcb14e2f 100644 --- a/drivers/media/pci/cx18/cx18-ioctl.c +++ b/drivers/media/pci/cx18/cx18-ioctl.c @@ -39,7 +39,6 @@ #include "cx18-cards.h" #include "cx18-av-core.h" #include <media/tveeprom.h> -#include <media/v4l2-chip-ident.h> u16 cx18_service2vbi(int type) { @@ -362,73 +361,18 @@ static int cx18_s_fmt_sliced_vbi_cap(struct file *file, void *fh, return 0; } -static int cx18_g_chip_ident(struct file *file, void *fh, - struct v4l2_dbg_chip_ident *chip) -{ - struct cx18 *cx = fh2id(fh)->cx; - int err = 0; - - chip->ident = V4L2_IDENT_NONE; - chip->revision = 0; - switch (chip->match.type) { - case V4L2_CHIP_MATCH_HOST: - switch (chip->match.addr) { - case 0: - chip->ident = V4L2_IDENT_CX23418; - chip->revision = cx18_read_reg(cx, 0xC72028); - break; - case 1: - /* - * The A/V decoder is always present, but in the rare - * case that the card doesn't have analog, we don't - * use it. We find it w/o using the cx->sd_av pointer - */ - cx18_call_hw(cx, CX18_HW_418_AV, - core, g_chip_ident, chip); - break; - default: - /* - * Could return ident = V4L2_IDENT_UNKNOWN if we had - * other host chips at higher addresses, but we don't - */ - err = -EINVAL; /* per V4L2 spec */ - break; - } - break; - case V4L2_CHIP_MATCH_I2C_DRIVER: - /* If needed, returns V4L2_IDENT_AMBIGUOUS without extra work */ - cx18_call_all(cx, core, g_chip_ident, chip); - break; - case V4L2_CHIP_MATCH_I2C_ADDR: - /* - * We could return V4L2_IDENT_UNKNOWN, but we don't do the work - * to look if a chip is at the address with no driver. That's a - * dangerous thing to do with EEPROMs anyway. - */ - cx18_call_all(cx, core, g_chip_ident, chip); - break; - default: - err = -EINVAL; - break; - } - return err; -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int cx18_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg) { struct cx18 *cx = fh2id(fh)->cx; - if (v4l2_chip_match_host(®->match)) { - if (reg->reg >= CX18_MEM_OFFSET + CX18_MEM_SIZE) - return -EINVAL; - reg->size = 4; - reg->val = cx18_read_enc(cx, reg->reg); - return 0; - } - /* FIXME - errors shouldn't be ignored */ - cx18_call_all(cx, core, g_register, reg); + if (reg->reg & 0x3) + return -EINVAL; + if (reg->reg >= CX18_MEM_OFFSET + CX18_MEM_SIZE) + return -EINVAL; + reg->size = 4; + reg->val = cx18_read_enc(cx, reg->reg); return 0; } @@ -437,14 +381,11 @@ static int cx18_s_register(struct file *file, void *fh, { struct cx18 *cx = fh2id(fh)->cx; - if (v4l2_chip_match_host(®->match)) { - if (reg->reg >= CX18_MEM_OFFSET + CX18_MEM_SIZE) - return -EINVAL; - cx18_write_enc(cx, reg->val, reg->reg); - return 0; - } - /* FIXME - errors shouldn't be ignored */ - cx18_call_all(cx, core, s_register, reg); + if (reg->reg & 0x3) + return -EINVAL; + if (reg->reg >= CX18_MEM_OFFSET + CX18_MEM_SIZE) + return -EINVAL; + cx18_write_enc(cx, reg->val, reg->reg); return 0; } #endif @@ -1162,7 +1103,6 @@ static const struct v4l2_ioctl_ops cx18_ioctl_ops = { .vidioc_try_fmt_vbi_cap = cx18_try_fmt_vbi_cap, .vidioc_try_fmt_sliced_vbi_cap = cx18_try_fmt_sliced_vbi_cap, .vidioc_g_sliced_vbi_cap = cx18_g_sliced_vbi_cap, - .vidioc_g_chip_ident = cx18_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = cx18_g_register, .vidioc_s_register = cx18_s_register, diff --git a/drivers/media/pci/cx23885/cx23885-417.c b/drivers/media/pci/cx23885/cx23885-417.c index 6dea11a7a858..e3fc2c71808a 100644 --- a/drivers/media/pci/cx23885/cx23885-417.c +++ b/drivers/media/pci/cx23885/cx23885-417.c @@ -1217,8 +1217,7 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) struct cx23885_fh *fh = file->private_data; struct cx23885_dev *dev = fh->dev; - call_all(dev, core, g_std, id); - + *id = dev->tvnorm; return 0; } @@ -1661,7 +1660,6 @@ static struct v4l2_file_operations mpeg_fops = { }; static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { - .vidioc_querystd = vidioc_g_std, .vidioc_g_std = vidioc_g_std, .vidioc_s_std = vidioc_s_std, .vidioc_enum_input = vidioc_enum_input, @@ -1690,8 +1688,8 @@ static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { .vidioc_log_status = vidioc_log_status, .vidioc_querymenu = vidioc_querymenu, .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_g_chip_ident = cx23885_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_chip_info = cx23885_g_chip_info, .vidioc_g_register = cx23885_g_register, .vidioc_s_register = cx23885_s_register, #endif @@ -1702,7 +1700,6 @@ static struct video_device cx23885_mpeg_template = { .fops = &mpeg_fops, .ioctl_ops = &mpeg_ioctl_ops, .tvnorms = CX23885_NORMS, - .current_norm = V4L2_STD_NTSC_M, }; void cx23885_417_unregister(struct cx23885_dev *dev) @@ -1735,7 +1732,7 @@ static struct video_device *cx23885_video_dev_alloc( *vfd = *template; snprintf(vfd->name, sizeof(vfd->name), "%s (%s)", cx23885_boards[tsport->dev->board].name, type); - vfd->parent = &pci->dev; + vfd->v4l2_dev = &dev->v4l2_dev; vfd->release = video_device_release; return vfd; } diff --git a/drivers/media/pci/cx23885/cx23885-ioctl.c b/drivers/media/pci/cx23885/cx23885-ioctl.c index acdb6d58db58..271d69d1ca8c 100644 --- a/drivers/media/pci/cx23885/cx23885-ioctl.c +++ b/drivers/media/pci/cx23885/cx23885-ioctl.c @@ -24,93 +24,21 @@ #include "cx23885.h" #include "cx23885-ioctl.h" -#include <media/v4l2-chip-ident.h> - -int cx23885_g_chip_ident(struct file *file, void *fh, - struct v4l2_dbg_chip_ident *chip) +#ifdef CONFIG_VIDEO_ADV_DEBUG +int cx23885_g_chip_info(struct file *file, void *fh, + struct v4l2_dbg_chip_info *chip) { struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev; - int err = 0; - u8 rev; - - chip->ident = V4L2_IDENT_NONE; - chip->revision = 0; - switch (chip->match.type) { - case V4L2_CHIP_MATCH_HOST: - switch (chip->match.addr) { - case 0: - rev = cx_read(RDR_CFG2) & 0xff; - switch (dev->pci->device) { - case 0x8852: - /* rev 0x04 could be '885 or '888. Pick '888. */ - if (rev == 0x04) - chip->ident = V4L2_IDENT_CX23888; - else - chip->ident = V4L2_IDENT_CX23885; - break; - case 0x8880: - if (rev == 0x0e || rev == 0x0f) - chip->ident = V4L2_IDENT_CX23887; - else - chip->ident = V4L2_IDENT_CX23888; - break; - default: - chip->ident = V4L2_IDENT_UNKNOWN; - break; - } - chip->revision = (dev->pci->device << 16) | (rev << 8) | - (dev->hwrevision & 0xff); - break; - case 1: - if (dev->v4l_device != NULL) { - chip->ident = V4L2_IDENT_CX23417; - chip->revision = 0; - } - break; - case 2: - /* - * The integrated IR controller on the CX23888 is - * host chip 2. It may not be used/initialized or sd_ir - * may be pointing at the cx25840 subdevice for the - * IR controller on the CX23885. Thus we find it - * without using the dev->sd_ir pointer. - */ - call_hw(dev, CX23885_HW_888_IR, core, g_chip_ident, - chip); - break; - default: - err = -EINVAL; /* per V4L2 spec */ - break; - } - break; - case V4L2_CHIP_MATCH_I2C_DRIVER: - /* If needed, returns V4L2_IDENT_AMBIGUOUS without extra work */ - call_all(dev, core, g_chip_ident, chip); - break; - case V4L2_CHIP_MATCH_I2C_ADDR: - /* - * We could return V4L2_IDENT_UNKNOWN, but we don't do the work - * to look if a chip is at the address with no driver. That's a - * dangerous thing to do with EEPROMs anyway. - */ - call_all(dev, core, g_chip_ident, chip); - break; - default: - err = -EINVAL; - break; - } - return err; -} -#ifdef CONFIG_VIDEO_ADV_DEBUG -static int cx23885_g_host_register(struct cx23885_dev *dev, - struct v4l2_dbg_register *reg) -{ - if ((reg->reg & 0x3) != 0 || reg->reg >= pci_resource_len(dev->pci, 0)) + if (chip->match.addr > 1) return -EINVAL; - - reg->size = 4; - reg->val = cx_read(reg->reg); + if (chip->match.addr == 1) { + if (dev->v4l_device == NULL) + return -EINVAL; + strlcpy(chip->name, "cx23417", sizeof(chip->name)); + } else { + strlcpy(chip->name, dev->v4l2_dev.name, sizeof(chip->name)); + } return 0; } @@ -138,32 +66,16 @@ int cx23885_g_register(struct file *file, void *fh, { struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - if (reg->match.type == V4L2_CHIP_MATCH_HOST) { - switch (reg->match.addr) { - case 0: - return cx23885_g_host_register(dev, reg); - case 1: - return cx23417_g_register(dev, reg); - default: - break; - } - } - - /* FIXME - any error returns should not be ignored */ - call_all(dev, core, g_register, reg); - return 0; -} + if (reg->match.addr > 1) + return -EINVAL; + if (reg->match.addr) + return cx23417_g_register(dev, reg); -static int cx23885_s_host_register(struct cx23885_dev *dev, - const struct v4l2_dbg_register *reg) -{ if ((reg->reg & 0x3) != 0 || reg->reg >= pci_resource_len(dev->pci, 0)) return -EINVAL; - cx_write(reg->reg, reg->val); + reg->size = 4; + reg->val = cx_read(reg->reg); return 0; } @@ -186,22 +98,15 @@ int cx23885_s_register(struct file *file, void *fh, { struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - if (reg->match.type == V4L2_CHIP_MATCH_HOST) { - switch (reg->match.addr) { - case 0: - return cx23885_s_host_register(dev, reg); - case 1: - return cx23417_s_register(dev, reg); - default: - break; - } - } + if (reg->match.addr > 1) + return -EINVAL; + if (reg->match.addr) + return cx23417_s_register(dev, reg); + + if ((reg->reg & 0x3) != 0 || reg->reg >= pci_resource_len(dev->pci, 0)) + return -EINVAL; - /* FIXME - any error returns should not be ignored */ - call_all(dev, core, s_register, reg); + cx_write(reg->reg, reg->val); return 0; } #endif diff --git a/drivers/media/pci/cx23885/cx23885-ioctl.h b/drivers/media/pci/cx23885/cx23885-ioctl.h index a6080964a9ee..92d9f0774366 100644 --- a/drivers/media/pci/cx23885/cx23885-ioctl.h +++ b/drivers/media/pci/cx23885/cx23885-ioctl.h @@ -24,8 +24,8 @@ #ifndef _CX23885_IOCTL_H_ #define _CX23885_IOCTL_H_ -int cx23885_g_chip_ident(struct file *file, void *fh, - struct v4l2_dbg_chip_ident *chip); +int cx23885_g_chip_info(struct file *file, void *fh, + struct v4l2_dbg_chip_info *chip); #ifdef CONFIG_VIDEO_ADV_DEBUG int cx23885_g_register(struct file *file, void *fh, diff --git a/drivers/media/pci/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c index ed08c89adde0..e33d1a7dfdd0 100644 --- a/drivers/media/pci/cx23885/cx23885-video.c +++ b/drivers/media/pci/cx23885/cx23885-video.c @@ -1254,8 +1254,7 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; dprintk(1, "%s()\n", __func__); - call_all(dev, core, g_std, id); - + *id = dev->tvnorm; return 0; } @@ -1743,7 +1742,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_dqbuf = vidioc_dqbuf, .vidioc_s_std = vidioc_s_std, .vidioc_g_std = vidioc_g_std, - .vidioc_querystd = vidioc_g_std, .vidioc_enum_input = vidioc_enum_input, .vidioc_g_input = vidioc_g_input, .vidioc_s_input = vidioc_s_input, @@ -1757,8 +1755,8 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_s_tuner = vidioc_s_tuner, .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency, - .vidioc_g_chip_ident = cx23885_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_chip_info = cx23885_g_chip_info, .vidioc_g_register = cx23885_g_register, .vidioc_s_register = cx23885_s_register, #endif @@ -1773,7 +1771,6 @@ static struct video_device cx23885_video_template = { .fops = &video_fops, .ioctl_ops = &video_ioctl_ops, .tvnorms = CX23885_NORMS, - .current_norm = V4L2_STD_NTSC_M, }; static const struct v4l2_file_operations radio_fops = { @@ -1822,7 +1819,7 @@ int cx23885_video_register(struct cx23885_dev *dev) cx23885_vbi_template = cx23885_video_template; strcpy(cx23885_vbi_template.name, "cx23885-vbi"); - dev->tvnorm = cx23885_video_template.current_norm; + dev->tvnorm = V4L2_STD_NTSC_M; /* init video dma queues */ INIT_LIST_HEAD(&dev->vidq.active); diff --git a/drivers/media/pci/cx23885/cx23888-ir.c b/drivers/media/pci/cx23885/cx23888-ir.c index fa672fe41079..2c951dec2d33 100644 --- a/drivers/media/pci/cx23885/cx23888-ir.c +++ b/drivers/media/pci/cx23885/cx23888-ir.c @@ -25,7 +25,6 @@ #include <linux/slab.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> #include <media/rc-core.h> #include "cx23885.h" @@ -131,8 +130,6 @@ union cx23888_ir_fifo_rec { struct cx23888_ir_state { struct v4l2_subdev sd; struct cx23885_dev *dev; - u32 id; - u32 rev; struct v4l2_subdev_ir_parameters rx_params; struct mutex rx_params_lock; @@ -1086,23 +1083,6 @@ static int cx23888_ir_log_status(struct v4l2_subdev *sd) return 0; } -static inline int cx23888_ir_dbg_match(const struct v4l2_dbg_match *match) -{ - return match->type == V4L2_CHIP_MATCH_HOST && match->addr == 2; -} - -static int cx23888_ir_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - struct cx23888_ir_state *state = to_state(sd); - - if (cx23888_ir_dbg_match(&chip->match)) { - chip->ident = state->id; - chip->revision = state->rev; - } - return 0; -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int cx23888_ir_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) @@ -1110,14 +1090,10 @@ static int cx23888_ir_g_register(struct v4l2_subdev *sd, struct cx23888_ir_state *state = to_state(sd); u32 addr = CX23888_IR_REG_BASE + (u32) reg->reg; - if (!cx23888_ir_dbg_match(®->match)) - return -EINVAL; if ((addr & 0x3) != 0) return -EINVAL; if (addr < CX23888_IR_CNTRL_REG || addr > CX23888_IR_LEARN_REG) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; reg->size = 4; reg->val = cx23888_ir_read4(state->dev, addr); return 0; @@ -1129,21 +1105,16 @@ static int cx23888_ir_s_register(struct v4l2_subdev *sd, struct cx23888_ir_state *state = to_state(sd); u32 addr = CX23888_IR_REG_BASE + (u32) reg->reg; - if (!cx23888_ir_dbg_match(®->match)) - return -EINVAL; if ((addr & 0x3) != 0) return -EINVAL; if (addr < CX23888_IR_CNTRL_REG || addr > CX23888_IR_LEARN_REG) return -EINVAL; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; cx23888_ir_write4(state->dev, addr, reg->val); return 0; } #endif static const struct v4l2_subdev_core_ops cx23888_ir_core_ops = { - .g_chip_ident = cx23888_ir_g_chip_ident, .log_status = cx23888_ir_log_status, #ifdef CONFIG_VIDEO_ADV_DEBUG .g_register = cx23888_ir_g_register, @@ -1217,8 +1188,6 @@ int cx23888_ir_probe(struct cx23885_dev *dev) return -ENOMEM; state->dev = dev; - state->id = V4L2_IDENT_CX23888_IR; - state->rev = 0; sd = &state->sd; v4l2_subdev_init(sd, &cx23888_ir_controller_ops); diff --git a/drivers/media/pci/cx88/cx88-cards.c b/drivers/media/pci/cx88/cx88-cards.c index a87a0e19593e..e18a7ace08b1 100644 --- a/drivers/media/pci/cx88/cx88-cards.c +++ b/drivers/media/pci/cx88/cx88-cards.c @@ -744,7 +744,7 @@ static const struct cx88_board cx88_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, /* Some variants use a tda9874 and so need the tvaudio module. */ - .audio_chip = V4L2_IDENT_TVAUDIO, + .audio_chip = CX88_AUDIO_TVAUDIO, .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, @@ -976,7 +976,7 @@ static const struct cx88_board cx88_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .audio_chip = V4L2_IDENT_WM8775, + .audio_chip = CX88_AUDIO_WM8775, .i2sinputcntl = 2, .input = {{ .type = CX88_VMUX_DVB, @@ -1014,7 +1014,7 @@ static const struct cx88_board cx88_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .audio_chip = V4L2_IDENT_WM8775, + .audio_chip = CX88_AUDIO_WM8775, .input = {{ .type = CX88_VMUX_DVB, .vmux = 0, @@ -1376,7 +1376,7 @@ static const struct cx88_board cx88_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, - .audio_chip = V4L2_IDENT_WM8775, + .audio_chip = CX88_AUDIO_WM8775, .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, @@ -1461,7 +1461,7 @@ static const struct cx88_board cx88_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, - .audio_chip = V4L2_IDENT_WM8775, + .audio_chip = CX88_AUDIO_WM8775, /* * gpio0 as reported by Mike Crash <mike AT mikecrash.com> */ @@ -1929,7 +1929,7 @@ static const struct cx88_board cx88_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, - .audio_chip = V4L2_IDENT_WM8775, + .audio_chip = CX88_AUDIO_WM8775, /* * GPIO0 (WINTV2000) * diff --git a/drivers/media/pci/cx88/cx88-core.c b/drivers/media/pci/cx88/cx88-core.c index c8f3dcc579d4..ad59dc9235ae 100644 --- a/drivers/media/pci/cx88/cx88-core.c +++ b/drivers/media/pci/cx88/cx88-core.c @@ -1034,7 +1034,14 @@ struct video_device *cx88_vdev_init(struct cx88_core *core, if (NULL == vfd) return NULL; *vfd = *template_; + /* + * The dev pointer of v4l2_device is NULL, instead we set the + * video_device dev_parent pointer to the correct PCI bus device. + * This driver is a rare example where there is one v4l2_device, + * but the video nodes have different parent (PCI) devices. + */ vfd->v4l2_dev = &core->v4l2_dev; + vfd->dev_parent = &pci->dev; vfd->release = video_device_release; snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", core->name, type, core->board.name); diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c index c7a9be1065c0..ecf21d9f1f34 100644 --- a/drivers/media/pci/cx88/cx88-video.c +++ b/drivers/media/pci/cx88/cx88-video.c @@ -1353,26 +1353,14 @@ static int vidioc_s_frequency (struct file *file, void *priv, return cx88_set_freq(core, f); } -static int vidioc_g_chip_ident(struct file *file, void *priv, - struct v4l2_dbg_chip_ident *chip) -{ - if (!v4l2_chip_match_host(&chip->match)) - return -EINVAL; - chip->revision = 0; - chip->ident = V4L2_IDENT_UNKNOWN; - return 0; -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int vidioc_g_register (struct file *file, void *fh, struct v4l2_dbg_register *reg) { struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core; - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; /* cx2388x has a 24-bit register space */ - reg->val = cx_read(reg->reg & 0xffffff); + reg->val = cx_read(reg->reg & 0xfffffc); reg->size = 4; return 0; } @@ -1382,9 +1370,7 @@ static int vidioc_s_register (struct file *file, void *fh, { struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core; - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; - cx_write(reg->reg & 0xffffff, reg->val); + cx_write(reg->reg & 0xfffffc, reg->val); return 0; } #endif @@ -1578,7 +1564,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_s_frequency = vidioc_s_frequency, .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, - .vidioc_g_chip_ident = vidioc_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = vidioc_g_register, .vidioc_s_register = vidioc_s_register, @@ -1612,7 +1597,6 @@ static const struct v4l2_ioctl_ops vbi_ioctl_ops = { .vidioc_s_tuner = vidioc_s_tuner, .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency, - .vidioc_g_chip_ident = vidioc_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = vidioc_g_register, .vidioc_s_register = vidioc_s_register, @@ -1643,7 +1627,6 @@ static const struct v4l2_ioctl_ops radio_ioctl_ops = { .vidioc_s_frequency = vidioc_s_frequency, .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, - .vidioc_g_chip_ident = vidioc_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = vidioc_g_register, .vidioc_s_register = vidioc_s_register, @@ -1794,7 +1777,7 @@ static int cx8800_initdev(struct pci_dev *pci_dev, /* load and configure helper modules */ - if (core->board.audio_chip == V4L2_IDENT_WM8775) { + if (core->board.audio_chip == CX88_AUDIO_WM8775) { struct i2c_board_info wm8775_info = { .type = "wm8775", .addr = 0x36 >> 1, @@ -1815,7 +1798,7 @@ static int cx8800_initdev(struct pci_dev *pci_dev, } } - if (core->board.audio_chip == V4L2_IDENT_TVAUDIO) { + if (core->board.audio_chip == CX88_AUDIO_TVAUDIO) { /* This probes for a tda9874 as is used on some Pixelview Ultra boards. */ v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap, diff --git a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h index 51ce2c0e8bc1..afe0eaea81b4 100644 --- a/drivers/media/pci/cx88/cx88.h +++ b/drivers/media/pci/cx88/cx88.h @@ -30,7 +30,6 @@ #include <media/tuner.h> #include <media/tveeprom.h> #include <media/videobuf-dma-sg.h> -#include <media/v4l2-chip-ident.h> #include <media/cx2341x.h> #include <media/videobuf-dvb.h> #include <media/ir-kbd-i2c.h> @@ -259,6 +258,11 @@ struct cx88_input { unsigned int audioroute:4; }; +enum cx88_audio_chip { + CX88_AUDIO_WM8775, + CX88_AUDIO_TVAUDIO, +}; + struct cx88_board { const char *name; unsigned int tuner_type; @@ -269,7 +273,7 @@ struct cx88_board { struct cx88_input input[MAX_CX88_INPUT]; struct cx88_input radio; enum cx88_board_type mpeg; - unsigned int audio_chip; + enum cx88_audio_chip audio_chip; int num_frontends; /* Used for I2S devices */ diff --git a/drivers/media/pci/dm1105/dm1105.c b/drivers/media/pci/dm1105/dm1105.c index 026767bed5cd..ab797fe466d2 100644 --- a/drivers/media/pci/dm1105/dm1105.c +++ b/drivers/media/pci/dm1105/dm1105.c @@ -1241,18 +1241,7 @@ static struct pci_driver dm1105_driver = { .remove = dm1105_remove, }; -static int __init dm1105_init(void) -{ - return pci_register_driver(&dm1105_driver); -} - -static void __exit dm1105_exit(void) -{ - pci_unregister_driver(&dm1105_driver); -} - -module_init(dm1105_init); -module_exit(dm1105_exit); +module_pci_driver(dm1105_driver); MODULE_AUTHOR("Igor M. Liplianin <liplianin@me.by>"); MODULE_DESCRIPTION("SDMC DM1105 DVB driver"); diff --git a/drivers/media/pci/ivtv/ivtv-driver.c b/drivers/media/pci/ivtv/ivtv-driver.c index b809bc868a9f..c08ae3eb9554 100644 --- a/drivers/media/pci/ivtv/ivtv-driver.c +++ b/drivers/media/pci/ivtv/ivtv-driver.c @@ -58,7 +58,6 @@ #include <linux/dma-mapping.h> #include <media/tveeprom.h> #include <media/saa7115.h> -#include <media/v4l2-chip-ident.h> #include "tuner-xc2028.h" /* If you have already X v4l cards, then set this to X. This way @@ -968,15 +967,10 @@ static void ivtv_load_and_init_modules(struct ivtv *itv) } if (hw & IVTV_HW_SAA711X) { - struct v4l2_dbg_chip_ident v; - /* determine the exact saa711x model */ itv->hw_flags &= ~IVTV_HW_SAA711X; - v.match.type = V4L2_CHIP_MATCH_I2C_DRIVER; - strlcpy(v.match.name, "saa7115", sizeof(v.match.name)); - ivtv_call_hw(itv, IVTV_HW_SAA711X, core, g_chip_ident, &v); - if (v.ident == V4L2_IDENT_SAA7114) { + if (strstr(itv->sd_video->name, "saa7114")) { itv->hw_flags |= IVTV_HW_SAA7114; /* VBI is not yet supported by the saa7114 driver. */ itv->v4l2_cap &= ~(V4L2_CAP_SLICED_VBI_CAPTURE|V4L2_CAP_VBI_CAPTURE); diff --git a/drivers/media/pci/ivtv/ivtv-ioctl.c b/drivers/media/pci/ivtv/ivtv-ioctl.c index 9cbbce0eaedc..807b275a847e 100644 --- a/drivers/media/pci/ivtv/ivtv-ioctl.c +++ b/drivers/media/pci/ivtv/ivtv-ioctl.c @@ -34,7 +34,6 @@ #include "ivtv-cards.h" #include <media/saa7127.h> #include <media/tveeprom.h> -#include <media/v4l2-chip-ident.h> #include <media/v4l2-event.h> #include <linux/dvb/audio.h> @@ -692,31 +691,13 @@ static int ivtv_s_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_f return ret; } -static int ivtv_g_chip_ident(struct file *file, void *fh, struct v4l2_dbg_chip_ident *chip) -{ - struct ivtv *itv = fh2id(fh)->itv; - - chip->ident = V4L2_IDENT_NONE; - chip->revision = 0; - if (chip->match.type == V4L2_CHIP_MATCH_HOST) { - if (v4l2_chip_match_host(&chip->match)) - chip->ident = itv->has_cx23415 ? V4L2_IDENT_CX23415 : V4L2_IDENT_CX23416; - return 0; - } - if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER && - chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR) - return -EINVAL; - /* TODO: is this correct? */ - return ivtv_call_all_err(itv, core, g_chip_ident, chip); -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int ivtv_itvc(struct ivtv *itv, bool get, u64 reg, u64 *val) { volatile u8 __iomem *reg_start; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; + if (reg & 0x3) + return -EINVAL; if (reg >= IVTV_REG_OFFSET && reg < IVTV_REG_OFFSET + IVTV_REG_SIZE) reg_start = itv->reg_mem - IVTV_REG_OFFSET; else if (itv->has_cx23415 && reg >= IVTV_DECODER_OFFSET && @@ -738,29 +719,16 @@ static int ivtv_g_register(struct file *file, void *fh, struct v4l2_dbg_register { struct ivtv *itv = fh2id(fh)->itv; - if (v4l2_chip_match_host(®->match)) { - reg->size = 4; - return ivtv_itvc(itv, true, reg->reg, ®->val); - } - /* TODO: subdev errors should not be ignored, this should become a - subdev helper function. */ - ivtv_call_all(itv, core, g_register, reg); - return 0; + reg->size = 4; + return ivtv_itvc(itv, true, reg->reg, ®->val); } static int ivtv_s_register(struct file *file, void *fh, const struct v4l2_dbg_register *reg) { struct ivtv *itv = fh2id(fh)->itv; + u64 val = reg->val; - if (v4l2_chip_match_host(®->match)) { - u64 val = reg->val; - - return ivtv_itvc(itv, false, reg->reg, &val); - } - /* TODO: subdev errors should not be ignored, this should become a - subdev helper function. */ - ivtv_call_all(itv, core, s_register, reg); - return 0; + return ivtv_itvc(itv, false, reg->reg, &val); } #endif @@ -1914,7 +1882,6 @@ static const struct v4l2_ioctl_ops ivtv_ioctl_ops = { .vidioc_try_fmt_vid_out_overlay = ivtv_try_fmt_vid_out_overlay, .vidioc_try_fmt_sliced_vbi_out = ivtv_try_fmt_sliced_vbi_out, .vidioc_g_sliced_vbi_cap = ivtv_g_sliced_vbi_cap, - .vidioc_g_chip_ident = ivtv_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = ivtv_g_register, .vidioc_s_register = ivtv_s_register, diff --git a/drivers/media/pci/mantis/hopper_cards.c b/drivers/media/pci/mantis/hopper_cards.c index 6fe9fe5293dc..104914a5bf06 100644 --- a/drivers/media/pci/mantis/hopper_cards.c +++ b/drivers/media/pci/mantis/hopper_cards.c @@ -260,18 +260,7 @@ static struct pci_driver hopper_pci_driver = { .remove = hopper_pci_remove, }; -static int hopper_init(void) -{ - return pci_register_driver(&hopper_pci_driver); -} - -static void hopper_exit(void) -{ - return pci_unregister_driver(&hopper_pci_driver); -} - -module_init(hopper_init); -module_exit(hopper_exit); +module_pci_driver(hopper_pci_driver); MODULE_DESCRIPTION("HOPPER driver"); MODULE_AUTHOR("Manu Abraham"); diff --git a/drivers/media/pci/mantis/mantis_cards.c b/drivers/media/pci/mantis/mantis_cards.c index 932a0d73a7f8..801fc55b6167 100644 --- a/drivers/media/pci/mantis/mantis_cards.c +++ b/drivers/media/pci/mantis/mantis_cards.c @@ -290,18 +290,7 @@ static struct pci_driver mantis_pci_driver = { .remove = mantis_pci_remove, }; -static int mantis_init(void) -{ - return pci_register_driver(&mantis_pci_driver); -} - -static void mantis_exit(void) -{ - return pci_unregister_driver(&mantis_pci_driver); -} - -module_init(mantis_init); -module_exit(mantis_exit); +module_pci_driver(mantis_pci_driver); MODULE_DESCRIPTION("MANTIS driver"); MODULE_AUTHOR("Manu Abraham"); diff --git a/drivers/media/pci/mantis/mantis_vp1041.c b/drivers/media/pci/mantis/mantis_vp1041.c index 07aa887a4b4a..07a20748b707 100644 --- a/drivers/media/pci/mantis/mantis_vp1041.c +++ b/drivers/media/pci/mantis/mantis_vp1041.c @@ -273,7 +273,7 @@ struct stb0899_config vp1041_stb0899_config = { .demod_address = 0x68, /* 0xd0 >> 1 */ .xtal_freq = 27000000, - .inversion = IQ_SWAP_ON, /* 1 */ + .inversion = IQ_SWAP_ON, .lo_clk = 76500000, .hi_clk = 99000000, diff --git a/drivers/media/pci/pluto2/pluto2.c b/drivers/media/pci/pluto2/pluto2.c index 2290faee5852..493828500055 100644 --- a/drivers/media/pci/pluto2/pluto2.c +++ b/drivers/media/pci/pluto2/pluto2.c @@ -796,18 +796,7 @@ static struct pci_driver pluto2_driver = { .remove = pluto2_remove, }; -static int __init pluto2_init(void) -{ - return pci_register_driver(&pluto2_driver); -} - -static void __exit pluto2_exit(void) -{ - pci_unregister_driver(&pluto2_driver); -} - -module_init(pluto2_init); -module_exit(pluto2_exit); +module_pci_driver(pluto2_driver); MODULE_AUTHOR("Andreas Oberritter <obi@linuxtv.org>"); MODULE_DESCRIPTION("Pluto2 driver"); diff --git a/drivers/media/pci/pt1/pt1.c b/drivers/media/pci/pt1/pt1.c index e9211086df49..75ce14229e03 100644 --- a/drivers/media/pci/pt1/pt1.c +++ b/drivers/media/pci/pt1/pt1.c @@ -1225,20 +1225,7 @@ static struct pci_driver pt1_driver = { .id_table = pt1_id_table, }; - -static int __init pt1_init(void) -{ - return pci_register_driver(&pt1_driver); -} - - -static void __exit pt1_cleanup(void) -{ - pci_unregister_driver(&pt1_driver); -} - -module_init(pt1_init); -module_exit(pt1_cleanup); +module_pci_driver(pt1_driver); MODULE_AUTHOR("Takahito HIRANO <hiranotaka@zng.info>"); MODULE_DESCRIPTION("Earthsoft PT1/PT2 Driver"); diff --git a/drivers/media/pci/saa7134/saa6752hs.c b/drivers/media/pci/saa7134/saa6752hs.c index f147b05bd860..8ac4b1f2322d 100644 --- a/drivers/media/pci/saa7134/saa6752hs.c +++ b/drivers/media/pci/saa7134/saa6752hs.c @@ -34,8 +34,8 @@ #include <linux/types.h> #include <linux/videodev2.h> #include <media/v4l2-device.h> +#include <media/v4l2-ctrls.h> #include <media/v4l2-common.h> -#include <media/v4l2-chip-ident.h> #include <linux/init.h> #include <linux/crc32.h> @@ -92,7 +92,12 @@ static const struct v4l2_format v4l2_format_table[] = struct saa6752hs_state { struct v4l2_subdev sd; - int chip; + struct v4l2_ctrl_handler hdl; + struct { /* video bitrate mode control cluster */ + struct v4l2_ctrl *video_bitrate_mode; + struct v4l2_ctrl *video_bitrate; + struct v4l2_ctrl *video_bitrate_peak; + }; u32 revision; int has_ac3; struct saa6752hs_mpeg_params params; @@ -362,316 +367,72 @@ static int saa6752hs_set_bitrate(struct i2c_client *client, return 0; } - -static int get_ctrl(int has_ac3, struct saa6752hs_mpeg_params *params, - struct v4l2_ext_control *ctrl) +static int saa6752hs_try_ctrl(struct v4l2_ctrl *ctrl) { + struct saa6752hs_state *h = + container_of(ctrl->handler, struct saa6752hs_state, hdl); + switch (ctrl->id) { - case V4L2_CID_MPEG_STREAM_TYPE: - ctrl->value = V4L2_MPEG_STREAM_TYPE_MPEG2_TS; - break; - case V4L2_CID_MPEG_STREAM_PID_PMT: - ctrl->value = params->ts_pid_pmt; - break; - case V4L2_CID_MPEG_STREAM_PID_AUDIO: - ctrl->value = params->ts_pid_audio; - break; - case V4L2_CID_MPEG_STREAM_PID_VIDEO: - ctrl->value = params->ts_pid_video; - break; - case V4L2_CID_MPEG_STREAM_PID_PCR: - ctrl->value = params->ts_pid_pcr; - break; - case V4L2_CID_MPEG_AUDIO_ENCODING: - ctrl->value = params->au_encoding; - break; - case V4L2_CID_MPEG_AUDIO_L2_BITRATE: - ctrl->value = params->au_l2_bitrate; - break; - case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: - if (!has_ac3) - return -EINVAL; - ctrl->value = params->au_ac3_bitrate; - break; - case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: - ctrl->value = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000; - break; - case V4L2_CID_MPEG_VIDEO_ENCODING: - ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_2; - break; - case V4L2_CID_MPEG_VIDEO_ASPECT: - ctrl->value = params->vi_aspect; - break; - case V4L2_CID_MPEG_VIDEO_BITRATE: - ctrl->value = params->vi_bitrate * 1000; - break; - case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: - ctrl->value = params->vi_bitrate_peak * 1000; - break; case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: - ctrl->value = params->vi_bitrate_mode; + /* peak bitrate shall be >= normal bitrate */ + if (ctrl->val == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR && + h->video_bitrate_peak->val < h->video_bitrate->val) + h->video_bitrate_peak->val = h->video_bitrate->val; break; - default: - return -EINVAL; } return 0; } -static int handle_ctrl(int has_ac3, struct saa6752hs_mpeg_params *params, - struct v4l2_ext_control *ctrl, int set) +static int saa6752hs_s_ctrl(struct v4l2_ctrl *ctrl) { - int old = 0, new; + struct saa6752hs_state *h = + container_of(ctrl->handler, struct saa6752hs_state, hdl); + struct saa6752hs_mpeg_params *params = &h->params; - new = ctrl->value; switch (ctrl->id) { case V4L2_CID_MPEG_STREAM_TYPE: - old = V4L2_MPEG_STREAM_TYPE_MPEG2_TS; - if (set && new != old) - return -ERANGE; - new = old; break; case V4L2_CID_MPEG_STREAM_PID_PMT: - old = params->ts_pid_pmt; - if (set && new > MPEG_PID_MAX) - return -ERANGE; - if (new > MPEG_PID_MAX) - new = MPEG_PID_MAX; - params->ts_pid_pmt = new; + params->ts_pid_pmt = ctrl->val; break; case V4L2_CID_MPEG_STREAM_PID_AUDIO: - old = params->ts_pid_audio; - if (set && new > MPEG_PID_MAX) - return -ERANGE; - if (new > MPEG_PID_MAX) - new = MPEG_PID_MAX; - params->ts_pid_audio = new; + params->ts_pid_audio = ctrl->val; break; case V4L2_CID_MPEG_STREAM_PID_VIDEO: - old = params->ts_pid_video; - if (set && new > MPEG_PID_MAX) - return -ERANGE; - if (new > MPEG_PID_MAX) - new = MPEG_PID_MAX; - params->ts_pid_video = new; + params->ts_pid_video = ctrl->val; break; case V4L2_CID_MPEG_STREAM_PID_PCR: - old = params->ts_pid_pcr; - if (set && new > MPEG_PID_MAX) - return -ERANGE; - if (new > MPEG_PID_MAX) - new = MPEG_PID_MAX; - params->ts_pid_pcr = new; + params->ts_pid_pcr = ctrl->val; break; case V4L2_CID_MPEG_AUDIO_ENCODING: - old = params->au_encoding; - if (set && new != V4L2_MPEG_AUDIO_ENCODING_LAYER_2 && - (!has_ac3 || new != V4L2_MPEG_AUDIO_ENCODING_AC3)) - return -ERANGE; - params->au_encoding = new; + params->au_encoding = ctrl->val; break; case V4L2_CID_MPEG_AUDIO_L2_BITRATE: - old = params->au_l2_bitrate; - if (set && new != V4L2_MPEG_AUDIO_L2_BITRATE_256K && - new != V4L2_MPEG_AUDIO_L2_BITRATE_384K) - return -ERANGE; - if (new <= V4L2_MPEG_AUDIO_L2_BITRATE_256K) - new = V4L2_MPEG_AUDIO_L2_BITRATE_256K; - else - new = V4L2_MPEG_AUDIO_L2_BITRATE_384K; - params->au_l2_bitrate = new; + params->au_l2_bitrate = ctrl->val; break; case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: - if (!has_ac3) - return -EINVAL; - old = params->au_ac3_bitrate; - if (set && new != V4L2_MPEG_AUDIO_AC3_BITRATE_256K && - new != V4L2_MPEG_AUDIO_AC3_BITRATE_384K) - return -ERANGE; - if (new <= V4L2_MPEG_AUDIO_AC3_BITRATE_256K) - new = V4L2_MPEG_AUDIO_AC3_BITRATE_256K; - else - new = V4L2_MPEG_AUDIO_AC3_BITRATE_384K; - params->au_ac3_bitrate = new; + params->au_ac3_bitrate = ctrl->val; break; case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: - old = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000; - if (set && new != old) - return -ERANGE; - new = old; break; case V4L2_CID_MPEG_VIDEO_ENCODING: - old = V4L2_MPEG_VIDEO_ENCODING_MPEG_2; - if (set && new != old) - return -ERANGE; - new = old; break; case V4L2_CID_MPEG_VIDEO_ASPECT: - old = params->vi_aspect; - if (set && new != V4L2_MPEG_VIDEO_ASPECT_16x9 && - new != V4L2_MPEG_VIDEO_ASPECT_4x3) - return -ERANGE; - if (new != V4L2_MPEG_VIDEO_ASPECT_16x9) - new = V4L2_MPEG_VIDEO_ASPECT_4x3; - params->vi_aspect = new; - break; - case V4L2_CID_MPEG_VIDEO_BITRATE: - old = params->vi_bitrate * 1000; - new = 1000 * (new / 1000); - if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) - return -ERANGE; - if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) - new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000; - params->vi_bitrate = new / 1000; - break; - case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: - old = params->vi_bitrate_peak * 1000; - new = 1000 * (new / 1000); - if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) - return -ERANGE; - if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000) - new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000; - params->vi_bitrate_peak = new / 1000; + params->vi_aspect = ctrl->val; break; case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: - old = params->vi_bitrate_mode; - params->vi_bitrate_mode = new; + params->vi_bitrate_mode = ctrl->val; + params->vi_bitrate = h->video_bitrate->val / 1000; + params->vi_bitrate_peak = h->video_bitrate_peak->val / 1000; + v4l2_ctrl_activate(h->video_bitrate_peak, + ctrl->val == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); break; default: return -EINVAL; } - ctrl->value = new; return 0; } - -static int saa6752hs_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qctrl) -{ - struct saa6752hs_state *h = to_state(sd); - struct saa6752hs_mpeg_params *params = &h->params; - int err; - - switch (qctrl->id) { - case V4L2_CID_MPEG_AUDIO_ENCODING: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_AUDIO_ENCODING_LAYER_2, - h->has_ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3 : - V4L2_MPEG_AUDIO_ENCODING_LAYER_2, - 1, V4L2_MPEG_AUDIO_ENCODING_LAYER_2); - - case V4L2_CID_MPEG_AUDIO_L2_BITRATE: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_AUDIO_L2_BITRATE_256K, - V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1, - V4L2_MPEG_AUDIO_L2_BITRATE_256K); - - case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: - if (!h->has_ac3) - return -EINVAL; - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_AUDIO_AC3_BITRATE_256K, - V4L2_MPEG_AUDIO_AC3_BITRATE_384K, 1, - V4L2_MPEG_AUDIO_AC3_BITRATE_256K); - - case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000, - V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000, 1, - V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000); - - case V4L2_CID_MPEG_VIDEO_ENCODING: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_VIDEO_ENCODING_MPEG_2, - V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1, - V4L2_MPEG_VIDEO_ENCODING_MPEG_2); - - case V4L2_CID_MPEG_VIDEO_ASPECT: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_VIDEO_ASPECT_4x3, - V4L2_MPEG_VIDEO_ASPECT_16x9, 1, - V4L2_MPEG_VIDEO_ASPECT_4x3); - - case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: - err = v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 8000000); - if (err == 0 && - params->vi_bitrate_mode == - V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) - qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; - return err; - - case V4L2_CID_MPEG_STREAM_TYPE: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_STREAM_TYPE_MPEG2_TS, - V4L2_MPEG_STREAM_TYPE_MPEG2_TS, 1, - V4L2_MPEG_STREAM_TYPE_MPEG2_TS); - - case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: - return v4l2_ctrl_query_fill(qctrl, - V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, - V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1, - V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); - case V4L2_CID_MPEG_VIDEO_BITRATE: - return v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 6000000); - case V4L2_CID_MPEG_STREAM_PID_PMT: - return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 16); - case V4L2_CID_MPEG_STREAM_PID_AUDIO: - return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 260); - case V4L2_CID_MPEG_STREAM_PID_VIDEO: - return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 256); - case V4L2_CID_MPEG_STREAM_PID_PCR: - return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 259); - - default: - break; - } - return -EINVAL; -} - -static int saa6752hs_querymenu(struct v4l2_subdev *sd, struct v4l2_querymenu *qmenu) -{ - static const u32 mpeg_audio_encoding[] = { - V4L2_MPEG_AUDIO_ENCODING_LAYER_2, - V4L2_CTRL_MENU_IDS_END - }; - static const u32 mpeg_audio_ac3_encoding[] = { - V4L2_MPEG_AUDIO_ENCODING_LAYER_2, - V4L2_MPEG_AUDIO_ENCODING_AC3, - V4L2_CTRL_MENU_IDS_END - }; - static u32 mpeg_audio_l2_bitrate[] = { - V4L2_MPEG_AUDIO_L2_BITRATE_256K, - V4L2_MPEG_AUDIO_L2_BITRATE_384K, - V4L2_CTRL_MENU_IDS_END - }; - static u32 mpeg_audio_ac3_bitrate[] = { - V4L2_MPEG_AUDIO_AC3_BITRATE_256K, - V4L2_MPEG_AUDIO_AC3_BITRATE_384K, - V4L2_CTRL_MENU_IDS_END - }; - struct saa6752hs_state *h = to_state(sd); - struct v4l2_queryctrl qctrl; - int err; - - qctrl.id = qmenu->id; - err = saa6752hs_queryctrl(sd, &qctrl); - if (err) - return err; - switch (qmenu->id) { - case V4L2_CID_MPEG_AUDIO_L2_BITRATE: - return v4l2_ctrl_query_menu_valid_items(qmenu, - mpeg_audio_l2_bitrate); - case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: - if (!h->has_ac3) - return -EINVAL; - return v4l2_ctrl_query_menu_valid_items(qmenu, - mpeg_audio_ac3_bitrate); - case V4L2_CID_MPEG_AUDIO_ENCODING: - return v4l2_ctrl_query_menu_valid_items(qmenu, - h->has_ac3 ? mpeg_audio_ac3_encoding : - mpeg_audio_encoding); - } - return v4l2_ctrl_query_menu(qmenu, &qctrl, NULL); -} - static int saa6752hs_init(struct v4l2_subdev *sd, u32 leading_null_bytes) { unsigned char buf[9], buf2[4]; @@ -793,58 +554,6 @@ static int saa6752hs_init(struct v4l2_subdev *sd, u32 leading_null_bytes) return 0; } -static int saa6752hs_do_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls, int set) -{ - struct saa6752hs_state *h = to_state(sd); - struct saa6752hs_mpeg_params params; - int i; - - if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) - return -EINVAL; - - params = h->params; - for (i = 0; i < ctrls->count; i++) { - int err = handle_ctrl(h->has_ac3, ¶ms, ctrls->controls + i, set); - - if (err) { - ctrls->error_idx = i; - return err; - } - } - if (set) - h->params = params; - return 0; -} - -static int saa6752hs_s_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls) -{ - return saa6752hs_do_ext_ctrls(sd, ctrls, 1); -} - -static int saa6752hs_try_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls) -{ - return saa6752hs_do_ext_ctrls(sd, ctrls, 0); -} - -static int saa6752hs_g_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls) -{ - struct saa6752hs_state *h = to_state(sd); - int i; - - if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) - return -EINVAL; - - for (i = 0; i < ctrls->count; i++) { - int err = get_ctrl(h->has_ac3, &h->params, ctrls->controls + i); - - if (err) { - ctrls->error_idx = i; - return err; - } - } - return 0; -} - static int saa6752hs_g_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f) { struct saa6752hs_state *h = to_state(sd); @@ -859,25 +568,11 @@ static int saa6752hs_g_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefm return 0; } -static int saa6752hs_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f) +static int saa6752hs_try_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f) { - struct saa6752hs_state *h = to_state(sd); int dist_352, dist_480, dist_720; - if (f->code != V4L2_MBUS_FMT_FIXED) - return -EINVAL; - - /* - FIXME: translate and round width/height into EMPRESS - subsample type: - - type | PAL | NTSC - --------------------------- - SIF | 352x288 | 352x240 - 1/2 D1 | 352x576 | 352x480 - 2/3 D1 | 480x576 | 480x480 - D1 | 720x576 | 720x480 - */ + f->code = V4L2_MBUS_FMT_FIXED; dist_352 = abs(f->width - 352); dist_480 = abs(f->width - 480); @@ -885,59 +580,82 @@ static int saa6752hs_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefm if (dist_720 < dist_480) { f->width = 720; f->height = 576; - h->video_format = SAA6752HS_VF_D1; } else if (dist_480 < dist_352) { f->width = 480; f->height = 576; - h->video_format = SAA6752HS_VF_2_3_D1; } else { f->width = 352; - if (abs(f->height - 576) < - abs(f->height - 288)) { + if (abs(f->height - 576) < abs(f->height - 288)) f->height = 576; - h->video_format = SAA6752HS_VF_1_2_D1; - } else { + else f->height = 288; - h->video_format = SAA6752HS_VF_SIF; - } } f->field = V4L2_FIELD_INTERLACED; f->colorspace = V4L2_COLORSPACE_SMPTE170M; return 0; } -static int saa6752hs_s_std(struct v4l2_subdev *sd, v4l2_std_id std) +static int saa6752hs_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f) { struct saa6752hs_state *h = to_state(sd); - h->standard = std; + if (f->code != V4L2_MBUS_FMT_FIXED) + return -EINVAL; + + /* + FIXME: translate and round width/height into EMPRESS + subsample type: + + type | PAL | NTSC + --------------------------- + SIF | 352x288 | 352x240 + 1/2 D1 | 352x576 | 352x480 + 2/3 D1 | 480x576 | 480x480 + D1 | 720x576 | 720x480 + */ + + saa6752hs_try_mbus_fmt(sd, f); + if (f->width == 720) + h->video_format = SAA6752HS_VF_D1; + else if (f->width == 480) + h->video_format = SAA6752HS_VF_2_3_D1; + else if (f->height == 576) + h->video_format = SAA6752HS_VF_1_2_D1; + else + h->video_format = SAA6752HS_VF_SIF; return 0; } -static int saa6752hs_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) +static int saa6752hs_s_std(struct v4l2_subdev *sd, v4l2_std_id std) { - struct i2c_client *client = v4l2_get_subdevdata(sd); struct saa6752hs_state *h = to_state(sd); - return v4l2_chip_ident_i2c_client(client, - chip, h->chip, h->revision); + h->standard = std; + return 0; } /* ----------------------------------------------------------------------- */ +static const struct v4l2_ctrl_ops saa6752hs_ctrl_ops = { + .try_ctrl = saa6752hs_try_ctrl, + .s_ctrl = saa6752hs_s_ctrl, +}; + static const struct v4l2_subdev_core_ops saa6752hs_core_ops = { - .g_chip_ident = saa6752hs_g_chip_ident, .init = saa6752hs_init, - .queryctrl = saa6752hs_queryctrl, - .querymenu = saa6752hs_querymenu, - .g_ext_ctrls = saa6752hs_g_ext_ctrls, - .s_ext_ctrls = saa6752hs_s_ext_ctrls, - .try_ext_ctrls = saa6752hs_try_ext_ctrls, + .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, + .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, + .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, + .g_ctrl = v4l2_subdev_g_ctrl, + .s_ctrl = v4l2_subdev_s_ctrl, + .queryctrl = v4l2_subdev_queryctrl, + .querymenu = v4l2_subdev_querymenu, .s_std = saa6752hs_s_std, }; static const struct v4l2_subdev_video_ops saa6752hs_video_ops = { .s_mbus_fmt = saa6752hs_s_mbus_fmt, + .try_mbus_fmt = saa6752hs_try_mbus_fmt, .g_mbus_fmt = saa6752hs_g_mbus_fmt, }; @@ -951,6 +669,7 @@ static int saa6752hs_probe(struct i2c_client *client, { struct saa6752hs_state *h = kzalloc(sizeof(*h), GFP_KERNEL); struct v4l2_subdev *sd; + struct v4l2_ctrl_handler *hdl; u8 addr = 0x13; u8 data[12]; @@ -963,15 +682,88 @@ static int saa6752hs_probe(struct i2c_client *client, i2c_master_send(client, &addr, 1); i2c_master_recv(client, data, sizeof(data)); - h->chip = V4L2_IDENT_SAA6752HS; h->revision = (data[8] << 8) | data[9]; h->has_ac3 = 0; if (h->revision == 0x0206) { - h->chip = V4L2_IDENT_SAA6752HS_AC3; h->has_ac3 = 1; - v4l_info(client, "support AC-3\n"); + v4l_info(client, "supports AC-3\n"); } h->params = param_defaults; + + hdl = &h->hdl; + v4l2_ctrl_handler_init(hdl, 14); + v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops, + V4L2_CID_MPEG_AUDIO_ENCODING, + h->has_ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3 : + V4L2_MPEG_AUDIO_ENCODING_LAYER_2, + 0x0d, V4L2_MPEG_AUDIO_ENCODING_LAYER_2); + + v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops, + V4L2_CID_MPEG_AUDIO_L2_BITRATE, + V4L2_MPEG_AUDIO_L2_BITRATE_384K, + ~((1 << V4L2_MPEG_AUDIO_L2_BITRATE_256K) | + (1 << V4L2_MPEG_AUDIO_L2_BITRATE_384K)), + V4L2_MPEG_AUDIO_L2_BITRATE_256K); + + if (h->has_ac3) + v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops, + V4L2_CID_MPEG_AUDIO_AC3_BITRATE, + V4L2_MPEG_AUDIO_AC3_BITRATE_384K, + ~((1 << V4L2_MPEG_AUDIO_AC3_BITRATE_256K) | + (1 << V4L2_MPEG_AUDIO_AC3_BITRATE_384K)), + V4L2_MPEG_AUDIO_AC3_BITRATE_256K); + + v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops, + V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ, + V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000, + ~(1 << V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000), + V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000); + + v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops, + V4L2_CID_MPEG_VIDEO_ENCODING, + V4L2_MPEG_VIDEO_ENCODING_MPEG_2, + ~(1 << V4L2_MPEG_VIDEO_ENCODING_MPEG_2), + V4L2_MPEG_VIDEO_ENCODING_MPEG_2); + + v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops, + V4L2_CID_MPEG_VIDEO_ASPECT, + V4L2_MPEG_VIDEO_ASPECT_16x9, 0x01, + V4L2_MPEG_VIDEO_ASPECT_4x3); + + h->video_bitrate_peak = v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops, + V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, + 1000000, 27000000, 1000, 8000000); + + v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops, + V4L2_CID_MPEG_STREAM_TYPE, + V4L2_MPEG_STREAM_TYPE_MPEG2_TS, + ~(1 << V4L2_MPEG_STREAM_TYPE_MPEG2_TS), + V4L2_MPEG_STREAM_TYPE_MPEG2_TS); + + h->video_bitrate_mode = v4l2_ctrl_new_std_menu(hdl, &saa6752hs_ctrl_ops, + V4L2_CID_MPEG_VIDEO_BITRATE_MODE, + V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 0, + V4L2_MPEG_VIDEO_BITRATE_MODE_VBR); + h->video_bitrate = v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops, + V4L2_CID_MPEG_VIDEO_BITRATE, 1000000, 27000000, 1000, 6000000); + v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops, + V4L2_CID_MPEG_STREAM_PID_PMT, 0, (1 << 14) - 1, 1, 16); + v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops, + V4L2_CID_MPEG_STREAM_PID_AUDIO, 0, (1 << 14) - 1, 1, 260); + v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops, + V4L2_CID_MPEG_STREAM_PID_VIDEO, 0, (1 << 14) - 1, 1, 256); + v4l2_ctrl_new_std(hdl, &saa6752hs_ctrl_ops, + V4L2_CID_MPEG_STREAM_PID_PCR, 0, (1 << 14) - 1, 1, 259); + sd->ctrl_handler = hdl; + if (hdl->error) { + int err = hdl->error; + + v4l2_ctrl_handler_free(hdl); + kfree(h); + return err; + } + v4l2_ctrl_cluster(3, &h->video_bitrate_mode); + v4l2_ctrl_handler_setup(hdl); h->standard = 0; /* Assume 625 input lines */ return 0; } @@ -981,6 +773,7 @@ static int saa6752hs_remove(struct i2c_client *client) struct v4l2_subdev *sd = i2c_get_clientdata(client); v4l2_device_unregister_subdev(sd); + v4l2_ctrl_handler_free(&to_state(sd)->hdl); kfree(to_state(sd)); return 0; } @@ -1002,11 +795,3 @@ static struct i2c_driver saa6752hs_driver = { }; module_i2c_driver(saa6752hs_driver); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * --------------------------------------------------------------------------- - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/pci/saa7134/saa7134-empress.c b/drivers/media/pci/saa7134/saa7134-empress.c index 66a70814004c..3022eb2a7925 100644 --- a/drivers/media/pci/saa7134/saa7134-empress.c +++ b/drivers/media/pci/saa7134/saa7134-empress.c @@ -28,7 +28,6 @@ #include <media/saa6752hs.h> #include <media/v4l2-common.h> -#include <media/v4l2-chip-ident.h> /* ------------------------------------------------------------------ */ @@ -213,7 +212,7 @@ static int empress_enum_fmt_vid_cap(struct file *file, void *priv, strlcpy(f->description, "MPEG TS", sizeof(f->description)); f->pixelformat = V4L2_PIX_FMT_MPEG; - + f->flags = V4L2_FMT_FLAG_COMPRESSED; return 0; } @@ -228,6 +227,8 @@ static int empress_g_fmt_vid_cap(struct file *file, void *priv, v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt); f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets; + f->fmt.pix.bytesperline = 0; + f->fmt.pix.priv = 0; return 0; } @@ -244,6 +245,8 @@ static int empress_s_fmt_vid_cap(struct file *file, void *priv, f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets; + f->fmt.pix.bytesperline = 0; + f->fmt.pix.priv = 0; return 0; } @@ -252,9 +255,16 @@ static int empress_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { struct saa7134_dev *dev = file->private_data; + struct v4l2_mbus_framefmt mbus_fmt; + + v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED); + saa_call_all(dev, video, try_mbus_fmt, &mbus_fmt); + v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt); f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets; + f->fmt.pix.bytesperline = 0; + f->fmt.pix.priv = 0; return 0; } @@ -413,21 +423,6 @@ static int empress_querymenu(struct file *file, void *priv, return saa_call_empress(dev, core, querymenu, c); } -static int empress_g_chip_ident(struct file *file, void *fh, - struct v4l2_dbg_chip_ident *chip) -{ - struct saa7134_dev *dev = file->private_data; - - chip->ident = V4L2_IDENT_NONE; - chip->revision = 0; - if (chip->match.type == V4L2_CHIP_MATCH_I2C_DRIVER && - !strcmp(chip->match.name, "saa6752hs")) - return saa_call_empress(dev, core, g_chip_ident, chip); - if (chip->match.type == V4L2_CHIP_MATCH_I2C_ADDR) - return saa_call_empress(dev, core, g_chip_ident, chip); - return -EINVAL; -} - static int empress_s_std(struct file *file, void *priv, v4l2_std_id id) { struct saa7134_dev *dev = file->private_data; @@ -475,7 +470,6 @@ static const struct v4l2_ioctl_ops ts_ioctl_ops = { .vidioc_querymenu = empress_querymenu, .vidioc_g_ctrl = empress_g_ctrl, .vidioc_s_ctrl = empress_s_ctrl, - .vidioc_g_chip_ident = empress_g_chip_ident, .vidioc_s_std = empress_s_std, .vidioc_g_std = empress_g_std, }; @@ -488,7 +482,6 @@ static struct video_device saa7134_empress_template = { .ioctl_ops = &ts_ioctl_ops, .tvnorms = SAA7134_NORMS, - .current_norm = V4L2_STD_PAL, }; static void empress_signal_update(struct work_struct *work) @@ -518,7 +511,7 @@ static int empress_init(struct saa7134_dev *dev) if (NULL == dev->empress_dev) return -ENOMEM; *(dev->empress_dev) = saa7134_empress_template; - dev->empress_dev->parent = &dev->pci->dev; + dev->empress_dev->v4l2_dev = &dev->v4l2_dev; dev->empress_dev->release = video_device_release; snprintf(dev->empress_dev->name, sizeof(dev->empress_dev->name), "%s empress (%s)", dev->name, diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index cc409380ee16..e12bbd8c3f0b 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -825,20 +825,22 @@ static int setup_clipping(struct saa7134_dev *dev, struct v4l2_clip *clips, return 0; } -static int verify_preview(struct saa7134_dev *dev, struct v4l2_window *win) +static int verify_preview(struct saa7134_dev *dev, struct v4l2_window *win, bool try) { enum v4l2_field field; int maxw, maxh; - if (NULL == dev->ovbuf.base) + if (!try && (dev->ovbuf.base == NULL || dev->ovfmt == NULL)) return -EINVAL; - if (NULL == dev->ovfmt) - return -EINVAL; - if (win->w.width < 48 || win->w.height < 32) - return -EINVAL; - if (win->clipcount > 2048) - return -EINVAL; - + if (win->w.width < 48) + win->w.width = 48; + if (win->w.height < 32) + win->w.height = 32; + if (win->clipcount > 8) + win->clipcount = 8; + + win->chromakey = 0; + win->global_alpha = 0; field = win->field; maxw = dev->crop_current.width; maxh = dev->crop_current.height; @@ -853,10 +855,9 @@ static int verify_preview(struct saa7134_dev *dev, struct v4l2_window *win) case V4L2_FIELD_BOTTOM: maxh = maxh / 2; break; - case V4L2_FIELD_INTERLACED: - break; default: - return -EINVAL; + field = V4L2_FIELD_INTERLACED; + break; } win->field = field; @@ -872,20 +873,20 @@ static int start_preview(struct saa7134_dev *dev, struct saa7134_fh *fh) unsigned long base,control,bpl; int err; - err = verify_preview(dev,&fh->win); + err = verify_preview(dev, &dev->win, false); if (0 != err) return err; - dev->ovfield = fh->win.field; + dev->ovfield = dev->win.field; dprintk("start_preview %dx%d+%d+%d %s field=%s\n", - fh->win.w.width,fh->win.w.height, - fh->win.w.left,fh->win.w.top, - dev->ovfmt->name,v4l2_field_names[dev->ovfield]); + dev->win.w.width, dev->win.w.height, + dev->win.w.left, dev->win.w.top, + dev->ovfmt->name, v4l2_field_names[dev->ovfield]); /* setup window + clipping */ - set_size(dev,TASK_B,fh->win.w.width,fh->win.w.height, + set_size(dev, TASK_B, dev->win.w.width, dev->win.w.height, V4L2_FIELD_HAS_BOTH(dev->ovfield)); - setup_clipping(dev,fh->clips,fh->nclips, + setup_clipping(dev, dev->clips, dev->nclips, V4L2_FIELD_HAS_BOTH(dev->ovfield)); if (dev->ovfmt->yuv) saa_andorb(SAA7134_DATA_PATH(TASK_B), 0x3f, 0x03); @@ -895,8 +896,8 @@ static int start_preview(struct saa7134_dev *dev, struct saa7134_fh *fh) /* dma: setup channel 1 (= Video Task B) */ base = (unsigned long)dev->ovbuf.base; - base += dev->ovbuf.fmt.bytesperline * fh->win.w.top; - base += dev->ovfmt->depth/8 * fh->win.w.left; + base += dev->ovbuf.fmt.bytesperline * dev->win.w.top; + base += dev->ovfmt->depth/8 * dev->win.w.left; bpl = dev->ovbuf.fmt.bytesperline; control = SAA7134_RS_CONTROL_BURST_16; if (dev->ovfmt->bswap) @@ -1024,38 +1025,38 @@ static int buffer_prepare(struct videobuf_queue *q, int err; /* sanity checks */ - if (NULL == fh->fmt) + if (NULL == dev->fmt) return -EINVAL; - if (fh->width < 48 || - fh->height < 32 || - fh->width/4 > dev->crop_current.width || - fh->height/4 > dev->crop_current.height || - fh->width > dev->crop_bounds.width || - fh->height > dev->crop_bounds.height) + if (dev->width < 48 || + dev->height < 32 || + dev->width/4 > dev->crop_current.width || + dev->height/4 > dev->crop_current.height || + dev->width > dev->crop_bounds.width || + dev->height > dev->crop_bounds.height) return -EINVAL; - size = (fh->width * fh->height * fh->fmt->depth) >> 3; + size = (dev->width * dev->height * dev->fmt->depth) >> 3; if (0 != buf->vb.baddr && buf->vb.bsize < size) return -EINVAL; dprintk("buffer_prepare [%d,size=%dx%d,bytes=%d,fields=%s,%s]\n", - vb->i,fh->width,fh->height,size,v4l2_field_names[field], - fh->fmt->name); - if (buf->vb.width != fh->width || - buf->vb.height != fh->height || + vb->i, dev->width, dev->height, size, v4l2_field_names[field], + dev->fmt->name); + if (buf->vb.width != dev->width || + buf->vb.height != dev->height || buf->vb.size != size || buf->vb.field != field || - buf->fmt != fh->fmt) { + buf->fmt != dev->fmt) { saa7134_dma_free(q,buf); } if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); - buf->vb.width = fh->width; - buf->vb.height = fh->height; + buf->vb.width = dev->width; + buf->vb.height = dev->height; buf->vb.size = size; buf->vb.field = field; - buf->fmt = fh->fmt; + buf->fmt = dev->fmt; buf->pt = &fh->pt_cap; dev->video_q.curr = NULL; @@ -1082,8 +1083,9 @@ static int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) { struct saa7134_fh *fh = q->priv_data; + struct saa7134_dev *dev = fh->dev; - *size = fh->fmt->depth * fh->width * fh->height >> 3; + *size = dev->fmt->depth * dev->width * dev->height >> 3; if (0 == *count) *count = gbuffers; *count = saa7134_buffer_count(*size,*count); @@ -1287,15 +1289,17 @@ static int saa7134_s_ctrl(struct file *file, void *f, struct v4l2_control *c) /* ------------------------------------------------------------------ */ -static struct videobuf_queue* saa7134_queue(struct saa7134_fh *fh) +static struct videobuf_queue *saa7134_queue(struct file *file) { - struct videobuf_queue* q = NULL; + struct video_device *vdev = video_devdata(file); + struct saa7134_fh *fh = file->private_data; + struct videobuf_queue *q = NULL; - switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: + switch (vdev->vfl_type) { + case VFL_TYPE_GRABBER: q = &fh->cap; break; - case V4L2_BUF_TYPE_VBI_CAPTURE: + case VFL_TYPE_VBI: q = &fh->vbi; break; default: @@ -1304,12 +1308,14 @@ static struct videobuf_queue* saa7134_queue(struct saa7134_fh *fh) return q; } -static int saa7134_resource(struct saa7134_fh *fh) +static int saa7134_resource(struct file *file) { - if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + struct video_device *vdev = video_devdata(file); + + if (vdev->vfl_type == VFL_TYPE_GRABBER) return RESOURCE_VIDEO; - if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) + if (vdev->vfl_type == VFL_TYPE_VBI) return RESOURCE_VBI; BUG(); @@ -1321,23 +1327,6 @@ static int video_open(struct file *file) struct video_device *vdev = video_devdata(file); struct saa7134_dev *dev = video_drvdata(file); struct saa7134_fh *fh; - enum v4l2_buf_type type = 0; - int radio = 0; - - switch (vdev->vfl_type) { - case VFL_TYPE_GRABBER: - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - break; - case VFL_TYPE_VBI: - type = V4L2_BUF_TYPE_VBI_CAPTURE; - break; - case VFL_TYPE_RADIO: - radio = 1; - break; - } - - dprintk("open dev=%s radio=%d type=%s\n", video_device_node_name(vdev), - radio, v4l2_type_names[type]); /* allocate + initialize per filehandle data */ fh = kzalloc(sizeof(*fh),GFP_KERNEL); @@ -1347,11 +1336,6 @@ static int video_open(struct file *file) v4l2_fh_init(&fh->fh, vdev); file->private_data = fh; fh->dev = dev; - fh->radio = radio; - fh->type = type; - fh->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); - fh->width = 720; - fh->height = 576; videobuf_queue_sg_init(&fh->cap, &video_qops, &dev->pci->dev, &dev->slock, @@ -1368,7 +1352,7 @@ static int video_open(struct file *file) saa7134_pgtable_alloc(dev->pci,&fh->pt_cap); saa7134_pgtable_alloc(dev->pci,&fh->pt_vbi); - if (fh->radio) { + if (vdev->vfl_type == VFL_TYPE_RADIO) { /* switch to radio mode */ saa7134_tvaudio_setinput(dev,&card(dev).radio); saa_call_all(dev, tuner, s_radio); @@ -1384,19 +1368,20 @@ static int video_open(struct file *file) static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) { + struct video_device *vdev = video_devdata(file); struct saa7134_fh *fh = file->private_data; - switch (fh->type) { - case V4L2_BUF_TYPE_VIDEO_CAPTURE: + switch (vdev->vfl_type) { + case VFL_TYPE_GRABBER: if (res_locked(fh->dev,RESOURCE_VIDEO)) return -EBUSY; - return videobuf_read_one(saa7134_queue(fh), + return videobuf_read_one(saa7134_queue(file), data, count, ppos, file->f_flags & O_NONBLOCK); - case V4L2_BUF_TYPE_VBI_CAPTURE: + case VFL_TYPE_VBI: if (!res_get(fh->dev,fh,RESOURCE_VBI)) return -EBUSY; - return videobuf_read_stream(saa7134_queue(fh), + return videobuf_read_stream(saa7134_queue(file), data, count, ppos, 1, file->f_flags & O_NONBLOCK); break; @@ -1409,11 +1394,12 @@ video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) static unsigned int video_poll(struct file *file, struct poll_table_struct *wait) { + struct video_device *vdev = video_devdata(file); struct saa7134_fh *fh = file->private_data; struct videobuf_buffer *buf = NULL; unsigned int rc = 0; - if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) + if (vdev->vfl_type == VFL_TYPE_VBI) return videobuf_poll_stream(file, &fh->vbi, wait); if (res_check(fh,RESOURCE_VIDEO)) { @@ -1451,6 +1437,7 @@ err: static int video_release(struct file *file) { + struct video_device *vdev = video_devdata(file); struct saa7134_fh *fh = file->private_data; struct saa7134_dev *dev = fh->dev; struct saa6588_command cmd; @@ -1489,7 +1476,7 @@ static int video_release(struct file *file) saa_andorb(SAA7134_OFMT_DATA_B, 0x1f, 0); saa_call_all(dev, core, s_power, 0); - if (fh->radio) + if (vdev->vfl_type == VFL_TYPE_RADIO) saa_call_all(dev, core, ioctl, SAA6588_CMD_CLOSE, &cmd); /* free stuff */ @@ -1507,9 +1494,7 @@ static int video_release(struct file *file) static int video_mmap(struct file *file, struct vm_area_struct * vma) { - struct saa7134_fh *fh = file->private_data; - - return videobuf_mmap_mapper(saa7134_queue(fh), vma); + return videobuf_mmap_mapper(saa7134_queue(file), vma); } static ssize_t radio_read(struct file *file, char __user *data, @@ -1570,15 +1555,18 @@ static int saa7134_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { struct saa7134_fh *fh = priv; + struct saa7134_dev *dev = fh->dev; - f->fmt.pix.width = fh->width; - f->fmt.pix.height = fh->height; + f->fmt.pix.width = dev->width; + f->fmt.pix.height = dev->height; f->fmt.pix.field = fh->cap.field; - f->fmt.pix.pixelformat = fh->fmt->fourcc; + f->fmt.pix.pixelformat = dev->fmt->fourcc; f->fmt.pix.bytesperline = - (f->fmt.pix.width * fh->fmt->depth) >> 3; + (f->fmt.pix.width * dev->fmt->depth) >> 3; f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; + f->fmt.pix.priv = 0; return 0; } @@ -1586,14 +1574,33 @@ static int saa7134_g_fmt_vid_overlay(struct file *file, void *priv, struct v4l2_format *f) { struct saa7134_fh *fh = priv; + struct saa7134_dev *dev = fh->dev; + struct v4l2_clip __user *clips = f->fmt.win.clips; + u32 clipcount = f->fmt.win.clipcount; + int err = 0; + int i; if (saa7134_no_overlay > 0) { printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n"); return -EINVAL; } - f->fmt.win = fh->win; + mutex_lock(&dev->lock); + f->fmt.win = dev->win; + f->fmt.win.clips = clips; + if (clips == NULL) + clipcount = 0; + if (dev->nclips < clipcount) + clipcount = dev->nclips; + f->fmt.win.clipcount = clipcount; + + for (i = 0; !err && i < clipcount; i++) { + if (copy_to_user(&f->fmt.win.clips[i].c, &dev->clips[i].c, + sizeof(struct v4l2_rect))) + err = -EFAULT; + } + mutex_unlock(&dev->lock); - return 0; + return err; } static int saa7134_try_fmt_vid_cap(struct file *file, void *priv, @@ -1623,10 +1630,9 @@ static int saa7134_try_fmt_vid_cap(struct file *file, void *priv, case V4L2_FIELD_BOTTOM: maxh = maxh / 2; break; - case V4L2_FIELD_INTERLACED: - break; default: - return -EINVAL; + field = V4L2_FIELD_INTERLACED; + break; } f->fmt.pix.field = field; @@ -1643,6 +1649,8 @@ static int saa7134_try_fmt_vid_cap(struct file *file, void *priv, (f->fmt.pix.width * fmt->depth) >> 3; f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; + f->fmt.pix.priv = 0; return 0; } @@ -1658,22 +1666,25 @@ static int saa7134_try_fmt_vid_overlay(struct file *file, void *priv, return -EINVAL; } - return verify_preview(dev, &f->fmt.win); + if (f->fmt.win.clips == NULL) + f->fmt.win.clipcount = 0; + return verify_preview(dev, &f->fmt.win, true); } static int saa7134_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { struct saa7134_fh *fh = priv; + struct saa7134_dev *dev = fh->dev; int err; err = saa7134_try_fmt_vid_cap(file, priv, f); if (0 != err) return err; - fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat); - fh->width = f->fmt.pix.width; - fh->height = f->fmt.pix.height; + dev->fmt = format_by_fourcc(f->fmt.pix.pixelformat); + dev->width = f->fmt.pix.width; + dev->height = f->fmt.pix.height; fh->cap.field = f->fmt.pix.field; return 0; } @@ -1690,20 +1701,19 @@ static int saa7134_s_fmt_vid_overlay(struct file *file, void *priv, printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n"); return -EINVAL; } - err = verify_preview(dev, &f->fmt.win); + if (f->fmt.win.clips == NULL) + f->fmt.win.clipcount = 0; + err = verify_preview(dev, &f->fmt.win, true); if (0 != err) return err; mutex_lock(&dev->lock); - fh->win = f->fmt.win; - fh->nclips = f->fmt.win.clipcount; + dev->win = f->fmt.win; + dev->nclips = f->fmt.win.clipcount; - if (fh->nclips > 8) - fh->nclips = 8; - - if (copy_from_user(fh->clips, f->fmt.win.clips, - sizeof(struct v4l2_clip)*fh->nclips)) { + if (copy_from_user(dev->clips, f->fmt.win.clips, + sizeof(struct v4l2_clip) * dev->nclips)) { mutex_unlock(&dev->lock); return -EFAULT; } @@ -2057,7 +2067,6 @@ static int saa7134_g_frequency(struct file *file, void *priv, if (0 != f->tuner) return -EINVAL; - f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; saa_call_all(dev, tuner, g_frequency, f); return 0; @@ -2071,10 +2080,6 @@ static int saa7134_s_frequency(struct file *file, void *priv, if (0 != f->tuner) return -EINVAL; - if (0 == fh->radio && V4L2_TUNER_ANALOG_TV != f->type) - return -EINVAL; - if (1 == fh->radio && V4L2_TUNER_RADIO != f->type) - return -EINVAL; mutex_lock(&dev->lock); saa_call_all(dev, tuner, s_frequency, f); @@ -2186,27 +2191,23 @@ static int saa7134_overlay(struct file *file, void *f, unsigned int on) static int saa7134_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *p) { - struct saa7134_fh *fh = priv; - return videobuf_reqbufs(saa7134_queue(fh), p); + return videobuf_reqbufs(saa7134_queue(file), p); } static int saa7134_querybuf(struct file *file, void *priv, struct v4l2_buffer *b) { - struct saa7134_fh *fh = priv; - return videobuf_querybuf(saa7134_queue(fh), b); + return videobuf_querybuf(saa7134_queue(file), b); } static int saa7134_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) { - struct saa7134_fh *fh = priv; - return videobuf_qbuf(saa7134_queue(fh), b); + return videobuf_qbuf(saa7134_queue(file), b); } static int saa7134_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) { - struct saa7134_fh *fh = priv; - return videobuf_dqbuf(saa7134_queue(fh), b, + return videobuf_dqbuf(saa7134_queue(file), b, file->f_flags & O_NONBLOCK); } @@ -2215,7 +2216,7 @@ static int saa7134_streamon(struct file *file, void *priv, { struct saa7134_fh *fh = priv; struct saa7134_dev *dev = fh->dev; - int res = saa7134_resource(fh); + int res = saa7134_resource(file); if (!res_get(dev, fh, res)) return -EBUSY; @@ -2227,11 +2228,11 @@ static int saa7134_streamon(struct file *file, void *priv, * Unfortunately, I lack register-level documentation to check the * Linux FIFO setup and confirm the perfect value. */ - pm_qos_add_request(&fh->qos_request, + pm_qos_add_request(&dev->qos_request, PM_QOS_CPU_DMA_LATENCY, 20); - return videobuf_streamon(saa7134_queue(fh)); + return videobuf_streamon(saa7134_queue(file)); } static int saa7134_streamoff(struct file *file, void *priv, @@ -2240,11 +2241,11 @@ static int saa7134_streamoff(struct file *file, void *priv, int err; struct saa7134_fh *fh = priv; struct saa7134_dev *dev = fh->dev; - int res = saa7134_resource(fh); + int res = saa7134_resource(file); - pm_qos_remove_request(&fh->qos_request); + pm_qos_remove_request(&dev->qos_request); - err = videobuf_streamoff(saa7134_queue(fh)); + err = videobuf_streamoff(saa7134_queue(file)); if (err < 0) return err; res_free(dev, fh, res); @@ -2258,9 +2259,7 @@ static int vidioc_g_register (struct file *file, void *priv, struct saa7134_fh *fh = priv; struct saa7134_dev *dev = fh->dev; - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; - reg->val = saa_readb(reg->reg); + reg->val = saa_readb(reg->reg & 0xffffff); reg->size = 1; return 0; } @@ -2271,9 +2270,7 @@ static int vidioc_s_register (struct file *file, void *priv, struct saa7134_fh *fh = priv; struct saa7134_dev *dev = fh->dev; - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; - saa_writeb(reg->reg&0xffffff, reg->val); + saa_writeb(reg->reg & 0xffffff, reg->val); return 0; } #endif @@ -2287,9 +2284,7 @@ static int radio_g_tuner(struct file *file, void *priv, if (0 != t->index) return -EINVAL; - memset(t, 0, sizeof(*t)); strcpy(t->name, "Radio"); - t->type = V4L2_TUNER_RADIO; saa_call_all(dev, tuner, g_tuner, t); t->audmode &= V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO; @@ -2443,7 +2438,6 @@ struct video_device saa7134_video_template = { .fops = &video_fops, .ioctl_ops = &video_ioctl_ops, .tvnorms = SAA7134_NORMS, - .current_norm = V4L2_STD_PAL, }; struct video_device saa7134_radio_template = { @@ -2480,6 +2474,16 @@ int saa7134_video_init1(struct saa7134_dev *dev) dev->video_q.timeout.function = saa7134_buffer_timeout; dev->video_q.timeout.data = (unsigned long)(&dev->video_q); dev->video_q.dev = dev; + dev->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); + dev->width = 720; + dev->height = 576; + dev->win.w.width = dev->width; + dev->win.w.height = dev->height; + dev->win.field = V4L2_FIELD_INTERLACED; + dev->ovbuf.fmt.width = dev->width; + dev->ovbuf.fmt.height = dev->height; + dev->ovbuf.fmt.pixelformat = dev->fmt->fourcc; + dev->ovbuf.fmt.colorspace = V4L2_COLORSPACE_SMPTE170M; if (saa7134_boards[dev->board].video_out) saa7134_videoport_init(dev); diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h index d2ad16c1569a..8d1453a48014 100644 --- a/drivers/media/pci/saa7134/saa7134.h +++ b/drivers/media/pci/saa7134/saa7134.h @@ -471,19 +471,9 @@ struct saa7134_dmaqueue { struct saa7134_fh { struct v4l2_fh fh; struct saa7134_dev *dev; - unsigned int radio; - enum v4l2_buf_type type; unsigned int resources; - struct pm_qos_request qos_request; - - /* video overlay */ - struct v4l2_window win; - struct v4l2_clip clips[8]; - unsigned int nclips; /* video capture */ - struct saa7134_format *fmt; - unsigned int width,height; struct videobuf_queue cap; struct saa7134_pgtable pt_cap; @@ -592,12 +582,19 @@ struct saa7134_dev { struct saa7134_format *ovfmt; unsigned int ovenable; enum v4l2_field ovfield; + struct v4l2_window win; + struct v4l2_clip clips[8]; + unsigned int nclips; + /* video+ts+vbi capture */ struct saa7134_dmaqueue video_q; struct saa7134_dmaqueue vbi_q; unsigned int video_fieldcount; unsigned int vbi_fieldcount; + struct saa7134_format *fmt; + unsigned int width, height; + struct pm_qos_request qos_request; /* various v4l controls */ struct saa7134_tvnorm *tvnorm; /* video */ diff --git a/drivers/media/pci/saa7146/mxb.c b/drivers/media/pci/saa7146/mxb.c index 71e8bead321b..33abe332d175 100644 --- a/drivers/media/pci/saa7146/mxb.c +++ b/drivers/media/pci/saa7146/mxb.c @@ -669,14 +669,10 @@ static int vidioc_g_register(struct file *file, void *fh, struct v4l2_dbg_regist { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (v4l2_chip_match_host(®->match)) { - reg->val = saa7146_read(dev, reg->reg); - reg->size = 4; - return 0; - } - call_all(dev, core, g_register, reg); + if (reg->reg > pci_resource_len(dev->pci, 0) - 4) + return -EINVAL; + reg->val = saa7146_read(dev, reg->reg); + reg->size = 4; return 0; } @@ -684,13 +680,10 @@ static int vidioc_s_register(struct file *file, void *fh, const struct v4l2_dbg_ { struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (v4l2_chip_match_host(®->match)) { - saa7146_write(dev, reg->reg, reg->val); - return 0; - } - return call_all(dev, core, s_register, reg); + if (reg->reg > pci_resource_len(dev->pci, 0) - 4) + return -EINVAL; + saa7146_write(dev, reg->reg, reg->val); + return 0; } #endif diff --git a/drivers/media/pci/saa7164/saa7164-core.c b/drivers/media/pci/saa7164/saa7164-core.c index 7618fdae811e..d37ee37aaefe 100644 --- a/drivers/media/pci/saa7164/saa7164-core.c +++ b/drivers/media/pci/saa7164/saa7164-core.c @@ -1196,6 +1196,12 @@ static int saa7164_initdev(struct pci_dev *pci_dev, if (NULL == dev) return -ENOMEM; + err = v4l2_device_register(&pci_dev->dev, &dev->v4l2_dev); + if (err < 0) { + dev_err(&pci_dev->dev, "v4l2_device_register failed\n"); + goto fail_free; + } + /* pci init */ dev->pci = pci_dev; if (pci_enable_device(pci_dev)) { @@ -1367,6 +1373,7 @@ fail_fw: fail_irq: saa7164_dev_unregister(dev); fail_free: + v4l2_device_unregister(&dev->v4l2_dev); kfree(dev); return err; } @@ -1439,6 +1446,7 @@ static void saa7164_finidev(struct pci_dev *pci_dev) mutex_unlock(&devlist); saa7164_dev_unregister(dev); + v4l2_device_unregister(&dev->v4l2_dev); kfree(dev); } diff --git a/drivers/media/pci/saa7164/saa7164-encoder.c b/drivers/media/pci/saa7164/saa7164-encoder.c index 0b74fb2300dd..9266965412c3 100644 --- a/drivers/media/pci/saa7164/saa7164-encoder.c +++ b/drivers/media/pci/saa7164/saa7164-encoder.c @@ -228,6 +228,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id) return -EINVAL; port->encodernorm = saa7164_tvnorms[i]; + port->std = id; /* Update the audio decoder while is not running in * auto detect mode. @@ -239,6 +240,15 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id) return 0; } +static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) +{ + struct saa7164_encoder_fh *fh = file->private_data; + struct saa7164_port *port = fh->port; + + *id = port->std; + return 0; +} + static int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *i) { @@ -1288,46 +1298,9 @@ static const struct v4l2_file_operations mpeg_fops = { .unlocked_ioctl = video_ioctl2, }; -static int saa7164_g_chip_ident(struct file *file, void *fh, - struct v4l2_dbg_chip_ident *chip) -{ - struct saa7164_port *port = ((struct saa7164_encoder_fh *)fh)->port; - struct saa7164_dev *dev = port->dev; - dprintk(DBGLVL_ENC, "%s()\n", __func__); - - return 0; -} - -#ifdef CONFIG_VIDEO_ADV_DEBUG -static int saa7164_g_register(struct file *file, void *fh, - struct v4l2_dbg_register *reg) -{ - struct saa7164_port *port = ((struct saa7164_encoder_fh *)fh)->port; - struct saa7164_dev *dev = port->dev; - dprintk(DBGLVL_ENC, "%s()\n", __func__); - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - return 0; -} - -static int saa7164_s_register(struct file *file, void *fh, - const struct v4l2_dbg_register *reg) -{ - struct saa7164_port *port = ((struct saa7164_encoder_fh *)fh)->port; - struct saa7164_dev *dev = port->dev; - dprintk(DBGLVL_ENC, "%s()\n", __func__); - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - return 0; -} -#endif - static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { .vidioc_s_std = vidioc_s_std, + .vidioc_g_std = vidioc_g_std, .vidioc_enum_input = vidioc_enum_input, .vidioc_g_input = vidioc_g_input, .vidioc_s_input = vidioc_s_input, @@ -1346,11 +1319,6 @@ static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls, .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_g_chip_ident = saa7164_g_chip_ident, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = saa7164_g_register, - .vidioc_s_register = saa7164_s_register, -#endif }; static struct video_device saa7164_mpeg_template = { @@ -1359,7 +1327,6 @@ static struct video_device saa7164_mpeg_template = { .ioctl_ops = &mpeg_ioctl_ops, .minor = -1, .tvnorms = SAA7164_NORMS, - .current_norm = V4L2_STD_NTSC_M, }; static struct video_device *saa7164_encoder_alloc( @@ -1381,7 +1348,7 @@ static struct video_device *saa7164_encoder_alloc( snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, type, saa7164_boards[dev->board].name); - vfd->parent = &pci->dev; + vfd->v4l2_dev = &dev->v4l2_dev; vfd->release = video_device_release; return vfd; } @@ -1426,6 +1393,7 @@ int saa7164_encoder_register(struct saa7164_port *port) port->encoder_params.ctl_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3; port->encoder_params.refdist = 1; port->encoder_params.gop_size = SAA7164_ENCODER_DEFAULT_GOP_SIZE; + port->std = V4L2_STD_NTSC_M; if (port->encodernorm.id & V4L2_STD_525_60) port->height = 480; diff --git a/drivers/media/pci/saa7164/saa7164-vbi.c b/drivers/media/pci/saa7164/saa7164-vbi.c index da224eb39b95..6e025fea2542 100644 --- a/drivers/media/pci/saa7164/saa7164-vbi.c +++ b/drivers/media/pci/saa7164/saa7164-vbi.c @@ -200,6 +200,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id) return -EINVAL; port->encodernorm = saa7164_tvnorms[i]; + port->std = id; /* Update the audio decoder while is not running in * auto detect mode. @@ -211,6 +212,15 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id) return 0; } +static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) +{ + struct saa7164_encoder_fh *fh = file->private_data; + struct saa7164_port *port = fh->port; + + *id = port->std; + return 0; +} + static int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *i) { @@ -1236,6 +1246,7 @@ static const struct v4l2_file_operations vbi_fops = { static const struct v4l2_ioctl_ops vbi_ioctl_ops = { .vidioc_s_std = vidioc_s_std, + .vidioc_g_std = vidioc_g_std, .vidioc_enum_input = vidioc_enum_input, .vidioc_g_input = vidioc_g_input, .vidioc_s_input = vidioc_s_input, @@ -1254,15 +1265,6 @@ static const struct v4l2_ioctl_ops vbi_ioctl_ops = { .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls, .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls, .vidioc_queryctrl = vidioc_queryctrl, -#if 0 - .vidioc_g_chip_ident = saa7164_g_chip_ident, -#endif -#ifdef CONFIG_VIDEO_ADV_DEBUG -#if 0 - .vidioc_g_register = saa7164_g_register, - .vidioc_s_register = saa7164_s_register, -#endif -#endif .vidioc_g_fmt_vbi_cap = saa7164_vbi_fmt, .vidioc_try_fmt_vbi_cap = saa7164_vbi_fmt, .vidioc_s_fmt_vbi_cap = saa7164_vbi_fmt, @@ -1274,7 +1276,6 @@ static struct video_device saa7164_vbi_template = { .ioctl_ops = &vbi_ioctl_ops, .minor = -1, .tvnorms = SAA7164_NORMS, - .current_norm = V4L2_STD_NTSC_M, }; static struct video_device *saa7164_vbi_alloc( @@ -1296,7 +1297,7 @@ static struct video_device *saa7164_vbi_alloc( snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, type, saa7164_boards[dev->board].name); - vfd->parent = &pci->dev; + vfd->v4l2_dev = &dev->v4l2_dev; vfd->release = video_device_release; return vfd; } @@ -1333,6 +1334,7 @@ int saa7164_vbi_register(struct saa7164_port *port) goto failed; } + port->std = V4L2_STD_NTSC_M; video_set_drvdata(port->v4l_device, port); result = video_register_device(port->v4l_device, VFL_TYPE_VBI, -1); diff --git a/drivers/media/pci/saa7164/saa7164.h b/drivers/media/pci/saa7164/saa7164.h index 437284e747c9..8b29e8990301 100644 --- a/drivers/media/pci/saa7164/saa7164.h +++ b/drivers/media/pci/saa7164/saa7164.h @@ -63,7 +63,7 @@ #include <dmxdev.h> #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> -#include <media/v4l2-chip-ident.h> +#include <media/v4l2-device.h> #include "saa7164-reg.h" #include "saa7164-types.h" @@ -376,6 +376,7 @@ struct saa7164_port { /* Encoder */ /* Defaults established in saa7164-encoder.c */ struct saa7164_tvnorm encodernorm; + v4l2_std_id std; u32 height; u32 width; u32 freq; @@ -427,6 +428,8 @@ struct saa7164_dev { struct list_head devlist; atomic_t refcount; + struct v4l2_device v4l2_dev; + /* pci stuff */ struct pci_dev *pci; unsigned char pci_rev, pci_lat; diff --git a/drivers/media/pci/sta2x11/sta2x11_vip.c b/drivers/media/pci/sta2x11/sta2x11_vip.c index 7005695aa4bd..77edc113e485 100644 --- a/drivers/media/pci/sta2x11/sta2x11_vip.c +++ b/drivers/media/pci/sta2x11/sta2x11_vip.c @@ -1047,7 +1047,8 @@ static int sta2x11_vip_init_one(struct pci_dev *pdev, ret = sta2x11_vip_init_controls(vip); if (ret) goto free_mem; - if (v4l2_device_register(&pdev->dev, &vip->v4l2_dev)) + ret = v4l2_device_register(&pdev->dev, &vip->v4l2_dev); + if (ret) goto free_mem; dev_dbg(&pdev->dev, "BAR #0 at 0x%lx 0x%lx irq %d\n", diff --git a/drivers/media/pci/ttpci/budget-av.c b/drivers/media/pci/ttpci/budget-av.c index 1f8b1bb0bf9f..0ba3875af22e 100644 --- a/drivers/media/pci/ttpci/budget-av.c +++ b/drivers/media/pci/ttpci/budget-av.c @@ -1128,7 +1128,7 @@ static struct stb0899_config knc1_dvbs2_config = { // .ts_pfbit_toggle = STB0899_MPEG_NORMAL, /* DirecTV, MPEG toggling seq */ .xtal_freq = 27000000, - .inversion = IQ_SWAP_OFF, /* 1 */ + .inversion = IQ_SWAP_OFF, .lo_clk = 76500000, .hi_clk = 90000000, diff --git a/drivers/media/pci/ttpci/budget-ci.c b/drivers/media/pci/ttpci/budget-ci.c index 98e524178765..0acf9202103d 100644 --- a/drivers/media/pci/ttpci/budget-ci.c +++ b/drivers/media/pci/ttpci/budget-ci.c @@ -1280,7 +1280,7 @@ static struct stb0899_config tt3200_config = { .demod_address = 0x68, .xtal_freq = 27000000, - .inversion = IQ_SWAP_ON, /* 1 */ + .inversion = IQ_SWAP_ON, .lo_clk = 76500000, .hi_clk = 99000000, diff --git a/drivers/media/pci/zoran/zoran_card.c b/drivers/media/pci/zoran/zoran_card.c index bb53d2488ad0..923d59a321f8 100644 --- a/drivers/media/pci/zoran/zoran_card.c +++ b/drivers/media/pci/zoran/zoran_card.c @@ -1050,7 +1050,7 @@ static int zr36057_init (struct zoran *zr) * Now add the template and register the device unit. */ memcpy(zr->video_dev, &zoran_template, sizeof(zoran_template)); - zr->video_dev->parent = &zr->pci_dev->dev; + zr->video_dev->v4l2_dev = &zr->v4l2_dev; strcpy(zr->video_dev->name, ZR_DEVNAME(zr)); /* 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 diff --git a/drivers/media/pci/zoran/zoran_driver.c b/drivers/media/pci/zoran/zoran_driver.c index d133c30c3fdc..e7e9840c6c35 100644 --- a/drivers/media/pci/zoran/zoran_driver.c +++ b/drivers/media/pci/zoran/zoran_driver.c @@ -1456,29 +1456,6 @@ zoran_set_norm (struct zoran *zr, return -EINVAL; } - if (norm == V4L2_STD_ALL) { - unsigned int status = 0; - v4l2_std_id std = 0; - - decoder_call(zr, video, querystd, &std); - decoder_call(zr, core, s_std, std); - - /* let changes come into effect */ - ssleep(2); - - decoder_call(zr, video, g_input_status, &status); - if (status & V4L2_IN_ST_NO_SIGNAL) { - dprintk(1, - KERN_ERR - "%s: %s - no norm detected\n", - ZR_DEVNAME(zr), __func__); - /* reset norm */ - decoder_call(zr, core, s_std, zr->norm); - return -EIO; - } - - norm = std; - } if (norm & V4L2_STD_SECAM) zr->timing = zr->card.tvn[2]; else if (norm & V4L2_STD_NTSC) diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 25eaf61b98b4..08de865cc399 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -36,7 +36,7 @@ source "drivers/media/platform/blackfin/Kconfig" config VIDEO_SH_VOU tristate "SuperH VOU video output driver" depends on MEDIA_CAMERA_SUPPORT - depends on VIDEO_DEV && ARCH_SHMOBILE + depends on VIDEO_DEV && ARCH_SHMOBILE && I2C select VIDEOBUF_DMA_CONTIG help Support for the Video Output Unit (VOU) on SuperH SoCs. diff --git a/drivers/media/platform/blackfin/bfin_capture.c b/drivers/media/platform/blackfin/bfin_capture.c index 0e55b087076f..7f838c681cea 100644 --- a/drivers/media/platform/blackfin/bfin_capture.c +++ b/drivers/media/platform/blackfin/bfin_capture.c @@ -32,7 +32,6 @@ #include <linux/time.h> #include <linux/types.h> -#include <media/v4l2-chip-ident.h> #include <media/v4l2-common.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> @@ -649,18 +648,30 @@ static int bcap_s_std(struct file *file, void *priv, v4l2_std_id std) return 0; } -static int bcap_g_dv_timings(struct file *file, void *priv, +static int bcap_enum_dv_timings(struct file *file, void *priv, + struct v4l2_enum_dv_timings *timings) +{ + struct bcap_device *bcap_dev = video_drvdata(file); + + return v4l2_subdev_call(bcap_dev->sd, video, + enum_dv_timings, timings); +} + +static int bcap_query_dv_timings(struct file *file, void *priv, struct v4l2_dv_timings *timings) { struct bcap_device *bcap_dev = video_drvdata(file); - int ret; - ret = v4l2_subdev_call(bcap_dev->sd, video, - g_dv_timings, timings); - if (ret < 0) - return ret; + return v4l2_subdev_call(bcap_dev->sd, video, + query_dv_timings, timings); +} - bcap_dev->dv_timings = *timings; +static int bcap_g_dv_timings(struct file *file, void *priv, + struct v4l2_dv_timings *timings) +{ + struct bcap_device *bcap_dev = video_drvdata(file); + + *timings = bcap_dev->dv_timings; return 0; } @@ -864,41 +875,6 @@ static int bcap_s_parm(struct file *file, void *fh, return v4l2_subdev_call(bcap_dev->sd, video, s_parm, a); } -static int bcap_g_chip_ident(struct file *file, void *priv, - struct v4l2_dbg_chip_ident *chip) -{ - struct bcap_device *bcap_dev = video_drvdata(file); - - chip->ident = V4L2_IDENT_NONE; - chip->revision = 0; - if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER && - chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR) - return -EINVAL; - - return v4l2_subdev_call(bcap_dev->sd, core, - g_chip_ident, chip); -} - -#ifdef CONFIG_VIDEO_ADV_DEBUG -static int bcap_dbg_g_register(struct file *file, void *priv, - struct v4l2_dbg_register *reg) -{ - struct bcap_device *bcap_dev = video_drvdata(file); - - return v4l2_subdev_call(bcap_dev->sd, core, - g_register, reg); -} - -static int bcap_dbg_s_register(struct file *file, void *priv, - const struct v4l2_dbg_register *reg) -{ - struct bcap_device *bcap_dev = video_drvdata(file); - - return v4l2_subdev_call(bcap_dev->sd, core, - s_register, reg); -} -#endif - static int bcap_log_status(struct file *file, void *priv) { struct bcap_device *bcap_dev = video_drvdata(file); @@ -921,6 +897,8 @@ static const struct v4l2_ioctl_ops bcap_ioctl_ops = { .vidioc_g_std = bcap_g_std, .vidioc_s_dv_timings = bcap_s_dv_timings, .vidioc_g_dv_timings = bcap_g_dv_timings, + .vidioc_query_dv_timings = bcap_query_dv_timings, + .vidioc_enum_dv_timings = bcap_enum_dv_timings, .vidioc_reqbufs = bcap_reqbufs, .vidioc_querybuf = bcap_querybuf, .vidioc_qbuf = bcap_qbuf, @@ -929,11 +907,6 @@ static const struct v4l2_ioctl_ops bcap_ioctl_ops = { .vidioc_streamoff = bcap_streamoff, .vidioc_g_parm = bcap_g_parm, .vidioc_s_parm = bcap_s_parm, - .vidioc_g_chip_ident = bcap_g_chip_ident, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = bcap_dbg_g_register, - .vidioc_s_register = bcap_dbg_s_register, -#endif .vidioc_log_status = bcap_log_status, }; @@ -960,7 +933,7 @@ static int bcap_probe(struct platform_device *pdev) int ret; config = pdev->dev.platform_data; - if (!config) { + if (!config || !config->num_inputs) { v4l2_err(pdev->dev.driver, "Unable to get board config\n"); return -ENODEV; } @@ -1031,7 +1004,9 @@ static int bcap_probe(struct platform_device *pdev) q->mem_ops = &vb2_dma_contig_memops; q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - vb2_queue_init(q); + ret = vb2_queue_init(q); + if (ret) + goto err_free_handler; mutex_init(&bcap_dev->mutex); init_completion(&bcap_dev->comp); @@ -1067,11 +1042,6 @@ static int bcap_probe(struct platform_device *pdev) NULL); if (bcap_dev->sd) { int i; - if (!config->num_inputs) { - v4l2_err(&bcap_dev->v4l2_dev, - "Unable to work without input\n"); - goto err_unreg_vdev; - } /* update tvnorms from the sub devices */ for (i = 0; i < config->num_inputs; i++) @@ -1079,6 +1049,7 @@ static int bcap_probe(struct platform_device *pdev) } else { v4l2_err(&bcap_dev->v4l2_dev, "Unable to register sub device\n"); + ret = -ENODEV; goto err_unreg_vdev; } diff --git a/drivers/media/platform/blackfin/ppi.c b/drivers/media/platform/blackfin/ppi.c index 01b5b501347e..15e9c2bac2b1 100644 --- a/drivers/media/platform/blackfin/ppi.c +++ b/drivers/media/platform/blackfin/ppi.c @@ -266,6 +266,18 @@ static int ppi_set_params(struct ppi_if *ppi, struct ppi_params *params) bfin_write32(®->vcnt, params->height); if (params->int_mask) bfin_write32(®->imsk, params->int_mask & 0xFF); + if (ppi->ppi_control & PORT_DIR) { + u32 hsync_width, vsync_width, vsync_period; + + hsync_width = params->hsync + * params->bpp / params->dlen; + vsync_width = params->vsync * samples_per_line; + vsync_period = samples_per_line * params->frame; + bfin_write32(®->fs1_wlhb, hsync_width); + bfin_write32(®->fs1_paspl, samples_per_line); + bfin_write32(®->fs2_wlvb, vsync_width); + bfin_write32(®->fs2_palpf, vsync_period); + } break; } default: diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index 9d1481a60bd9..df4ada880e42 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -49,16 +49,14 @@ #define CODA_MAX_FRAMEBUFFERS 2 -#define MAX_W 720 -#define MAX_H 576 -#define CODA_MAX_FRAME_SIZE 0x90000 +#define MAX_W 8192 +#define MAX_H 8192 +#define CODA_MAX_FRAME_SIZE 0x100000 #define FMO_SLICE_SAVE_BUF_SIZE (32) #define CODA_DEFAULT_GAMMA 4096 #define MIN_W 176 #define MIN_H 144 -#define MAX_W 720 -#define MAX_H 576 #define S_ALIGN 1 /* multiple of 2 */ #define W_ALIGN 1 /* multiple of 2 */ @@ -67,7 +65,7 @@ #define fh_to_ctx(__fh) container_of(__fh, struct coda_ctx, fh) static int coda_debug; -module_param(coda_debug, int, 0); +module_param(coda_debug, int, 0644); MODULE_PARM_DESC(coda_debug, "Debug level (0-1)"); enum { @@ -75,11 +73,6 @@ enum { V4L2_M2M_DST = 1, }; -enum coda_fmt_type { - CODA_FMT_ENC, - CODA_FMT_RAW, -}; - enum coda_inst_type { CODA_INST_ENCODER, CODA_INST_DECODER, @@ -93,14 +86,21 @@ enum coda_product { struct coda_fmt { char *name; u32 fourcc; - enum coda_fmt_type type; +}; + +struct coda_codec { + u32 mode; + u32 src_fourcc; + u32 dst_fourcc; + u32 max_w; + u32 max_h; }; struct coda_devtype { char *firmware; enum coda_product product; - struct coda_fmt *formats; - unsigned int num_formats; + struct coda_codec *codecs; + unsigned int num_codecs; size_t workbuf_size; }; @@ -109,7 +109,7 @@ struct coda_q_data { unsigned int width; unsigned int height; unsigned int sizeimage; - struct coda_fmt *fmt; + unsigned int fourcc; }; struct coda_aux_buf { @@ -137,12 +137,12 @@ struct coda_dev { spinlock_t irqlock; struct mutex dev_mutex; + struct mutex coda_mutex; struct v4l2_m2m_dev *m2m_dev; struct vb2_alloc_ctx *alloc_ctx; struct list_head instances; unsigned long instance_mask; struct delayed_work timeout; - struct completion done; }; struct coda_params { @@ -164,11 +164,12 @@ struct coda_ctx { struct coda_dev *dev; struct list_head list; int aborting; - int rawstreamon; - int compstreamon; + int streamon_out; + int streamon_cap; u32 isequence; struct coda_q_data q_data[2]; enum coda_inst_type inst_type; + struct coda_codec *codec; enum v4l2_colorspace colorspace; struct coda_params params; struct v4l2_m2m_ctx *m2m_ctx; @@ -257,62 +258,89 @@ static struct coda_q_data *get_q_data(struct coda_ctx *ctx, } /* - * Add one array of supported formats for each version of Coda: - * i.MX27 -> codadx6 - * i.MX51 -> coda7 - * i.MX6 -> coda960 + * Array of all formats supported by any version of Coda: */ -static struct coda_fmt codadx6_formats[] = { +static struct coda_fmt coda_formats[] = { { - .name = "YUV 4:2:0 Planar", + .name = "YUV 4:2:0 Planar, YCbCr", .fourcc = V4L2_PIX_FMT_YUV420, - .type = CODA_FMT_RAW, - }, - { - .name = "H264 Encoded Stream", - .fourcc = V4L2_PIX_FMT_H264, - .type = CODA_FMT_ENC, }, { - .name = "MPEG4 Encoded Stream", - .fourcc = V4L2_PIX_FMT_MPEG4, - .type = CODA_FMT_ENC, - }, -}; - -static struct coda_fmt coda7_formats[] = { - { - .name = "YUV 4:2:0 Planar", - .fourcc = V4L2_PIX_FMT_YUV420, - .type = CODA_FMT_RAW, + .name = "YUV 4:2:0 Planar, YCrCb", + .fourcc = V4L2_PIX_FMT_YVU420, }, { .name = "H264 Encoded Stream", .fourcc = V4L2_PIX_FMT_H264, - .type = CODA_FMT_ENC, }, { .name = "MPEG4 Encoded Stream", .fourcc = V4L2_PIX_FMT_MPEG4, - .type = CODA_FMT_ENC, }, }; -static struct coda_fmt *find_format(struct coda_dev *dev, struct v4l2_format *f) +#define CODA_CODEC(mode, src_fourcc, dst_fourcc, max_w, max_h) \ + { mode, src_fourcc, dst_fourcc, max_w, max_h } + +/* + * Arrays of codecs supported by each given version of Coda: + * i.MX27 -> codadx6 + * i.MX5x -> coda7 + * i.MX6 -> coda960 + * Use V4L2_PIX_FMT_YUV420 as placeholder for all supported YUV 4:2:0 variants + */ +static struct coda_codec codadx6_codecs[] = { + CODA_CODEC(CODADX6_MODE_ENCODE_H264, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_H264, 720, 576), + CODA_CODEC(CODADX6_MODE_ENCODE_MP4, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_MPEG4, 720, 576), +}; + +static struct coda_codec coda7_codecs[] = { + CODA_CODEC(CODA7_MODE_ENCODE_H264, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_H264, 1280, 720), + CODA_CODEC(CODA7_MODE_ENCODE_MP4, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_MPEG4, 1280, 720), +}; + +static bool coda_format_is_yuv(u32 fourcc) +{ + switch (fourcc) { + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_YVU420: + return true; + default: + return false; + } +} + +/* + * Normalize all supported YUV 4:2:0 formats to the value used in the codec + * tables. + */ +static u32 coda_format_normalize_yuv(u32 fourcc) +{ + return coda_format_is_yuv(fourcc) ? V4L2_PIX_FMT_YUV420 : fourcc; +} + +static struct coda_codec *coda_find_codec(struct coda_dev *dev, int src_fourcc, + int dst_fourcc) { - struct coda_fmt *formats = dev->devtype->formats; - int num_formats = dev->devtype->num_formats; - unsigned int k; + struct coda_codec *codecs = dev->devtype->codecs; + int num_codecs = dev->devtype->num_codecs; + int k; + + src_fourcc = coda_format_normalize_yuv(src_fourcc); + dst_fourcc = coda_format_normalize_yuv(dst_fourcc); + if (src_fourcc == dst_fourcc) + return NULL; - for (k = 0; k < num_formats; k++) { - if (formats[k].fourcc == f->fmt.pix.pixelformat) + for (k = 0; k < num_codecs; k++) { + if (codecs[k].src_fourcc == src_fourcc && + codecs[k].dst_fourcc == dst_fourcc) break; } - if (k == num_formats) + if (k == num_codecs) return NULL; - return &formats[k]; + return &codecs[k]; } /* @@ -323,7 +351,7 @@ static int vidioc_querycap(struct file *file, void *priv, { strlcpy(cap->driver, CODA_NAME, sizeof(cap->driver)); strlcpy(cap->card, CODA_NAME, sizeof(cap->card)); - strlcpy(cap->bus_info, CODA_NAME, sizeof(cap->bus_info)); + strlcpy(cap->bus_info, "platform:" CODA_NAME, sizeof(cap->bus_info)); /* * This is only a mem-to-mem video device. The capture and output * device capability flags are left only for backward compatibility @@ -337,17 +365,34 @@ static int vidioc_querycap(struct file *file, void *priv, } static int enum_fmt(void *priv, struct v4l2_fmtdesc *f, - enum coda_fmt_type type) + enum v4l2_buf_type type) { struct coda_ctx *ctx = fh_to_ctx(priv); - struct coda_dev *dev = ctx->dev; - struct coda_fmt *formats = dev->devtype->formats; + struct coda_codec *codecs = ctx->dev->devtype->codecs; + struct coda_fmt *formats = coda_formats; struct coda_fmt *fmt; - int num_formats = dev->devtype->num_formats; - int i, num = 0; + int num_codecs = ctx->dev->devtype->num_codecs; + int num_formats = ARRAY_SIZE(coda_formats); + int i, k, num = 0; for (i = 0; i < num_formats; i++) { - if (formats[i].type == type) { + /* Both uncompressed formats are always supported */ + if (coda_format_is_yuv(formats[i].fourcc)) { + if (num == f->index) + break; + ++num; + continue; + } + /* Compressed formats may be supported, check the codec list */ + for (k = 0; k < num_codecs; k++) { + if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE && + formats[i].fourcc == codecs[k].dst_fourcc) + break; + if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT && + formats[i].fourcc == codecs[k].src_fourcc) + break; + } + if (k < num_codecs) { if (num == f->index) break; ++num; @@ -368,13 +413,13 @@ static int enum_fmt(void *priv, struct v4l2_fmtdesc *f, static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - return enum_fmt(priv, f, CODA_FMT_ENC); + return enum_fmt(priv, f, V4L2_BUF_TYPE_VIDEO_CAPTURE); } static int vidioc_enum_fmt_vid_out(struct file *file, void *priv, struct v4l2_fmtdesc *f) { - return enum_fmt(priv, f, CODA_FMT_RAW); + return enum_fmt(priv, f, V4L2_BUF_TYPE_VIDEO_OUTPUT); } static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) @@ -390,10 +435,10 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) q_data = get_q_data(ctx, f->type); f->fmt.pix.field = V4L2_FIELD_NONE; - f->fmt.pix.pixelformat = q_data->fmt->fourcc; + f->fmt.pix.pixelformat = q_data->fourcc; f->fmt.pix.width = q_data->width; f->fmt.pix.height = q_data->height; - if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) + if (coda_format_is_yuv(f->fmt.pix.pixelformat)) f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 2); else /* encoded formats h.264/mpeg4 */ f->fmt.pix.bytesperline = 0; @@ -404,8 +449,9 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) return 0; } -static int vidioc_try_fmt(struct coda_dev *dev, struct v4l2_format *f) +static int vidioc_try_fmt(struct coda_codec *codec, struct v4l2_format *f) { + unsigned int max_w, max_h; enum v4l2_field field; field = f->fmt.pix.field; @@ -418,12 +464,21 @@ static int vidioc_try_fmt(struct coda_dev *dev, struct v4l2_format *f) * if any of the dimensions is unsupported */ f->fmt.pix.field = field; - if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) { - v4l_bound_align_image(&f->fmt.pix.width, MIN_W, MAX_W, - W_ALIGN, &f->fmt.pix.height, - MIN_H, MAX_H, H_ALIGN, S_ALIGN); - f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 2); - f->fmt.pix.sizeimage = f->fmt.pix.width * + if (codec) { + max_w = codec->max_w; + max_h = codec->max_h; + } else { + max_w = MAX_W; + max_h = MAX_H; + } + v4l_bound_align_image(&f->fmt.pix.width, MIN_W, max_w, + W_ALIGN, &f->fmt.pix.height, + MIN_H, max_h, H_ALIGN, S_ALIGN); + + if (coda_format_is_yuv(f->fmt.pix.pixelformat)) { + /* Frame stride must be multiple of 8 */ + f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 8); + f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height * 3 / 2; } else { /*encoded formats h.264/mpeg4 */ f->fmt.pix.bytesperline = 0; @@ -436,57 +491,38 @@ static int vidioc_try_fmt(struct coda_dev *dev, struct v4l2_format *f) static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { - int ret; - struct coda_fmt *fmt; struct coda_ctx *ctx = fh_to_ctx(priv); + struct coda_codec *codec = NULL; - fmt = find_format(ctx->dev, f); - /* - * Since decoding support is not implemented yet do not allow - * CODA_FMT_RAW formats in the capture interface. - */ - if (!fmt || !(fmt->type == CODA_FMT_ENC)) - f->fmt.pix.pixelformat = V4L2_PIX_FMT_H264; + /* Determine codec by the encoded format */ + codec = coda_find_codec(ctx->dev, V4L2_PIX_FMT_YUV420, + f->fmt.pix.pixelformat); f->fmt.pix.colorspace = ctx->colorspace; - ret = vidioc_try_fmt(ctx->dev, f); - if (ret < 0) - return ret; - - return 0; + return vidioc_try_fmt(codec, f); } static int vidioc_try_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f) { struct coda_ctx *ctx = fh_to_ctx(priv); - struct coda_fmt *fmt; - int ret; + struct coda_codec *codec; - fmt = find_format(ctx->dev, f); - /* - * Since decoding support is not implemented yet do not allow - * CODA_FMT formats in the capture interface. - */ - if (!fmt || !(fmt->type == CODA_FMT_RAW)) - f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420; + /* Determine codec by encoded format, returns NULL if raw or invalid */ + codec = coda_find_codec(ctx->dev, f->fmt.pix.pixelformat, + V4L2_PIX_FMT_YUV420); if (!f->fmt.pix.colorspace) f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709; - ret = vidioc_try_fmt(ctx->dev, f); - if (ret < 0) - return ret; - - return 0; + return vidioc_try_fmt(codec, f); } static int vidioc_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f) { struct coda_q_data *q_data; struct vb2_queue *vq; - int ret; vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); if (!vq) @@ -501,18 +537,14 @@ static int vidioc_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f) return -EBUSY; } - ret = vidioc_try_fmt(ctx->dev, f); - if (ret) - return ret; - - q_data->fmt = find_format(ctx->dev, f); + q_data->fourcc = f->fmt.pix.pixelformat; q_data->width = f->fmt.pix.width; q_data->height = f->fmt.pix.height; q_data->sizeimage = f->fmt.pix.sizeimage; v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, "Setting format for type %d, wxh: %dx%d, fmt: %d\n", - f->type, q_data->width, q_data->height, q_data->fmt->fourcc); + f->type, q_data->width, q_data->height, q_data->fourcc); return 0; } @@ -520,13 +552,14 @@ static int vidioc_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f) static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f) { + struct coda_ctx *ctx = fh_to_ctx(priv); int ret; ret = vidioc_try_fmt_vid_cap(file, priv, f); if (ret) return ret; - return vidioc_s_fmt(fh_to_ctx(priv), f); + return vidioc_s_fmt(ctx, f); } static int vidioc_s_fmt_vid_out(struct file *file, void *priv, @@ -569,6 +602,14 @@ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); } +static int vidioc_expbuf(struct file *file, void *priv, + struct v4l2_exportbuffer *eb) +{ + struct coda_ctx *ctx = fh_to_ctx(priv); + + return v4l2_m2m_expbuf(file, ctx->m2m_ctx, eb); +} + static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) { struct coda_ctx *ctx = fh_to_ctx(priv); @@ -617,6 +658,7 @@ static const struct v4l2_ioctl_ops coda_ioctl_ops = { .vidioc_querybuf = vidioc_querybuf, .vidioc_qbuf = vidioc_qbuf, + .vidioc_expbuf = vidioc_expbuf, .vidioc_dqbuf = vidioc_dqbuf, .vidioc_create_bufs = vidioc_create_bufs, @@ -639,11 +681,13 @@ static void coda_device_run(void *m2m_priv) u32 pic_stream_buffer_addr, pic_stream_buffer_size; u32 dst_fourcc; + mutex_lock(&dev->coda_mutex); + src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); - dst_fourcc = q_data_dst->fmt->fourcc; + dst_fourcc = q_data_dst->fourcc; src_buf->v4l2_buf.sequence = ctx->isequence; dst_buf->v4l2_buf.sequence = ctx->isequence; @@ -725,9 +769,20 @@ static void coda_device_run(void *m2m_priv) picture_y = vb2_dma_contig_plane_dma_addr(src_buf, 0); - picture_cb = picture_y + q_data_src->width * q_data_src->height; - picture_cr = picture_cb + q_data_src->width / 2 * - q_data_src->height / 2; + switch (q_data_src->fourcc) { + case V4L2_PIX_FMT_YVU420: + /* Switch Cb and Cr for YVU420 format */ + picture_cr = picture_y + q_data_src->width * q_data_src->height; + picture_cb = picture_cr + q_data_src->width / 2 * + q_data_src->height / 2; + break; + case V4L2_PIX_FMT_YUV420: + default: + picture_cb = picture_y + q_data_src->width * q_data_src->height; + picture_cr = picture_cb + q_data_src->width / 2 * + q_data_src->height / 2; + break; + } coda_write(dev, picture_y, CODA_CMD_ENC_PIC_SRC_ADDR_Y); coda_write(dev, picture_cb, CODA_CMD_ENC_PIC_SRC_ADDR_CB); @@ -748,7 +803,6 @@ static void coda_device_run(void *m2m_priv) /* 1 second timeout in case CODA locks up */ schedule_delayed_work(&dev->timeout, HZ); - INIT_COMPLETION(dev->done); coda_command_async(ctx, CODA_COMMAND_PIC_RUN); } @@ -767,6 +821,12 @@ static int coda_job_ready(void *m2m_priv) return 0; } + if (ctx->aborting) { + v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, + "not ready: aborting\n"); + return 0; + } + v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, "job ready\n"); return 1; @@ -775,14 +835,11 @@ static int coda_job_ready(void *m2m_priv) static void coda_job_abort(void *priv) { struct coda_ctx *ctx = priv; - struct coda_dev *dev = ctx->dev; ctx->aborting = 1; v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, "Aborting task\n"); - - v4l2_m2m_job_finish(dev->m2m_dev, ctx->m2m_ctx); } static void coda_lock(void *m2m_priv) @@ -809,7 +866,12 @@ static struct v4l2_m2m_ops coda_m2m_ops = { static void set_default_params(struct coda_ctx *ctx) { - struct coda_dev *dev = ctx->dev; + int max_w; + int max_h; + + ctx->codec = &ctx->dev->devtype->codecs[0]; + max_w = ctx->codec->max_w; + max_h = ctx->codec->max_h; ctx->params.codec_mode = CODA_MODE_INVALID; ctx->colorspace = V4L2_COLORSPACE_REC709; @@ -817,13 +879,13 @@ static void set_default_params(struct coda_ctx *ctx) ctx->aborting = 0; /* Default formats for output and input queues */ - ctx->q_data[V4L2_M2M_SRC].fmt = &dev->devtype->formats[0]; - ctx->q_data[V4L2_M2M_DST].fmt = &dev->devtype->formats[1]; - ctx->q_data[V4L2_M2M_SRC].width = MAX_W; - ctx->q_data[V4L2_M2M_SRC].height = MAX_H; - ctx->q_data[V4L2_M2M_SRC].sizeimage = (MAX_W * MAX_H * 3) / 2; - ctx->q_data[V4L2_M2M_DST].width = MAX_W; - ctx->q_data[V4L2_M2M_DST].height = MAX_H; + ctx->q_data[V4L2_M2M_SRC].fourcc = ctx->codec->src_fourcc; + ctx->q_data[V4L2_M2M_DST].fourcc = ctx->codec->dst_fourcc; + ctx->q_data[V4L2_M2M_SRC].width = max_w; + ctx->q_data[V4L2_M2M_SRC].height = max_h; + ctx->q_data[V4L2_M2M_SRC].sizeimage = (max_w * max_h * 3) / 2; + ctx->q_data[V4L2_M2M_DST].width = max_w; + ctx->q_data[V4L2_M2M_DST].height = max_h; ctx->q_data[V4L2_M2M_DST].sizeimage = CODA_MAX_FRAME_SIZE; } @@ -868,8 +930,6 @@ static int coda_buf_prepare(struct vb2_buffer *vb) return -EINVAL; } - vb2_set_plane_payload(vb, 0, q_data->sizeimage); - return 0; } @@ -906,21 +966,34 @@ static void coda_free_framebuffers(struct coda_ctx *ctx) } } +static void coda_parabuf_write(struct coda_ctx *ctx, int index, u32 value) +{ + struct coda_dev *dev = ctx->dev; + u32 *p = ctx->parabuf.vaddr; + + if (dev->devtype->product == CODA_DX6) + p[index] = value; + else + p[index ^ 1] = value; +} + static int coda_alloc_framebuffers(struct coda_ctx *ctx, struct coda_q_data *q_data, u32 fourcc) { struct coda_dev *dev = ctx->dev; int height = q_data->height; - int width = q_data->width; - u32 *p; + dma_addr_t paddr; + int ysize; int i; + ysize = round_up(q_data->width, 8) * height; + /* Allocate frame buffers */ ctx->num_internal_frames = CODA_MAX_FRAMEBUFFERS; for (i = 0; i < ctx->num_internal_frames; i++) { ctx->internal_frames[i].size = q_data->sizeimage; if (fourcc == V4L2_PIX_FMT_H264 && dev->devtype->product != CODA_DX6) - ctx->internal_frames[i].size += width / 2 * height / 2; + ctx->internal_frames[i].size += ysize/4; ctx->internal_frames[i].vaddr = dma_alloc_coherent( &dev->plat_dev->dev, ctx->internal_frames[i].size, &ctx->internal_frames[i].paddr, GFP_KERNEL); @@ -931,32 +1004,14 @@ static int coda_alloc_framebuffers(struct coda_ctx *ctx, struct coda_q_data *q_d } /* Register frame buffers in the parameter buffer */ - p = ctx->parabuf.vaddr; + for (i = 0; i < ctx->num_internal_frames; i++) { + paddr = ctx->internal_frames[i].paddr; + coda_parabuf_write(ctx, i * 3 + 0, paddr); /* Y */ + coda_parabuf_write(ctx, i * 3 + 1, paddr + ysize); /* Cb */ + coda_parabuf_write(ctx, i * 3 + 2, paddr + ysize + ysize/4); /* Cr */ - if (dev->devtype->product == CODA_DX6) { - for (i = 0; i < ctx->num_internal_frames; i++) { - p[i * 3] = ctx->internal_frames[i].paddr; /* Y */ - p[i * 3 + 1] = p[i * 3] + width * height; /* Cb */ - p[i * 3 + 2] = p[i * 3 + 1] + width / 2 * height / 2; /* Cr */ - } - } else { - for (i = 0; i < ctx->num_internal_frames; i += 2) { - p[i * 3 + 1] = ctx->internal_frames[i].paddr; /* Y */ - p[i * 3] = p[i * 3 + 1] + width * height; /* Cb */ - p[i * 3 + 3] = p[i * 3] + (width / 2) * (height / 2); /* Cr */ - - if (fourcc == V4L2_PIX_FMT_H264) - p[96 + i + 1] = p[i * 3 + 3] + (width / 2) * (height / 2); - - if (i + 1 < ctx->num_internal_frames) { - p[i * 3 + 2] = ctx->internal_frames[i+1].paddr; /* Y */ - p[i * 3 + 5] = p[i * 3 + 2] + width * height ; /* Cb */ - p[i * 3 + 4] = p[i * 3 + 5] + (width / 2) * (height / 2); /* Cr */ - - if (fourcc == V4L2_PIX_FMT_H264) - p[96 + i] = p[i * 3 + 4] + (width / 2) * (height / 2); - } - } + if (dev->devtype->product != CODA_DX6 && fourcc == V4L2_PIX_FMT_H264) + coda_parabuf_write(ctx, 96 + i, ctx->internal_frames[i].paddr + ysize + ysize/4 + ysize/4); } return 0; @@ -980,6 +1035,28 @@ static int coda_h264_padding(int size, char *p) return nal_size; } +static int coda_encode_header(struct coda_ctx *ctx, struct vb2_buffer *buf, + int header_code, u8 *header, int *size) +{ + struct coda_dev *dev = ctx->dev; + int ret; + + coda_write(dev, vb2_dma_contig_plane_dma_addr(buf, 0), + CODA_CMD_ENC_HEADER_BB_START); + coda_write(dev, vb2_plane_size(buf, 0), CODA_CMD_ENC_HEADER_BB_SIZE); + coda_write(dev, header_code, CODA_CMD_ENC_HEADER_CODE); + ret = coda_command_sync(ctx, CODA_COMMAND_ENCODE_HEADER); + if (ret < 0) { + v4l2_err(&dev->v4l2_dev, "CODA_COMMAND_ENCODE_HEADER timeout\n"); + return ret; + } + *size = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->idx)) - + coda_read(dev, CODA_CMD_ENC_HEADER_BB_START); + memcpy(header, vb2_plane_vaddr(buf, 0), *size); + + return 0; +} + static int coda_start_streaming(struct vb2_queue *q, unsigned int count) { struct coda_ctx *ctx = vb2_get_drv_priv(q); @@ -990,43 +1067,38 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) struct vb2_buffer *buf; u32 dst_fourcc; u32 value; - int ret; + int ret = 0; if (count < 1) return -EINVAL; if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) - ctx->rawstreamon = 1; + ctx->streamon_out = 1; else - ctx->compstreamon = 1; + ctx->streamon_cap = 1; + + q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); + if (ctx->streamon_out) { + if (coda_format_is_yuv(q_data_src->fourcc)) + ctx->inst_type = CODA_INST_ENCODER; + else + ctx->inst_type = CODA_INST_DECODER; + } /* Don't start the coda unless both queues are on */ - if (!(ctx->rawstreamon & ctx->compstreamon)) + if (!(ctx->streamon_out & ctx->streamon_cap)) return 0; - if (coda_isbusy(dev)) - if (wait_for_completion_interruptible_timeout(&dev->done, HZ) <= 0) - return -EBUSY; - ctx->gopcounter = ctx->params.gop_size - 1; - - q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); bitstream_buf = vb2_dma_contig_plane_dma_addr(buf, 0); q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); bitstream_size = q_data_dst->sizeimage; - dst_fourcc = q_data_dst->fmt->fourcc; - - /* Find out whether coda must encode or decode */ - if (q_data_src->fmt->type == CODA_FMT_RAW && - q_data_dst->fmt->type == CODA_FMT_ENC) { - ctx->inst_type = CODA_INST_ENCODER; - } else if (q_data_src->fmt->type == CODA_FMT_ENC && - q_data_dst->fmt->type == CODA_FMT_RAW) { - ctx->inst_type = CODA_INST_DECODER; - v4l2_err(v4l2_dev, "decoding not supported.\n"); - return -EINVAL; - } else { + dst_fourcc = q_data_dst->fourcc; + + ctx->codec = coda_find_codec(ctx->dev, q_data_src->fourcc, + q_data_dst->fourcc); + if (!ctx->codec) { v4l2_err(v4l2_dev, "couldn't tell instance type.\n"); return -EINVAL; } @@ -1035,6 +1107,9 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) v4l2_err(v4l2_dev, "coda is not initialized.\n"); return -EFAULT; } + + mutex_lock(&dev->coda_mutex); + coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR); coda_write(dev, bitstream_buf, CODA_REG_BIT_RD_PTR(ctx->idx)); coda_write(dev, bitstream_buf, CODA_REG_BIT_WR_PTR(ctx->idx)); @@ -1057,38 +1132,31 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) switch (dev->devtype->product) { case CODA_DX6: value = (q_data_src->width & CODADX6_PICWIDTH_MASK) << CODADX6_PICWIDTH_OFFSET; + value |= (q_data_src->height & CODADX6_PICHEIGHT_MASK) << CODA_PICHEIGHT_OFFSET; break; default: value = (q_data_src->width & CODA7_PICWIDTH_MASK) << CODA7_PICWIDTH_OFFSET; + value |= (q_data_src->height & CODA7_PICHEIGHT_MASK) << CODA_PICHEIGHT_OFFSET; } - value |= (q_data_src->height & CODA_PICHEIGHT_MASK) << CODA_PICHEIGHT_OFFSET; coda_write(dev, value, CODA_CMD_ENC_SEQ_SRC_SIZE); coda_write(dev, ctx->params.framerate, CODA_CMD_ENC_SEQ_SRC_F_RATE); + ctx->params.codec_mode = ctx->codec->mode; switch (dst_fourcc) { case V4L2_PIX_FMT_MPEG4: - if (dev->devtype->product == CODA_DX6) - ctx->params.codec_mode = CODADX6_MODE_ENCODE_MP4; - else - ctx->params.codec_mode = CODA7_MODE_ENCODE_MP4; - coda_write(dev, CODA_STD_MPEG4, CODA_CMD_ENC_SEQ_COD_STD); coda_write(dev, 0, CODA_CMD_ENC_SEQ_MP4_PARA); break; case V4L2_PIX_FMT_H264: - if (dev->devtype->product == CODA_DX6) - ctx->params.codec_mode = CODADX6_MODE_ENCODE_H264; - else - ctx->params.codec_mode = CODA7_MODE_ENCODE_H264; - coda_write(dev, CODA_STD_H264, CODA_CMD_ENC_SEQ_COD_STD); coda_write(dev, 0, CODA_CMD_ENC_SEQ_264_PARA); break; default: v4l2_err(v4l2_dev, "dst format (0x%08x) invalid.\n", dst_fourcc); - return -EINVAL; + ret = -EINVAL; + goto out; } switch (ctx->params.slice_mode) { @@ -1129,8 +1197,14 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) value = (CODA_DEFAULT_GAMMA & CODA_GAMMA_MASK) << CODA_GAMMA_OFFSET; coda_write(dev, value, CODA_CMD_ENC_SEQ_RC_GAMMA); - value = (CODA_DEFAULT_GAMMA > 0) << CODA_OPTION_GAMMA_OFFSET; - value |= (0 & CODA_OPTION_SLICEREPORT_MASK) << CODA_OPTION_SLICEREPORT_OFFSET; + if (CODA_DEFAULT_GAMMA > 0) { + if (dev->devtype->product == CODA_DX6) + value = 1 << CODADX6_OPTION_GAMMA_OFFSET; + else + value = 1 << CODA7_OPTION_GAMMA_OFFSET; + } else { + value = 0; + } coda_write(dev, value, CODA_CMD_ENC_SEQ_OPTION); if (dst_fourcc == V4L2_PIX_FMT_H264) { @@ -1145,17 +1219,23 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) } } - if (coda_command_sync(ctx, CODA_COMMAND_SEQ_INIT)) { + ret = coda_command_sync(ctx, CODA_COMMAND_SEQ_INIT); + if (ret < 0) { v4l2_err(v4l2_dev, "CODA_COMMAND_SEQ_INIT timeout\n"); - return -ETIMEDOUT; + goto out; } - if (coda_read(dev, CODA_RET_ENC_SEQ_SUCCESS) == 0) - return -EFAULT; + if (coda_read(dev, CODA_RET_ENC_SEQ_SUCCESS) == 0) { + v4l2_err(v4l2_dev, "CODA_COMMAND_SEQ_INIT failed\n"); + ret = -EFAULT; + goto out; + } ret = coda_alloc_framebuffers(ctx, q_data_src, dst_fourcc); - if (ret < 0) - return ret; + if (ret < 0) { + v4l2_err(v4l2_dev, "failed to allocate framebuffers\n"); + goto out; + } coda_write(dev, ctx->num_internal_frames, CODA_CMD_SET_FRAME_BUF_NUM); coda_write(dev, round_up(q_data_src->width, 8), CODA_CMD_SET_FRAME_BUF_STRIDE); @@ -1167,9 +1247,10 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) coda_write(dev, dev->iram_paddr + 68 * 1024, CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR); coda_write(dev, 0x0, CODA7_CMD_SET_FRAME_AXI_OVL_ADDR); } - if (coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF)) { + ret = coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF); + if (ret < 0) { v4l2_err(v4l2_dev, "CODA_COMMAND_SET_FRAME_BUF timeout\n"); - return -ETIMEDOUT; + goto out; } /* Save stream headers */ @@ -1180,33 +1261,22 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) * Get SPS in the first frame and copy it to an * intermediate buffer. */ - coda_write(dev, vb2_dma_contig_plane_dma_addr(buf, 0), CODA_CMD_ENC_HEADER_BB_START); - coda_write(dev, bitstream_size, CODA_CMD_ENC_HEADER_BB_SIZE); - coda_write(dev, CODA_HEADER_H264_SPS, CODA_CMD_ENC_HEADER_CODE); - if (coda_command_sync(ctx, CODA_COMMAND_ENCODE_HEADER)) { - v4l2_err(v4l2_dev, "CODA_COMMAND_ENCODE_HEADER timeout\n"); - return -ETIMEDOUT; - } - ctx->vpu_header_size[0] = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->idx)) - - coda_read(dev, CODA_CMD_ENC_HEADER_BB_START); - memcpy(&ctx->vpu_header[0][0], vb2_plane_vaddr(buf, 0), - ctx->vpu_header_size[0]); + ret = coda_encode_header(ctx, buf, CODA_HEADER_H264_SPS, + &ctx->vpu_header[0][0], + &ctx->vpu_header_size[0]); + if (ret < 0) + goto out; /* * Get PPS in the first frame and copy it to an * intermediate buffer. */ - coda_write(dev, vb2_dma_contig_plane_dma_addr(buf, 0), CODA_CMD_ENC_HEADER_BB_START); - coda_write(dev, bitstream_size, CODA_CMD_ENC_HEADER_BB_SIZE); - coda_write(dev, CODA_HEADER_H264_PPS, CODA_CMD_ENC_HEADER_CODE); - if (coda_command_sync(ctx, CODA_COMMAND_ENCODE_HEADER)) { - v4l2_err(v4l2_dev, "CODA_COMMAND_ENCODE_HEADER timeout\n"); - return -ETIMEDOUT; - } - ctx->vpu_header_size[1] = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->idx)) - - coda_read(dev, CODA_CMD_ENC_HEADER_BB_START); - memcpy(&ctx->vpu_header[1][0], vb2_plane_vaddr(buf, 0), - ctx->vpu_header_size[1]); + ret = coda_encode_header(ctx, buf, CODA_HEADER_H264_PPS, + &ctx->vpu_header[1][0], + &ctx->vpu_header_size[1]); + if (ret < 0) + goto out; + /* * Length of H.264 headers is variable and thus it might not be * aligned for the coda to append the encoded frame. In that is @@ -1222,48 +1292,32 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count) * Get VOS in the first frame and copy it to an * intermediate buffer */ - coda_write(dev, vb2_dma_contig_plane_dma_addr(buf, 0), CODA_CMD_ENC_HEADER_BB_START); - coda_write(dev, bitstream_size, CODA_CMD_ENC_HEADER_BB_SIZE); - coda_write(dev, CODA_HEADER_MP4V_VOS, CODA_CMD_ENC_HEADER_CODE); - if (coda_command_sync(ctx, CODA_COMMAND_ENCODE_HEADER)) { - v4l2_err(v4l2_dev, "CODA_COMMAND_ENCODE_HEADER timeout\n"); - return -ETIMEDOUT; - } - ctx->vpu_header_size[0] = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->idx)) - - coda_read(dev, CODA_CMD_ENC_HEADER_BB_START); - memcpy(&ctx->vpu_header[0][0], vb2_plane_vaddr(buf, 0), - ctx->vpu_header_size[0]); - - coda_write(dev, vb2_dma_contig_plane_dma_addr(buf, 0), CODA_CMD_ENC_HEADER_BB_START); - coda_write(dev, bitstream_size, CODA_CMD_ENC_HEADER_BB_SIZE); - coda_write(dev, CODA_HEADER_MP4V_VIS, CODA_CMD_ENC_HEADER_CODE); - if (coda_command_sync(ctx, CODA_COMMAND_ENCODE_HEADER)) { - v4l2_err(v4l2_dev, "CODA_COMMAND_ENCODE_HEADER failed\n"); - return -ETIMEDOUT; - } - ctx->vpu_header_size[1] = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->idx)) - - coda_read(dev, CODA_CMD_ENC_HEADER_BB_START); - memcpy(&ctx->vpu_header[1][0], vb2_plane_vaddr(buf, 0), - ctx->vpu_header_size[1]); - - coda_write(dev, vb2_dma_contig_plane_dma_addr(buf, 0), CODA_CMD_ENC_HEADER_BB_START); - coda_write(dev, bitstream_size, CODA_CMD_ENC_HEADER_BB_SIZE); - coda_write(dev, CODA_HEADER_MP4V_VOL, CODA_CMD_ENC_HEADER_CODE); - if (coda_command_sync(ctx, CODA_COMMAND_ENCODE_HEADER)) { - v4l2_err(v4l2_dev, "CODA_COMMAND_ENCODE_HEADER failed\n"); - return -ETIMEDOUT; - } - ctx->vpu_header_size[2] = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->idx)) - - coda_read(dev, CODA_CMD_ENC_HEADER_BB_START); - memcpy(&ctx->vpu_header[2][0], vb2_plane_vaddr(buf, 0), - ctx->vpu_header_size[2]); + ret = coda_encode_header(ctx, buf, CODA_HEADER_MP4V_VOS, + &ctx->vpu_header[0][0], + &ctx->vpu_header_size[0]); + if (ret < 0) + goto out; + + ret = coda_encode_header(ctx, buf, CODA_HEADER_MP4V_VIS, + &ctx->vpu_header[1][0], + &ctx->vpu_header_size[1]); + if (ret < 0) + goto out; + + ret = coda_encode_header(ctx, buf, CODA_HEADER_MP4V_VOL, + &ctx->vpu_header[2][0], + &ctx->vpu_header_size[2]); + if (ret < 0) + goto out; break; default: /* No more formats need to save headers at the moment */ break; } - return 0; +out: + mutex_unlock(&dev->coda_mutex); + return ret; } static int coda_stop_streaming(struct vb2_queue *q) @@ -1274,26 +1328,20 @@ static int coda_stop_streaming(struct vb2_queue *q) if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, "%s: output\n", __func__); - ctx->rawstreamon = 0; + ctx->streamon_out = 0; } else { v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, "%s: capture\n", __func__); - ctx->compstreamon = 0; + ctx->streamon_cap = 0; } /* Don't stop the coda unless both queues are off */ - if (ctx->rawstreamon || ctx->compstreamon) + if (ctx->streamon_out || ctx->streamon_cap) return 0; - if (coda_isbusy(dev)) { - if (wait_for_completion_interruptible_timeout(&dev->done, HZ) <= 0) { - v4l2_warn(&dev->v4l2_dev, - "%s: timeout, sending SEQ_END anyway\n", __func__); - } - } - cancel_delayed_work(&dev->timeout); + mutex_lock(&dev->coda_mutex); v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "%s: sent command 'SEQ_END' to coda\n", __func__); if (coda_command_sync(ctx, CODA_COMMAND_SEQ_END)) { @@ -1301,6 +1349,7 @@ static int coda_stop_streaming(struct vb2_queue *q) "CODA_COMMAND_SEQ_END failed\n"); return -ETIMEDOUT; } + mutex_unlock(&dev->coda_mutex); coda_free_framebuffers(ctx); @@ -1431,7 +1480,7 @@ static int coda_queue_init(void *priv, struct vb2_queue *src_vq, int ret; src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - src_vq->io_modes = VB2_MMAP | VB2_USERPTR; + src_vq->io_modes = VB2_DMABUF | VB2_MMAP | VB2_USERPTR; src_vq->drv_priv = ctx; src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); src_vq->ops = &coda_qops; @@ -1443,7 +1492,7 @@ static int coda_queue_init(void *priv, struct vb2_queue *src_vq, return ret; dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - dst_vq->io_modes = VB2_MMAP | VB2_USERPTR; + dst_vq->io_modes = VB2_DMABUF | VB2_MMAP | VB2_USERPTR; dst_vq->drv_priv = ctx; dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); dst_vq->ops = &coda_qops; @@ -1484,7 +1533,7 @@ static int coda_open(struct file *file) ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &coda_queue_init); if (IS_ERR(ctx->m2m_ctx)) { - int ret = PTR_ERR(ctx->m2m_ctx); + ret = PTR_ERR(ctx->m2m_ctx); v4l2_err(&dev->v4l2_dev, "%s return error (%d)\n", __func__, ret); @@ -1596,12 +1645,14 @@ static irqreturn_t coda_irq_handler(int irq, void *data) ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev); if (ctx == NULL) { v4l2_err(&dev->v4l2_dev, "Instance released before the end of transaction\n"); + mutex_unlock(&dev->coda_mutex); return IRQ_HANDLED; } if (ctx->aborting) { v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, "task has been aborted\n"); + mutex_unlock(&dev->coda_mutex); return IRQ_HANDLED; } @@ -1611,8 +1662,6 @@ static irqreturn_t coda_irq_handler(int irq, void *data) return IRQ_NONE; } - complete(&dev->done); - src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); @@ -1660,6 +1709,8 @@ static irqreturn_t coda_irq_handler(int irq, void *data) (dst_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) ? "KEYFRAME" : "PFRAME"); + mutex_unlock(&dev->coda_mutex); + v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->m2m_ctx); return IRQ_HANDLED; @@ -1671,12 +1722,7 @@ static void coda_timeout(struct work_struct *work) struct coda_dev *dev = container_of(to_delayed_work(work), struct coda_dev, timeout); - if (completion_done(&dev->done)) - return; - - complete(&dev->done); - - v4l2_err(&dev->v4l2_dev, "CODA PIC_RUN timeout, stopping all streams\n"); + dev_err(&dev->plat_dev->dev, "CODA PIC_RUN timeout, stopping all streams\n"); mutex_lock(&dev->dev_mutex); list_for_each_entry(ctx, &dev->instances, list) { @@ -1684,6 +1730,10 @@ static void coda_timeout(struct work_struct *work) v4l2_m2m_streamoff(NULL, ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); } mutex_unlock(&dev->dev_mutex); + + mutex_unlock(&dev->coda_mutex); + ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev); + v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->m2m_ctx); } static u32 coda_supported_firmwares[] = { @@ -1748,6 +1798,10 @@ static int coda_hw_init(struct coda_dev *dev) } } + /* Clear registers */ + for (i = 0; i < 64; i++) + coda_write(dev, 0, CODA_REG_BIT_CODE_BUF_ADDR + i * 4); + /* Tell the BIT where to find everything it needs */ coda_write(dev, dev->workbuf.paddr, CODA_REG_BIT_WORK_BUF_ADDR); @@ -1911,16 +1965,16 @@ enum coda_platform { static const struct coda_devtype coda_devdata[] = { [CODA_IMX27] = { - .firmware = "v4l-codadx6-imx27.bin", - .product = CODA_DX6, - .formats = codadx6_formats, - .num_formats = ARRAY_SIZE(codadx6_formats), + .firmware = "v4l-codadx6-imx27.bin", + .product = CODA_DX6, + .codecs = codadx6_codecs, + .num_codecs = ARRAY_SIZE(codadx6_codecs), }, [CODA_IMX53] = { - .firmware = "v4l-coda7541-imx53.bin", - .product = CODA_7541, - .formats = coda7_formats, - .num_formats = ARRAY_SIZE(coda7_formats), + .firmware = "v4l-coda7541-imx53.bin", + .product = CODA_7541, + .codecs = coda7_codecs, + .num_codecs = ARRAY_SIZE(coda7_codecs), }, }; @@ -1962,8 +2016,6 @@ static int coda_probe(struct platform_device *pdev) spin_lock_init(&dev->irqlock); INIT_LIST_HEAD(&dev->instances); INIT_DELAYED_WORK(&dev->timeout, coda_timeout); - init_completion(&dev->done); - complete(&dev->done); dev->plat_dev = pdev; dev->clk_per = devm_clk_get(&pdev->dev, "per"); @@ -1985,17 +2037,9 @@ static int coda_probe(struct platform_device *pdev) return -ENOENT; } - if (devm_request_mem_region(&pdev->dev, res->start, - resource_size(res), CODA_NAME) == NULL) { - dev_err(&pdev->dev, "failed to request memory region\n"); - return -ENOENT; - } - dev->regs_base = devm_ioremap(&pdev->dev, res->start, - resource_size(res)); - if (!dev->regs_base) { - dev_err(&pdev->dev, "failed to ioremap address region\n"); - return -ENOENT; - } + dev->regs_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(dev->regs_base)) + return PTR_ERR(dev->regs_base); /* IRQ */ irq = platform_get_irq(pdev, 0); @@ -2025,6 +2069,7 @@ static int coda_probe(struct platform_device *pdev) return ret; mutex_init(&dev->dev_mutex); + mutex_init(&dev->coda_mutex); pdev_id = of_id ? of_id->data : platform_get_device_id(pdev); diff --git a/drivers/media/platform/coda.h b/drivers/media/platform/coda.h index f3f5e43c1ac2..ace0bf0a3b9c 100644 --- a/drivers/media/platform/coda.h +++ b/drivers/media/platform/coda.h @@ -96,16 +96,12 @@ #define CODA_CMD_ENC_SEQ_BB_START 0x180 #define CODA_CMD_ENC_SEQ_BB_SIZE 0x184 #define CODA_CMD_ENC_SEQ_OPTION 0x188 -#define CODA_OPTION_GAMMA_OFFSET 7 -#define CODA_OPTION_GAMMA_MASK 0x01 +#define CODA7_OPTION_GAMMA_OFFSET 8 +#define CODADX6_OPTION_GAMMA_OFFSET 7 #define CODA_OPTION_LIMITQP_OFFSET 6 -#define CODA_OPTION_LIMITQP_MASK 0x01 #define CODA_OPTION_RCINTRAQP_OFFSET 5 -#define CODA_OPTION_RCINTRAQP_MASK 0x01 #define CODA_OPTION_FMO_OFFSET 4 -#define CODA_OPTION_FMO_MASK 0x01 #define CODA_OPTION_SLICEREPORT_OFFSET 1 -#define CODA_OPTION_SLICEREPORT_MASK 0x01 #define CODA_CMD_ENC_SEQ_COD_STD 0x18c #define CODA_STD_MPEG4 0 #define CODA_STD_H263 1 @@ -117,7 +113,8 @@ #define CODADX6_PICWIDTH_OFFSET 10 #define CODADX6_PICWIDTH_MASK 0x3ff #define CODA_PICHEIGHT_OFFSET 0 -#define CODA_PICHEIGHT_MASK 0x3ff +#define CODADX6_PICHEIGHT_MASK 0x3ff +#define CODA7_PICHEIGHT_MASK 0xffff #define CODA_CMD_ENC_SEQ_SRC_F_RATE 0x194 #define CODA_CMD_ENC_SEQ_MP4_PARA 0x198 #define CODA_MP4PARAM_VERID_OFFSET 6 diff --git a/drivers/media/platform/davinci/vpbe_display.c b/drivers/media/platform/davinci/vpbe_display.c index d0b375cf565f..e180ff7282d9 100644 --- a/drivers/media/platform/davinci/vpbe_display.c +++ b/drivers/media/platform/davinci/vpbe_display.c @@ -944,7 +944,7 @@ static int vpbe_display_s_fmt(struct file *file, void *priv, cfg->interlaced = vpbe_dev->current_timings.interlaced; if (V4L2_PIX_FMT_UYVY == pixfmt->pixelformat) - cfg->pixfmt = PIXFMT_YCbCrI; + cfg->pixfmt = PIXFMT_YCBCRI; /* Change of the default pixel format for both video windows */ if (V4L2_PIX_FMT_NV12 == pixfmt->pixelformat) { @@ -1593,31 +1593,6 @@ static int vpbe_display_release(struct file *file) return 0; } -#ifdef CONFIG_VIDEO_ADV_DEBUG -static int vpbe_display_g_register(struct file *file, void *priv, - struct v4l2_dbg_register *reg) -{ - struct v4l2_dbg_match *match = ®->match; - struct vpbe_fh *fh = file->private_data; - struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev; - - if (match->type >= 2) { - v4l2_subdev_call(vpbe_dev->venc, - core, - g_register, - reg); - } - - return 0; -} - -static int vpbe_display_s_register(struct file *file, void *priv, - const struct v4l2_dbg_register *reg) -{ - return 0; -} -#endif - /* vpbe capture ioctl operations */ static const struct v4l2_ioctl_ops vpbe_ioctl_ops = { .vidioc_querycap = vpbe_display_querycap, @@ -1644,10 +1619,6 @@ static const struct v4l2_ioctl_ops vpbe_ioctl_ops = { .vidioc_s_dv_timings = vpbe_display_s_dv_timings, .vidioc_g_dv_timings = vpbe_display_g_dv_timings, .vidioc_enum_dv_timings = vpbe_display_enum_dv_timings, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = vpbe_display_g_register, - .vidioc_s_register = vpbe_display_s_register, -#endif }; static struct v4l2_file_operations vpbe_fops = { diff --git a/drivers/media/platform/davinci/vpbe_osd.c b/drivers/media/platform/davinci/vpbe_osd.c index 396a51cbede7..6ed82e8b297b 100644 --- a/drivers/media/platform/davinci/vpbe_osd.c +++ b/drivers/media/platform/davinci/vpbe_osd.c @@ -119,7 +119,7 @@ static inline u32 osd_modify(struct osd_state *sd, u32 mask, u32 val, #define is_rgb_pixfmt(pixfmt) \ (((pixfmt) == PIXFMT_RGB565) || ((pixfmt) == PIXFMT_RGB888)) #define is_yc_pixfmt(pixfmt) \ - (((pixfmt) == PIXFMT_YCbCrI) || ((pixfmt) == PIXFMT_YCrCbI) || \ + (((pixfmt) == PIXFMT_YCBCRI) || ((pixfmt) == PIXFMT_YCRCBI) || \ ((pixfmt) == PIXFMT_NV12)) #define MAX_WIN_SIZE OSD_VIDWIN0XP_V0X #define MAX_LINE_LENGTH (OSD_VIDWIN0OFST_V0LO << 5) @@ -360,8 +360,8 @@ static void _osd_enable_color_key(struct osd_state *sd, osd_write(sd, colorkey & OSD_TRANSPVALL_RGBL, OSD_TRANSPVALL); break; - case PIXFMT_YCbCrI: - case PIXFMT_YCrCbI: + case PIXFMT_YCBCRI: + case PIXFMT_YCRCBI: if (sd->vpbe_type == VPBE_VERSION_3) osd_modify(sd, OSD_TRANSPVALU_Y, colorkey, OSD_TRANSPVALU); @@ -813,8 +813,8 @@ static int try_layer_config(struct osd_state *sd, enum osd_layer layer, if (osd->vpbe_type == VPBE_VERSION_1) bad_config = !is_vid_win(layer); break; - case PIXFMT_YCbCrI: - case PIXFMT_YCrCbI: + case PIXFMT_YCBCRI: + case PIXFMT_YCRCBI: bad_config = !is_vid_win(layer); break; case PIXFMT_RGB888: @@ -950,9 +950,9 @@ static void _osd_set_cbcr_order(struct osd_state *sd, * The caller must ensure that all windows using YC pixfmt use the same * Cb/Cr order. */ - if (pixfmt == PIXFMT_YCbCrI) + if (pixfmt == PIXFMT_YCBCRI) osd_clear(sd, OSD_MODE_CS, OSD_MODE); - else if (pixfmt == PIXFMT_YCrCbI) + else if (pixfmt == PIXFMT_YCRCBI) osd_set(sd, OSD_MODE_CS, OSD_MODE); } @@ -981,8 +981,8 @@ static void _osd_set_layer_config(struct osd_state *sd, enum osd_layer layer, winmd |= (2 << OSD_OSDWIN0MD_BMP0MD_SHIFT); _osd_enable_rgb888_pixblend(sd, OSDWIN_OSD0); break; - case PIXFMT_YCbCrI: - case PIXFMT_YCrCbI: + case PIXFMT_YCBCRI: + case PIXFMT_YCRCBI: winmd |= (3 << OSD_OSDWIN0MD_BMP0MD_SHIFT); break; default: @@ -1128,8 +1128,8 @@ static void _osd_set_layer_config(struct osd_state *sd, enum osd_layer layer, _osd_enable_rgb888_pixblend(sd, OSDWIN_OSD1); break; - case PIXFMT_YCbCrI: - case PIXFMT_YCrCbI: + case PIXFMT_YCBCRI: + case PIXFMT_YCRCBI: winmd |= (3 << OSD_OSDWIN1MD_BMP1MD_SHIFT); break; @@ -1508,7 +1508,7 @@ static int osd_initialize(struct osd_state *osd) _osd_init(osd); /* set default Cb/Cr order */ - osd->yc_pixfmt = PIXFMT_YCbCrI; + osd->yc_pixfmt = PIXFMT_YCBCRI; if (osd->vpbe_type == VPBE_VERSION_3) { /* diff --git a/drivers/media/platform/davinci/vpif.c b/drivers/media/platform/davinci/vpif.c index ea82a8bd2803..cd08e5248387 100644 --- a/drivers/media/platform/davinci/vpif.c +++ b/drivers/media/platform/davinci/vpif.c @@ -17,30 +17,26 @@ * GNU General Public License for more details. */ +#include <linux/err.h> #include <linux/init.h> +#include <linux/io.h> +#include <linux/kernel.h> #include <linux/module.h> #include <linux/platform_device.h> -#include <linux/spinlock.h> -#include <linux/kernel.h> -#include <linux/io.h> -#include <linux/err.h> #include <linux/pm_runtime.h> +#include <linux/spinlock.h> #include <linux/v4l2-dv-timings.h> -#include <mach/hardware.h> - #include "vpif.h" MODULE_DESCRIPTION("TI DaVinci Video Port Interface driver"); MODULE_LICENSE("GPL"); -#define VPIF_CH0_MAX_MODES (22) -#define VPIF_CH1_MAX_MODES (02) -#define VPIF_CH2_MAX_MODES (15) -#define VPIF_CH3_MAX_MODES (02) +#define VPIF_CH0_MAX_MODES 22 +#define VPIF_CH1_MAX_MODES 2 +#define VPIF_CH2_MAX_MODES 15 +#define VPIF_CH3_MAX_MODES 2 -static resource_size_t res_len; -static struct resource *res; spinlock_t vpif_lock; void __iomem *vpif_base; @@ -423,23 +419,12 @@ EXPORT_SYMBOL(vpif_channel_getfid); static int vpif_probe(struct platform_device *pdev) { - int status = 0; + static struct resource *res; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENOENT; - - res_len = resource_size(res); - - res = request_mem_region(res->start, res_len, res->name); - if (!res) - return -EBUSY; - - vpif_base = ioremap(res->start, res_len); - if (!vpif_base) { - status = -EBUSY; - goto fail; - } + vpif_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(vpif_base)) + return PTR_ERR(vpif_base); pm_runtime_enable(&pdev->dev); pm_runtime_get(&pdev->dev); @@ -447,17 +432,11 @@ static int vpif_probe(struct platform_device *pdev) spin_lock_init(&vpif_lock); dev_info(&pdev->dev, "vpif probe success\n"); return 0; - -fail: - release_mem_region(res->start, res_len); - return status; } static int vpif_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - iounmap(vpif_base); - release_mem_region(res->start, res_len); return 0; } diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c index 5f98df1fc8a0..5514175bbd07 100644 --- a/drivers/media/platform/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c @@ -18,28 +18,16 @@ * TODO : add support for VBI & HBI data service * add static buffer allocation */ -#include <linux/kernel.h> -#include <linux/init.h> + #include <linux/module.h> -#include <linux/errno.h> -#include <linux/fs.h> -#include <linux/mm.h> #include <linux/interrupt.h> -#include <linux/workqueue.h> -#include <linux/string.h> -#include <linux/videodev2.h> -#include <linux/wait.h> -#include <linux/time.h> -#include <linux/i2c.h> #include <linux/platform_device.h> -#include <linux/io.h> #include <linux/slab.h> -#include <media/v4l2-device.h> + #include <media/v4l2-ioctl.h> -#include <media/v4l2-chip-ident.h> -#include "vpif_capture.h" #include "vpif.h" +#include "vpif_capture.h" MODULE_DESCRIPTION("TI DaVinci VPIF Capture driver"); MODULE_LICENSE("GPL"); @@ -1874,66 +1862,6 @@ static int vpif_g_dv_timings(struct file *file, void *priv, } /* - * vpif_g_chip_ident() - Identify the chip - * @file: file ptr - * @priv: file handle - * @chip: chip identity - * - * Returns zero or -EINVAL if read operations fails. - */ -static int vpif_g_chip_ident(struct file *file, void *priv, - struct v4l2_dbg_chip_ident *chip) -{ - chip->ident = V4L2_IDENT_NONE; - chip->revision = 0; - if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER && - chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR) { - vpif_dbg(2, debug, "match_type is invalid.\n"); - return -EINVAL; - } - - return v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 0, core, - g_chip_ident, chip); -} - -#ifdef CONFIG_VIDEO_ADV_DEBUG -/* - * vpif_dbg_g_register() - Read register - * @file: file ptr - * @priv: file handle - * @reg: register to be read - * - * Debugging only - * Returns zero or -EINVAL if read operations fails. - */ -static int vpif_dbg_g_register(struct file *file, void *priv, - struct v4l2_dbg_register *reg){ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - - return v4l2_subdev_call(ch->sd, core, g_register, reg); -} - -/* - * vpif_dbg_s_register() - Write to register - * @file: file ptr - * @priv: file handle - * @reg: register to be modified - * - * Debugging only - * Returns zero or -EINVAL if write operations fails. - */ -static int vpif_dbg_s_register(struct file *file, void *priv, - const struct v4l2_dbg_register *reg) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - - return v4l2_subdev_call(ch->sd, core, s_register, reg); -} -#endif - -/* * vpif_log_status() - Status information * @file: file ptr * @priv: file handle @@ -1974,11 +1902,6 @@ static const struct v4l2_ioctl_ops vpif_ioctl_ops = { .vidioc_query_dv_timings = vpif_query_dv_timings, .vidioc_s_dv_timings = vpif_s_dv_timings, .vidioc_g_dv_timings = vpif_g_dv_timings, - .vidioc_g_chip_ident = vpif_g_chip_ident, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = vpif_dbg_g_register, - .vidioc_s_register = vpif_dbg_s_register, -#endif .vidioc_log_status = vpif_log_status, }; @@ -2092,16 +2015,13 @@ static __init int vpif_probe(struct platform_device *pdev) } while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, res_idx))) { - for (i = res->start; i <= res->end; i++) { - if (request_irq(i, vpif_channel_isr, IRQF_SHARED, - "VPIF_Capture", (void *) - (&vpif_obj.dev[res_idx]->channel_id))) { - err = -EBUSY; - for (j = 0; j < i; j++) - free_irq(j, (void *) - (&vpif_obj.dev[res_idx]->channel_id)); - goto vpif_int_err; - } + err = devm_request_irq(&pdev->dev, res->start, vpif_channel_isr, + IRQF_SHARED, "VPIF_Capture", + (void *)(&vpif_obj.dev[res_idx]-> + channel_id)); + if (err) { + err = -EINVAL; + goto vpif_unregister; } res_idx++; } @@ -2117,7 +2037,7 @@ static __init int vpif_probe(struct platform_device *pdev) video_device_release(ch->video_dev); } err = -ENOMEM; - goto vpif_int_err; + goto vpif_unregister; } /* Initialize field of video device */ @@ -2170,6 +2090,7 @@ static __init int vpif_probe(struct platform_device *pdev) if (!vpif_obj.sd[i]) { vpif_err("Error registering v4l2 subdevice\n"); + err = -ENODEV; goto probe_subdev_out; } v4l2_info(&vpif_obj.v4l2_dev, "registered sub device %s\n", @@ -2217,13 +2138,9 @@ vpif_sd_error: /* Note: does nothing if ch->video_dev == NULL */ video_device_release(ch->video_dev); } -vpif_int_err: +vpif_unregister: v4l2_device_unregister(&vpif_obj.v4l2_dev); - for (i = 0; i < res_idx; i++) { - res = platform_get_resource(pdev, IORESOURCE_IRQ, i); - for (j = res->start; j <= res->end; j++) - free_irq(j, (void *)(&vpif_obj.dev[i]->channel_id)); - } + return err; } @@ -2235,17 +2152,19 @@ vpif_int_err: */ static int vpif_remove(struct platform_device *device) { - int i; struct channel_obj *ch; + int i; v4l2_device_unregister(&vpif_obj.v4l2_dev); + kfree(vpif_obj.sd); /* un-register device */ for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) { /* Get the pointer to the channel object */ ch = vpif_obj.dev[i]; /* Unregister video device */ video_unregister_device(ch->video_dev); + kfree(vpif_obj.dev[i]); } return 0; } @@ -2336,47 +2255,4 @@ static __refdata struct platform_driver vpif_driver = { .remove = vpif_remove, }; -/** - * vpif_init: initialize the vpif driver - * - * This function registers device and driver to the kernel, requests irq - * handler and allocates memory - * for channel objects - */ -static __init int vpif_init(void) -{ - return platform_driver_register(&vpif_driver); -} - -/** - * vpif_cleanup : This function clean up the vpif capture resources - * - * This will un-registers device and driver to the kernel, frees - * requested irq handler and de-allocates memory allocated for channel - * objects. - */ -static void vpif_cleanup(void) -{ - struct platform_device *pdev; - struct resource *res; - int irq_num; - int i = 0; - - pdev = container_of(vpif_dev, struct platform_device, dev); - while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, i))) { - for (irq_num = res->start; irq_num <= res->end; irq_num++) - free_irq(irq_num, - (void *)(&vpif_obj.dev[i]->channel_id)); - i++; - } - - platform_driver_unregister(&vpif_driver); - - kfree(vpif_obj.sd); - for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) - kfree(vpif_obj.dev[i]); -} - -/* Function for module initialization and cleanup */ -module_init(vpif_init); -module_exit(vpif_cleanup); +module_platform_driver(vpif_driver); diff --git a/drivers/media/platform/davinci/vpif_capture.h b/drivers/media/platform/davinci/vpif_capture.h index 3d3c1e5cd5d4..0ebb31260369 100644 --- a/drivers/media/platform/davinci/vpif_capture.h +++ b/drivers/media/platform/davinci/vpif_capture.h @@ -22,11 +22,8 @@ #ifdef __KERNEL__ /* Header files */ -#include <linux/videodev2.h> -#include <media/v4l2-common.h> -#include <media/v4l2-device.h> #include <media/videobuf2-dma-contig.h> -#include <media/davinci/vpif_types.h> +#include <media/v4l2-device.h> #include "vpif.h" diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c index 1b3fb5ca2ad4..e6e573650250 100644 --- a/drivers/media/platform/davinci/vpif_display.c +++ b/drivers/media/platform/davinci/vpif_display.c @@ -14,33 +14,15 @@ * GNU General Public License for more details. */ -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/errno.h> -#include <linux/fs.h> -#include <linux/mm.h> #include <linux/interrupt.h> -#include <linux/workqueue.h> -#include <linux/string.h> -#include <linux/videodev2.h> -#include <linux/wait.h> -#include <linux/time.h> -#include <linux/i2c.h> +#include <linux/module.h> #include <linux/platform_device.h> -#include <linux/io.h> #include <linux/slab.h> -#include <asm/irq.h> -#include <asm/page.h> - -#include <media/adv7343.h> -#include <media/v4l2-device.h> #include <media/v4l2-ioctl.h> -#include <media/v4l2-chip-ident.h> -#include "vpif_display.h" #include "vpif.h" +#include "vpif_display.h" MODULE_DESCRIPTION("TI DaVinci VPIF Display driver"); MODULE_LICENSE("GPL"); @@ -1518,66 +1500,6 @@ static int vpif_g_dv_timings(struct file *file, void *priv, } /* - * vpif_g_chip_ident() - Identify the chip - * @file: file ptr - * @priv: file handle - * @chip: chip identity - * - * Returns zero or -EINVAL if read operations fails. - */ -static int vpif_g_chip_ident(struct file *file, void *priv, - struct v4l2_dbg_chip_ident *chip) -{ - chip->ident = V4L2_IDENT_NONE; - chip->revision = 0; - if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER && - chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR) { - vpif_dbg(2, debug, "match_type is invalid.\n"); - return -EINVAL; - } - - return v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 0, core, - g_chip_ident, chip); -} - -#ifdef CONFIG_VIDEO_ADV_DEBUG -/* - * vpif_dbg_g_register() - Read register - * @file: file ptr - * @priv: file handle - * @reg: register to be read - * - * Debugging only - * Returns zero or -EINVAL if read operations fails. - */ -static int vpif_dbg_g_register(struct file *file, void *priv, - struct v4l2_dbg_register *reg){ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - - return v4l2_subdev_call(ch->sd, core, g_register, reg); -} - -/* - * vpif_dbg_s_register() - Write to register - * @file: file ptr - * @priv: file handle - * @reg: register to be modified - * - * Debugging only - * Returns zero or -EINVAL if write operations fails. - */ -static int vpif_dbg_s_register(struct file *file, void *priv, - const struct v4l2_dbg_register *reg) -{ - struct vpif_fh *fh = priv; - struct channel_obj *ch = fh->channel; - - return v4l2_subdev_call(ch->sd, core, s_register, reg); -} -#endif - -/* * vpif_log_status() - Status information * @file: file ptr * @priv: file handle @@ -1616,11 +1538,6 @@ static const struct v4l2_ioctl_ops vpif_ioctl_ops = { .vidioc_enum_dv_timings = vpif_enum_dv_timings, .vidioc_s_dv_timings = vpif_s_dv_timings, .vidioc_g_dv_timings = vpif_g_dv_timings, - .vidioc_g_chip_ident = vpif_g_chip_ident, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = vpif_dbg_g_register, - .vidioc_s_register = vpif_dbg_s_register, -#endif .vidioc_log_status = vpif_log_status, }; @@ -1734,16 +1651,14 @@ static __init int vpif_probe(struct platform_device *pdev) } while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, res_idx))) { - for (i = res->start; i <= res->end; i++) { - if (request_irq(i, vpif_channel_isr, IRQF_SHARED, - "VPIF_Display", (void *) - (&vpif_obj.dev[res_idx]->channel_id))) { - err = -EBUSY; - for (j = 0; j < i; j++) - free_irq(j, (void *) - (&vpif_obj.dev[res_idx]->channel_id)); - goto vpif_int_err; - } + err = devm_request_irq(&pdev->dev, res->start, vpif_channel_isr, + IRQF_SHARED, "VPIF_Display", + (void *)(&vpif_obj.dev[res_idx]-> + channel_id)); + if (err) { + err = -EINVAL; + vpif_err("VPIF IRQ request failed\n"); + goto vpif_unregister; } res_idx++; } @@ -1760,7 +1675,7 @@ static __init int vpif_probe(struct platform_device *pdev) video_device_release(ch->video_dev); } err = -ENOMEM; - goto vpif_int_err; + goto vpif_unregister; } /* Initialize field of video device */ @@ -1813,6 +1728,7 @@ static __init int vpif_probe(struct platform_device *pdev) NULL); if (!vpif_obj.sd[i]) { vpif_err("Error registering v4l2 subdevice\n"); + err = -ENODEV; goto probe_subdev_out; } @@ -1893,14 +1809,8 @@ vpif_sd_error: /* Note: does nothing if ch->video_dev == NULL */ video_device_release(ch->video_dev); } -vpif_int_err: +vpif_unregister: v4l2_device_unregister(&vpif_obj.v4l2_dev); - vpif_err("VPIF IRQ request failed\n"); - for (i = 0; i < res_idx; i++) { - res = platform_get_resource(pdev, IORESOURCE_IRQ, i); - for (j = res->start; j <= res->end; j++) - free_irq(j, (void *)(&vpif_obj.dev[i]->channel_id)); - } return err; } @@ -1915,6 +1825,7 @@ static int vpif_remove(struct platform_device *device) v4l2_device_unregister(&vpif_obj.v4l2_dev); + kfree(vpif_obj.sd); /* un-register device */ for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) { /* Get the pointer to the channel object */ @@ -1923,6 +1834,7 @@ static int vpif_remove(struct platform_device *device) video_unregister_device(ch->video_dev); ch->video_dev = NULL; + kfree(vpif_obj.dev[i]); } return 0; @@ -2008,37 +1920,4 @@ static __refdata struct platform_driver vpif_driver = { .remove = vpif_remove, }; -static __init int vpif_init(void) -{ - return platform_driver_register(&vpif_driver); -} - -/* - * vpif_cleanup: This function un-registers device and driver to the kernel, - * frees requested irq handler and de-allocates memory allocated for channel - * objects. - */ -static void vpif_cleanup(void) -{ - struct platform_device *pdev; - struct resource *res; - int irq_num; - int i = 0; - - pdev = container_of(vpif_dev, struct platform_device, dev); - - while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, i))) { - for (irq_num = res->start; irq_num <= res->end; irq_num++) - free_irq(irq_num, - (void *)(&vpif_obj.dev[i]->channel_id)); - i++; - } - - platform_driver_unregister(&vpif_driver); - kfree(vpif_obj.sd); - for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) - kfree(vpif_obj.dev[i]); -} - -module_init(vpif_init); -module_exit(vpif_cleanup); +module_platform_driver(vpif_driver); diff --git a/drivers/media/platform/davinci/vpif_display.h b/drivers/media/platform/davinci/vpif_display.h index a5a18f74395c..5d87fc86e580 100644 --- a/drivers/media/platform/davinci/vpif_display.h +++ b/drivers/media/platform/davinci/vpif_display.h @@ -17,11 +17,8 @@ #define DAVINCIHD_DISPLAY_H /* Header files */ -#include <linux/videodev2.h> -#include <media/v4l2-common.h> -#include <media/v4l2-device.h> #include <media/videobuf2-dma-contig.h> -#include <media/davinci/vpif_types.h> +#include <media/v4l2-device.h> #include "vpif.h" diff --git a/drivers/media/platform/exynos-gsc/gsc-core.c b/drivers/media/platform/exynos-gsc/gsc-core.c index 33b5ffc8d66d..559fab2a2d67 100644 --- a/drivers/media/platform/exynos-gsc/gsc-core.c +++ b/drivers/media/platform/exynos-gsc/gsc-core.c @@ -988,7 +988,7 @@ static void *gsc_get_drv_data(struct platform_device *pdev) if (pdev->dev.of_node) { const struct of_device_id *match; - match = of_match_node(of_match_ptr(exynos_gsc_match), + match = of_match_node(exynos_gsc_match, pdev->dev.of_node); if (match) driver_data = (struct gsc_driverdata *)match->data; diff --git a/drivers/media/platform/exynos4-is/Kconfig b/drivers/media/platform/exynos4-is/Kconfig index 436a62a995ee..53ad0f080179 100644 --- a/drivers/media/platform/exynos4-is/Kconfig +++ b/drivers/media/platform/exynos4-is/Kconfig @@ -9,12 +9,16 @@ config VIDEO_SAMSUNG_EXYNOS4_IS if VIDEO_SAMSUNG_EXYNOS4_IS +config VIDEO_EXYNOS4_IS_COMMON + tristate + config VIDEO_S5P_FIMC tristate "S5P/EXYNOS4 FIMC/CAMIF camera interface driver" depends on I2C select VIDEOBUF2_DMA_CONTIG select V4L2_MEM2MEM_DEV select MFD_SYSCON if OF + select VIDEO_EXYNOS4_IS_COMMON help This is a V4L2 driver for Samsung S5P and EXYNOS4 SoC camera host interface and video postprocessor (FIMC) devices. @@ -39,6 +43,7 @@ config VIDEO_EXYNOS_FIMC_LITE tristate "EXYNOS FIMC-LITE camera interface driver" depends on I2C select VIDEOBUF2_DMA_CONTIG + select VIDEO_EXYNOS4_IS_COMMON help This is a V4L2 driver for Samsung EXYNOS4/5 SoC FIMC-LITE camera host interface. diff --git a/drivers/media/platform/exynos4-is/Makefile b/drivers/media/platform/exynos4-is/Makefile index f25f46377399..c2ff29ba6856 100644 --- a/drivers/media/platform/exynos4-is/Makefile +++ b/drivers/media/platform/exynos4-is/Makefile @@ -1,10 +1,13 @@ s5p-fimc-objs := fimc-core.o fimc-reg.o fimc-m2m.o fimc-capture.o media-dev.o exynos-fimc-lite-objs += fimc-lite-reg.o fimc-lite.o +s5p-csis-objs := mipi-csis.o +exynos4-is-common-objs := common.o + exynos-fimc-is-objs := fimc-is.o fimc-isp.o fimc-is-sensor.o fimc-is-regs.o exynos-fimc-is-objs += fimc-is-param.o fimc-is-errno.o fimc-is-i2c.o -s5p-csis-objs := mipi-csis.o obj-$(CONFIG_VIDEO_S5P_MIPI_CSIS) += s5p-csis.o obj-$(CONFIG_VIDEO_EXYNOS_FIMC_LITE) += exynos-fimc-lite.o obj-$(CONFIG_VIDEO_EXYNOS4_FIMC_IS) += exynos-fimc-is.o obj-$(CONFIG_VIDEO_S5P_FIMC) += s5p-fimc.o +obj-$(CONFIG_VIDEO_EXYNOS4_IS_COMMON) += exynos4-is-common.o diff --git a/drivers/media/platform/exynos4-is/common.c b/drivers/media/platform/exynos4-is/common.c new file mode 100644 index 000000000000..0ec210b4da1d --- /dev/null +++ b/drivers/media/platform/exynos4-is/common.c @@ -0,0 +1,53 @@ +/* + * Samsung S5P/EXYNOS4 SoC Camera Subsystem driver + * + * Copyright (C) 2013 Samsung Electronics Co., Ltd. + * Author: Sylwester Nawrocki <s.nawrocki@samsung.com> + * + * 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. + */ + +#include <linux/module.h> +#include <media/s5p_fimc.h> +#include "common.h" + +/* Called with the media graph mutex held or entity->stream_count > 0. */ +struct v4l2_subdev *fimc_find_remote_sensor(struct media_entity *entity) +{ + struct media_pad *pad = &entity->pads[0]; + struct v4l2_subdev *sd; + + while (pad->flags & MEDIA_PAD_FL_SINK) { + /* source pad */ + pad = media_entity_remote_pad(pad); + if (pad == NULL || + media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) + break; + + sd = media_entity_to_v4l2_subdev(pad->entity); + + if (sd->grp_id == GRP_ID_FIMC_IS_SENSOR || + sd->grp_id == GRP_ID_SENSOR) + return sd; + /* sink pad */ + pad = &sd->entity.pads[0]; + } + return NULL; +} +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)); + snprintf(cap->bus_info, sizeof(cap->bus_info), + "platform:%s", dev_name(dev)); + cap->device_caps = caps; + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; +} +EXPORT_SYMBOL(__fimc_vidioc_querycap); + +MODULE_LICENSE("GPL"); diff --git a/drivers/media/platform/exynos4-is/common.h b/drivers/media/platform/exynos4-is/common.h new file mode 100644 index 000000000000..75b9c71d9419 --- /dev/null +++ b/drivers/media/platform/exynos4-is/common.h @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2013 Samsung Electronics Co., Ltd. + * + * 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. + */ + +#include <linux/device.h> +#include <linux/videodev2.h> +#include <media/media-entity.h> +#include <media/v4l2-subdev.h> + +struct v4l2_subdev *fimc_find_remote_sensor(struct media_entity *entity); +void __fimc_vidioc_querycap(struct device *dev, struct v4l2_capability *cap, + unsigned int caps); diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c index 528f41369364..fb27ff7e1e07 100644 --- a/drivers/media/platform/exynos4-is/fimc-capture.c +++ b/drivers/media/platform/exynos4-is/fimc-capture.c @@ -27,9 +27,10 @@ #include <media/videobuf2-core.h> #include <media/videobuf2-dma-contig.h> -#include "media-dev.h" +#include "common.h" #include "fimc-core.h" #include "fimc-reg.h" +#include "media-dev.h" static int fimc_capture_hw_init(struct fimc_dev *fimc) { @@ -119,8 +120,7 @@ static int fimc_capture_state_cleanup(struct fimc_dev *fimc, bool suspend) spin_unlock_irqrestore(&fimc->slock, flags); if (streaming) - return fimc_pipeline_call(fimc, set_stream, - &fimc->pipeline, 0); + return fimc_pipeline_call(&cap->ve, set_stream, 0); else return 0; } @@ -178,8 +178,9 @@ static int fimc_capture_config_update(struct fimc_ctx *ctx) void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf) { - struct v4l2_subdev *csis = fimc->pipeline.subdevs[IDX_CSIS]; struct fimc_vid_cap *cap = &fimc->vid_cap; + struct fimc_pipeline *p = to_fimc_pipeline(cap->ve.pipe); + struct v4l2_subdev *csis = p->subdevs[IDX_CSIS]; struct fimc_frame *f = &cap->ctx->d_frame; struct fimc_vid_buffer *v_buf; struct timeval *tv; @@ -287,8 +288,7 @@ static int start_streaming(struct vb2_queue *q, unsigned int count) fimc_activate_capture(ctx); if (!test_and_set_bit(ST_CAPT_ISP_STREAM, &fimc->state)) - return fimc_pipeline_call(fimc, set_stream, - &fimc->pipeline, 1); + return fimc_pipeline_call(&vid_cap->ve, set_stream, 1); } return 0; @@ -312,7 +312,7 @@ int fimc_capture_suspend(struct fimc_dev *fimc) int ret = fimc_stop_capture(fimc, suspend); if (ret) return ret; - return fimc_pipeline_call(fimc, close, &fimc->pipeline); + return fimc_pipeline_call(&fimc->vid_cap.ve, close); } static void buffer_queue(struct vb2_buffer *vb); @@ -320,6 +320,7 @@ static void buffer_queue(struct vb2_buffer *vb); int fimc_capture_resume(struct fimc_dev *fimc) { struct fimc_vid_cap *vid_cap = &fimc->vid_cap; + struct exynos_video_entity *ve = &vid_cap->ve; struct fimc_vid_buffer *buf; int i; @@ -328,8 +329,7 @@ int fimc_capture_resume(struct fimc_dev *fimc) INIT_LIST_HEAD(&fimc->vid_cap.active_buf_q); vid_cap->buf_index = 0; - fimc_pipeline_call(fimc, open, &fimc->pipeline, - &vid_cap->vfd.entity, false); + fimc_pipeline_call(ve, open, &ve->vdev.entity, false); fimc_capture_hw_init(fimc); clear_bit(ST_CAPT_SUSPENDED, &fimc->state); @@ -397,7 +397,7 @@ static int buffer_prepare(struct vb2_buffer *vb) unsigned long size = ctx->d_frame.payload[i]; if (vb2_plane_size(vb, i) < size) { - v4l2_err(&ctx->fimc_dev->vid_cap.vfd, + v4l2_err(&ctx->fimc_dev->vid_cap.ve.vdev, "User buffer too small (%ld < %ld)\n", vb2_plane_size(vb, i), size); return -EINVAL; @@ -415,6 +415,7 @@ static void buffer_queue(struct vb2_buffer *vb) struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); struct fimc_dev *fimc = ctx->fimc_dev; struct fimc_vid_cap *vid_cap = &fimc->vid_cap; + struct exynos_video_entity *ve = &vid_cap->ve; unsigned long flags; int min_bufs; @@ -452,9 +453,9 @@ static void buffer_queue(struct vb2_buffer *vb) if (test_and_set_bit(ST_CAPT_ISP_STREAM, &fimc->state)) return; - ret = fimc_pipeline_call(fimc, set_stream, &fimc->pipeline, 1); + ret = fimc_pipeline_call(ve, set_stream, 1); if (ret < 0) - v4l2_err(&vid_cap->vfd, "stream on failed: %d\n", ret); + v4l2_err(&ve->vdev, "stream on failed: %d\n", ret); return; } spin_unlock_irqrestore(&fimc->slock, flags); @@ -470,44 +471,17 @@ static struct vb2_ops fimc_capture_qops = { .stop_streaming = stop_streaming, }; -/** - * fimc_capture_ctrls_create - initialize the control handler - * Initialize the capture video node control handler and fill it - * with the FIMC controls. Inherit any sensor's controls if the - * 'user_subdev_api' flag is false (default behaviour). - * This function need to be called with the graph mutex held. - */ -int fimc_capture_ctrls_create(struct fimc_dev *fimc) -{ - struct fimc_vid_cap *vid_cap = &fimc->vid_cap; - struct v4l2_subdev *sensor = fimc->pipeline.subdevs[IDX_SENSOR]; - int ret; - - if (WARN_ON(vid_cap->ctx == NULL)) - return -ENXIO; - if (vid_cap->ctx->ctrls.ready) - return 0; - - ret = fimc_ctrls_create(vid_cap->ctx); - - if (ret || vid_cap->user_subdev_api || !sensor || - !vid_cap->ctx->ctrls.ready) - return ret; - - return v4l2_ctrl_add_handler(&vid_cap->ctx->ctrls.handler, - sensor->ctrl_handler, NULL); -} - static int fimc_capture_set_default_format(struct fimc_dev *fimc); static int fimc_capture_open(struct file *file) { struct fimc_dev *fimc = video_drvdata(file); + struct fimc_vid_cap *vc = &fimc->vid_cap; + struct exynos_video_entity *ve = &vc->ve; int ret = -EBUSY; dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state); - fimc_md_graph_lock(fimc); mutex_lock(&fimc->lock); if (fimc_m2m_active(fimc)) @@ -520,31 +494,42 @@ static int fimc_capture_open(struct file *file) ret = v4l2_fh_open(file); if (ret) { - pm_runtime_put(&fimc->pdev->dev); + pm_runtime_put_sync(&fimc->pdev->dev); goto unlock; } if (v4l2_fh_is_singular_file(file)) { - ret = fimc_pipeline_call(fimc, open, &fimc->pipeline, - &fimc->vid_cap.vfd.entity, true); + fimc_md_graph_lock(ve); - if (!ret && !fimc->vid_cap.user_subdev_api) - ret = fimc_capture_set_default_format(fimc); + ret = fimc_pipeline_call(ve, open, &ve->vdev.entity, true); - if (!ret) - ret = fimc_capture_ctrls_create(fimc); + if (ret == 0 && vc->user_subdev_api && vc->inh_sensor_ctrls) { + /* + * Recreate controls of the the video node to drop + * any controls inherited from the sensor subdev. + */ + fimc_ctrls_delete(vc->ctx); + + ret = fimc_ctrls_create(vc->ctx); + if (ret == 0) + vc->inh_sensor_ctrls = false; + } + if (ret == 0) + ve->vdev.entity.use_count++; + + fimc_md_graph_unlock(ve); + + if (ret == 0) + ret = fimc_capture_set_default_format(fimc); if (ret < 0) { clear_bit(ST_CAPT_BUSY, &fimc->state); pm_runtime_put_sync(&fimc->pdev->dev); v4l2_fh_release(file); - } else { - fimc->vid_cap.refcnt++; } } unlock: mutex_unlock(&fimc->lock); - fimc_md_graph_unlock(fimc); return ret; } @@ -552,30 +537,31 @@ static int fimc_capture_release(struct file *file) { struct fimc_dev *fimc = video_drvdata(file); struct fimc_vid_cap *vc = &fimc->vid_cap; + bool close = v4l2_fh_is_singular_file(file); int ret; dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state); mutex_lock(&fimc->lock); - if (v4l2_fh_is_singular_file(file)) { - if (vc->streaming) { - media_entity_pipeline_stop(&vc->vfd.entity); - vc->streaming = false; - } - clear_bit(ST_CAPT_BUSY, &fimc->state); - fimc_stop_capture(fimc, false); - fimc_pipeline_call(fimc, close, &fimc->pipeline); - clear_bit(ST_CAPT_SUSPENDED, &fimc->state); - fimc->vid_cap.refcnt--; + if (close && vc->streaming) { + media_entity_pipeline_stop(&vc->ve.vdev.entity); + vc->streaming = false; } - pm_runtime_put(&fimc->pdev->dev); + ret = vb2_fop_release(file); - if (v4l2_fh_is_singular_file(file)) - fimc_ctrls_delete(fimc->vid_cap.ctx); + if (close) { + clear_bit(ST_CAPT_BUSY, &fimc->state); + fimc_pipeline_call(&vc->ve, close); + clear_bit(ST_CAPT_SUSPENDED, &fimc->state); - ret = vb2_fop_release(file); + fimc_md_graph_lock(&vc->ve); + vc->ve.vdev.entity.use_count--; + fimc_md_graph_unlock(&vc->ve); + } + + pm_runtime_put_sync(&fimc->pdev->dev); mutex_unlock(&fimc->lock); return ret; @@ -773,7 +759,7 @@ static struct media_entity *fimc_pipeline_get_head(struct media_entity *me) struct media_pad *pad = &me->pads[0]; while (!(pad->flags & MEDIA_PAD_FL_SOURCE)) { - pad = media_entity_remote_source(pad); + pad = media_entity_remote_pad(pad); if (!pad) break; me = pad->entity; @@ -797,7 +783,8 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx, bool set) { struct fimc_dev *fimc = ctx->fimc_dev; - struct v4l2_subdev *sd = fimc->pipeline.subdevs[IDX_SENSOR]; + struct fimc_pipeline *p = to_fimc_pipeline(fimc->vid_cap.ve.pipe); + struct v4l2_subdev *sd = p->subdevs[IDX_SENSOR]; struct v4l2_subdev_format sfmt; struct v4l2_mbus_framefmt *mf = &sfmt.format; struct media_entity *me; @@ -845,7 +832,7 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx, return ret; } - pad = media_entity_remote_source(&me->pads[sfmt.pad]); + pad = media_entity_remote_pad(&me->pads[sfmt.pad]); if (!pad) return -EINVAL; me = pad->entity; @@ -929,57 +916,101 @@ static int fimc_cap_g_fmt_mplane(struct file *file, void *fh, return 0; } -static int fimc_cap_try_fmt_mplane(struct file *file, void *fh, - struct v4l2_format *f) +/* + * Try or set format on the fimc.X.capture video node and additionally + * on the whole pipeline if @try is false. + * Locking: the caller must _not_ hold the graph mutex. + */ +static int __video_try_or_set_format(struct fimc_dev *fimc, + struct v4l2_format *f, bool try, + struct fimc_fmt **inp_fmt, + struct fimc_fmt **out_fmt) { struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; - struct fimc_dev *fimc = video_drvdata(file); - struct fimc_ctx *ctx = fimc->vid_cap.ctx; - struct v4l2_mbus_framefmt mf; - struct fimc_fmt *ffmt = NULL; + struct fimc_vid_cap *vc = &fimc->vid_cap; + struct exynos_video_entity *ve = &vc->ve; + struct fimc_ctx *ctx = vc->ctx; + unsigned int width = 0, height = 0; int ret = 0; - fimc_md_graph_lock(fimc); - mutex_lock(&fimc->lock); - + /* Pre-configure format at the camera input interface, for JPEG only */ if (fimc_jpeg_fourcc(pix->pixelformat)) { fimc_capture_try_format(ctx, &pix->width, &pix->height, NULL, &pix->pixelformat, FIMC_SD_PAD_SINK_CAM); - ctx->s_frame.f_width = pix->width; - ctx->s_frame.f_height = pix->height; + if (try) { + width = pix->width; + height = pix->height; + } else { + ctx->s_frame.f_width = pix->width; + ctx->s_frame.f_height = pix->height; + } } - ffmt = fimc_capture_try_format(ctx, &pix->width, &pix->height, - NULL, &pix->pixelformat, - FIMC_SD_PAD_SOURCE); - if (!ffmt) { - ret = -EINVAL; - goto unlock; + + /* Try the format at the scaler and the DMA output */ + *out_fmt = fimc_capture_try_format(ctx, &pix->width, &pix->height, + NULL, &pix->pixelformat, + FIMC_SD_PAD_SOURCE); + if (*out_fmt == NULL) + return -EINVAL; + + /* Restore image width/height for JPEG (no resizing supported). */ + if (try && fimc_jpeg_fourcc(pix->pixelformat)) { + pix->width = width; + pix->height = height; } - if (!fimc->vid_cap.user_subdev_api) { - mf.width = pix->width; - mf.height = pix->height; - mf.code = ffmt->mbus_code; - fimc_pipeline_try_format(ctx, &mf, &ffmt, false); - pix->width = mf.width; - pix->height = mf.height; - if (ffmt) - pix->pixelformat = ffmt->fourcc; + /* Try to match format at the host and the sensor */ + if (!vc->user_subdev_api) { + struct v4l2_mbus_framefmt mbus_fmt; + struct v4l2_mbus_framefmt *mf; + + mf = try ? &mbus_fmt : &fimc->vid_cap.ci_fmt; + + mf->code = (*out_fmt)->mbus_code; + mf->width = pix->width; + mf->height = pix->height; + + fimc_md_graph_lock(ve); + ret = fimc_pipeline_try_format(ctx, mf, inp_fmt, try); + fimc_md_graph_unlock(ve); + + if (ret < 0) + return ret; + + pix->width = mf->width; + pix->height = mf->height; } - fimc_adjust_mplane_format(ffmt, pix->width, pix->height, pix); + fimc_adjust_mplane_format(*out_fmt, pix->width, pix->height, pix); - if (ffmt->flags & FMT_FLAGS_COMPRESSED) - fimc_get_sensor_frame_desc(fimc->pipeline.subdevs[IDX_SENSOR], - pix->plane_fmt, ffmt->memplanes, true); -unlock: - mutex_unlock(&fimc->lock); - fimc_md_graph_unlock(fimc); + if ((*out_fmt)->flags & FMT_FLAGS_COMPRESSED) { + struct v4l2_subdev *sensor; + + fimc_md_graph_lock(ve); + + sensor = __fimc_md_get_subdev(ve->pipe, IDX_SENSOR); + if (sensor) + fimc_get_sensor_frame_desc(sensor, pix->plane_fmt, + (*out_fmt)->memplanes, try); + else + ret = -EPIPE; + + fimc_md_graph_unlock(ve); + } return ret; } +static int fimc_cap_try_fmt_mplane(struct file *file, void *fh, + struct v4l2_format *f) +{ + struct fimc_dev *fimc = video_drvdata(file); + struct fimc_fmt *out_fmt = NULL, *inp_fmt = NULL; + + return __video_try_or_set_format(fimc, f, true, &inp_fmt, &out_fmt); +} + static void fimc_capture_mark_jpeg_xfer(struct fimc_ctx *ctx, enum fimc_color_fmt color) { @@ -997,57 +1028,23 @@ static void fimc_capture_mark_jpeg_xfer(struct fimc_ctx *ctx, static int __fimc_capture_set_format(struct fimc_dev *fimc, struct v4l2_format *f) { - struct fimc_ctx *ctx = fimc->vid_cap.ctx; + struct fimc_vid_cap *vc = &fimc->vid_cap; + struct fimc_ctx *ctx = vc->ctx; struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; - struct v4l2_mbus_framefmt *mf = &fimc->vid_cap.ci_fmt; struct fimc_frame *ff = &ctx->d_frame; - struct fimc_fmt *s_fmt = NULL; + struct fimc_fmt *inp_fmt = NULL; int ret, i; if (vb2_is_busy(&fimc->vid_cap.vbq)) return -EBUSY; - /* Pre-configure format at camera interface input, for JPEG only */ - if (fimc_jpeg_fourcc(pix->pixelformat)) { - fimc_capture_try_format(ctx, &pix->width, &pix->height, - NULL, &pix->pixelformat, - FIMC_SD_PAD_SINK_CAM); - ctx->s_frame.f_width = pix->width; - ctx->s_frame.f_height = pix->height; - } - /* Try the format at the scaler and the DMA output */ - ff->fmt = fimc_capture_try_format(ctx, &pix->width, &pix->height, - NULL, &pix->pixelformat, - FIMC_SD_PAD_SOURCE); - if (!ff->fmt) - return -EINVAL; + ret = __video_try_or_set_format(fimc, f, false, &inp_fmt, &ff->fmt); + if (ret < 0) + return ret; /* Update RGB Alpha control state and value range */ fimc_alpha_ctrl_update(ctx); - /* Try to match format at the host and the sensor */ - if (!fimc->vid_cap.user_subdev_api) { - mf->code = ff->fmt->mbus_code; - mf->width = pix->width; - mf->height = pix->height; - ret = fimc_pipeline_try_format(ctx, mf, &s_fmt, true); - if (ret) - return ret; - - pix->width = mf->width; - pix->height = mf->height; - } - - fimc_adjust_mplane_format(ff->fmt, pix->width, pix->height, pix); - - if (ff->fmt->flags & FMT_FLAGS_COMPRESSED) { - ret = fimc_get_sensor_frame_desc(fimc->pipeline.subdevs[IDX_SENSOR], - pix->plane_fmt, ff->fmt->memplanes, - true); - if (ret < 0) - return ret; - } - for (i = 0; i < ff->fmt->memplanes; i++) { ff->bytesperline[i] = pix->plane_fmt[i].bytesperline; ff->payload[i] = pix->plane_fmt[i].sizeimage; @@ -1061,8 +1058,8 @@ static int __fimc_capture_set_format(struct fimc_dev *fimc, fimc_capture_mark_jpeg_xfer(ctx, ff->fmt->color); /* Reset cropping and set format at the camera interface input */ - if (!fimc->vid_cap.user_subdev_api) { - ctx->s_frame.fmt = s_fmt; + if (!vc->user_subdev_api) { + ctx->s_frame.fmt = inp_fmt; set_frame_bounds(&ctx->s_frame, pix->width, pix->height); set_frame_crop(&ctx->s_frame, 0, 0, pix->width, pix->height); } @@ -1074,37 +1071,28 @@ static int fimc_cap_s_fmt_mplane(struct file *file, void *priv, struct v4l2_format *f) { struct fimc_dev *fimc = video_drvdata(file); - int ret; - fimc_md_graph_lock(fimc); - mutex_lock(&fimc->lock); - /* - * The graph is walked within __fimc_capture_set_format() to set - * the format at subdevs thus the graph mutex needs to be held at - * this point and acquired before the video mutex, to avoid AB-BA - * deadlock when fimc_md_link_notify() is called by other thread. - * Ideally the graph walking and setting format at the whole pipeline - * should be removed from this driver and handled in userspace only. - */ - ret = __fimc_capture_set_format(fimc, f); - - mutex_unlock(&fimc->lock); - fimc_md_graph_unlock(fimc); - return ret; + return __fimc_capture_set_format(fimc, f); } static int fimc_cap_enum_input(struct file *file, void *priv, struct v4l2_input *i) { struct fimc_dev *fimc = video_drvdata(file); - struct v4l2_subdev *sd = fimc->pipeline.subdevs[IDX_SENSOR]; + struct exynos_video_entity *ve = &fimc->vid_cap.ve; + struct v4l2_subdev *sd; if (i->index != 0) return -EINVAL; i->type = V4L2_INPUT_TYPE_CAMERA; + fimc_md_graph_lock(ve); + sd = __fimc_md_get_subdev(ve->pipe, IDX_SENSOR); + fimc_md_graph_unlock(ve); + if (sd) strlcpy(i->name, sd->name, sizeof(i->name)); + return 0; } @@ -1130,6 +1118,7 @@ static int fimc_pipeline_validate(struct fimc_dev *fimc) struct v4l2_subdev_format sink_fmt, src_fmt; struct fimc_vid_cap *vc = &fimc->vid_cap; struct v4l2_subdev *sd = &vc->subdev; + struct fimc_pipeline *p = to_fimc_pipeline(vc->ve.pipe); struct media_pad *sink_pad, *src_pad; int i, ret; @@ -1146,7 +1135,7 @@ static int fimc_pipeline_validate(struct fimc_dev *fimc) if (p->flags & MEDIA_PAD_FL_SINK) { sink_pad = p; - src_pad = media_entity_remote_source(sink_pad); + src_pad = media_entity_remote_pad(sink_pad); if (src_pad) break; } @@ -1183,7 +1172,7 @@ static int fimc_pipeline_validate(struct fimc_dev *fimc) src_fmt.format.code != sink_fmt.format.code) return -EPIPE; - if (sd == fimc->pipeline.subdevs[IDX_SENSOR] && + if (sd == p->subdevs[IDX_SENSOR] && fimc_user_defined_mbus_fmt(src_fmt.format.code)) { struct v4l2_plane_pix_format plane_fmt[FIMC_MAX_PLANES]; struct fimc_frame *frame = &vc->ctx->d_frame; @@ -1207,9 +1196,8 @@ static int fimc_cap_streamon(struct file *file, void *priv, enum v4l2_buf_type type) { struct fimc_dev *fimc = video_drvdata(file); - struct fimc_pipeline *p = &fimc->pipeline; struct fimc_vid_cap *vc = &fimc->vid_cap; - struct media_entity *entity = &vc->vfd.entity; + struct media_entity *entity = &vc->ve.vdev.entity; struct fimc_source_info *si = NULL; struct v4l2_subdev *sd; int ret; @@ -1217,11 +1205,11 @@ static int fimc_cap_streamon(struct file *file, void *priv, if (fimc_capture_active(fimc)) return -EBUSY; - ret = media_entity_pipeline_start(entity, p->m_pipeline); + ret = media_entity_pipeline_start(entity, &vc->ve.pipe->mp); if (ret < 0) return ret; - sd = p->subdevs[IDX_SENSOR]; + sd = __fimc_md_get_subdev(vc->ve.pipe, IDX_SENSOR); if (sd) si = v4l2_get_subdev_hostdata(sd); @@ -1259,14 +1247,15 @@ static int fimc_cap_streamoff(struct file *file, void *priv, enum v4l2_buf_type type) { struct fimc_dev *fimc = video_drvdata(file); + struct fimc_vid_cap *vc = &fimc->vid_cap; int ret; ret = vb2_ioctl_streamoff(file, priv, type); if (ret < 0) return ret; - media_entity_pipeline_stop(&fimc->vid_cap.vfd.entity); - fimc->vid_cap.streaming = false; + media_entity_pipeline_stop(&vc->ve.vdev.entity); + vc->streaming = false; return 0; } @@ -1405,6 +1394,8 @@ static int fimc_link_setup(struct media_entity *entity, { struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); struct fimc_dev *fimc = v4l2_get_subdevdata(sd); + struct fimc_vid_cap *vc = &fimc->vid_cap; + struct v4l2_subdev *sensor; if (media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV) return -EINVAL; @@ -1416,15 +1407,26 @@ static int fimc_link_setup(struct media_entity *entity, local->entity->name, remote->entity->name, flags, fimc->vid_cap.input); - if (flags & MEDIA_LNK_FL_ENABLED) { - if (fimc->vid_cap.input != 0) - return -EBUSY; - fimc->vid_cap.input = sd->grp_id; + if (!(flags & MEDIA_LNK_FL_ENABLED)) { + fimc->vid_cap.input = 0; return 0; } - fimc->vid_cap.input = 0; - return 0; + if (vc->input != 0) + return -EBUSY; + + vc->input = sd->grp_id; + + if (vc->user_subdev_api || vc->inh_sensor_ctrls) + return 0; + + /* Inherit V4L2 controls from the image sensor subdev. */ + sensor = fimc_find_remote_sensor(&vc->subdev.entity); + if (sensor == NULL) + return 0; + + return v4l2_ctrl_add_handler(&vc->ctx->ctrls.handler, + sensor->ctrl_handler, NULL); } static const struct media_entity_operations fimc_sd_media_ops = { @@ -1720,8 +1722,8 @@ static int fimc_capture_set_default_format(struct fimc_dev *fimc) struct v4l2_format fmt = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, .fmt.pix_mp = { - .width = 640, - .height = 480, + .width = FIMC_DEFAULT_WIDTH, + .height = FIMC_DEFAULT_HEIGHT, .pixelformat = V4L2_PIX_FMT_YUYV, .field = V4L2_FIELD_NONE, .colorspace = V4L2_COLORSPACE_JPEG, @@ -1735,10 +1737,11 @@ static int fimc_capture_set_default_format(struct fimc_dev *fimc) static int fimc_register_capture_device(struct fimc_dev *fimc, struct v4l2_device *v4l2_dev) { - struct video_device *vfd = &fimc->vid_cap.vfd; + struct video_device *vfd = &fimc->vid_cap.ve.vdev; struct vb2_queue *q = &fimc->vid_cap.vbq; struct fimc_ctx *ctx; struct fimc_vid_cap *vid_cap; + struct fimc_fmt *fmt; int ret = -ENOMEM; ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); @@ -1784,22 +1787,34 @@ static int fimc_register_capture_device(struct fimc_dev *fimc, ret = vb2_queue_init(q); if (ret) - goto err_ent; + goto err_free_ctx; + + /* Default format configuration */ + fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_CAM, 0); + vid_cap->ci_fmt.width = FIMC_DEFAULT_WIDTH; + vid_cap->ci_fmt.height = FIMC_DEFAULT_HEIGHT; + vid_cap->ci_fmt.code = fmt->mbus_code; + + ctx->s_frame.width = FIMC_DEFAULT_WIDTH; + ctx->s_frame.height = FIMC_DEFAULT_HEIGHT; + ctx->s_frame.fmt = fmt; + + fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_WRITEBACK, 0); + vid_cap->wb_fmt = vid_cap->ci_fmt; + vid_cap->wb_fmt.code = fmt->mbus_code; vid_cap->vd_pad.flags = MEDIA_PAD_FL_SINK; ret = media_entity_init(&vfd->entity, 1, &vid_cap->vd_pad, 0); if (ret) - goto err_ent; - /* - * For proper order of acquiring/releasing the video - * and the graph mutex. - */ - v4l2_disable_ioctl_locking(vfd, VIDIOC_TRY_FMT); - v4l2_disable_ioctl_locking(vfd, VIDIOC_S_FMT); + goto err_free_ctx; + + ret = fimc_ctrls_create(ctx); + if (ret) + goto err_me_cleanup; ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1); if (ret) - goto err_vd; + goto err_ctrl_free; v4l2_info(v4l2_dev, "Registered %s as /dev/%s\n", vfd->name, video_device_node_name(vfd)); @@ -1807,9 +1822,11 @@ static int fimc_register_capture_device(struct fimc_dev *fimc, vfd->ctrl_handler = &ctx->ctrls.handler; return 0; -err_vd: +err_ctrl_free: + fimc_ctrls_delete(ctx); +err_me_cleanup: media_entity_cleanup(&vfd->entity); -err_ent: +err_free_ctx: kfree(ctx); return ret; } @@ -1826,12 +1843,12 @@ static int fimc_capture_subdev_registered(struct v4l2_subdev *sd) if (ret) return ret; - fimc->pipeline_ops = v4l2_get_subdev_hostdata(sd); + fimc->vid_cap.ve.pipe = v4l2_get_subdev_hostdata(sd); ret = fimc_register_capture_device(fimc, sd->v4l2_dev); if (ret) { fimc_unregister_m2m_device(fimc); - fimc->pipeline_ops = NULL; + fimc->vid_cap.ve.pipe = NULL; } return ret; @@ -1840,19 +1857,26 @@ static int fimc_capture_subdev_registered(struct v4l2_subdev *sd) static void fimc_capture_subdev_unregistered(struct v4l2_subdev *sd) { struct fimc_dev *fimc = v4l2_get_subdevdata(sd); + struct video_device *vdev; if (fimc == NULL) return; + mutex_lock(&fimc->lock); + fimc_unregister_m2m_device(fimc); + vdev = &fimc->vid_cap.ve.vdev; - if (video_is_registered(&fimc->vid_cap.vfd)) { - video_unregister_device(&fimc->vid_cap.vfd); - media_entity_cleanup(&fimc->vid_cap.vfd.entity); - fimc->pipeline_ops = NULL; + if (video_is_registered(vdev)) { + video_unregister_device(vdev); + media_entity_cleanup(&vdev->entity); + fimc_ctrls_delete(fimc->vid_cap.ctx); + fimc->vid_cap.ve.pipe = NULL; } kfree(fimc->vid_cap.ctx); fimc->vid_cap.ctx = NULL; + + mutex_unlock(&fimc->lock); } static const struct v4l2_subdev_internal_ops fimc_capture_sd_internal_ops = { diff --git a/drivers/media/platform/exynos4-is/fimc-core.c b/drivers/media/platform/exynos4-is/fimc-core.c index 379a5e9d52a7..6489c5160ee8 100644 --- a/drivers/media/platform/exynos4-is/fimc-core.c +++ b/drivers/media/platform/exynos4-is/fimc-core.c @@ -213,17 +213,6 @@ struct fimc_fmt *fimc_get_format(unsigned int index) return &fimc_formats[index]; } -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)); - snprintf(cap->bus_info, sizeof(cap->bus_info), - "platform:%s", dev_name(dev)); - cap->device_caps = caps; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; -} - int fimc_check_scaler_ratio(struct fimc_ctx *ctx, int sw, int sh, int dw, int dh, int rotation) { diff --git a/drivers/media/platform/exynos4-is/fimc-core.h b/drivers/media/platform/exynos4-is/fimc-core.h index 539a3f71c16a..3d376faec777 100644 --- a/drivers/media/platform/exynos4-is/fimc-core.h +++ b/drivers/media/platform/exynos4-is/fimc-core.h @@ -48,6 +48,8 @@ #define FIMC_DEF_MIN_SIZE 16 #define FIMC_DEF_HEIGHT_ALIGN 2 #define FIMC_DEF_HOR_OFFS_ALIGN 1 +#define FIMC_DEFAULT_WIDTH 640 +#define FIMC_DEFAULT_HEIGHT 480 /* indices to the clocks array */ enum { @@ -283,8 +285,8 @@ struct fimc_m2m_device { /** * struct fimc_vid_cap - camera capture device information * @ctx: hardware context data - * @vfd: video device node for camera capture mode * @subdev: subdev exposing the FIMC processing block + * @ve: exynos video device entity structure * @vd_pad: fimc video capture node pad * @sd_pads: fimc video processing block pads * @ci_fmt: image format at the FIMC camera input (and the scaler output) @@ -298,15 +300,16 @@ struct fimc_m2m_device { * @frame_count: the frame counter for statistics * @reqbufs_count: the number of buffers requested in REQBUFS ioctl * @input_index: input (camera sensor) index - * @refcnt: driver's private reference counter * @input: capture input type, grp_id of the attached subdev * @user_subdev_api: true if subdevs are not configured by the host driver + * @inh_sensor_ctrls: a flag indicating v4l2 controls are inherited from + * an image sensor subdev */ struct fimc_vid_cap { struct fimc_ctx *ctx; struct vb2_alloc_ctx *alloc_ctx; - struct video_device vfd; struct v4l2_subdev subdev; + struct exynos_video_entity ve; struct media_pad vd_pad; struct media_pad sd_pads[FIMC_SD_PADS_NUM]; struct v4l2_mbus_framefmt ci_fmt; @@ -321,9 +324,9 @@ struct fimc_vid_cap { unsigned int reqbufs_count; bool streaming; int input_index; - int refcnt; u32 input; bool user_subdev_api; + bool inh_sensor_ctrls; }; /** @@ -434,8 +437,6 @@ struct fimc_dev { struct fimc_vid_cap vid_cap; unsigned long state; struct vb2_alloc_ctx *alloc_ctx; - struct fimc_pipeline pipeline; - const struct fimc_pipeline_ops *pipeline_ops; }; /** @@ -620,8 +621,6 @@ static inline struct fimc_frame *ctx_get_frame(struct fimc_ctx *ctx, /* fimc-core.c */ int fimc_vidioc_enum_fmt_mplane(struct file *file, void *priv, struct v4l2_fmtdesc *f); -void __fimc_vidioc_querycap(struct device *dev, struct v4l2_capability *cap, - unsigned int caps); int fimc_ctrls_create(struct fimc_ctx *ctx); void fimc_ctrls_delete(struct fimc_ctx *ctx); void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active); diff --git a/drivers/media/platform/exynos4-is/fimc-is-i2c.c b/drivers/media/platform/exynos4-is/fimc-is-i2c.c index c397777d7cbb..617a798d9235 100644 --- a/drivers/media/platform/exynos4-is/fimc-is-i2c.c +++ b/drivers/media/platform/exynos4-is/fimc-is-i2c.c @@ -96,7 +96,7 @@ static int fimc_is_i2c_resume(struct device *dev) return clk_prepare_enable(isp_i2c->clock); } -UNIVERSAL_DEV_PM_OPS(fimc_is_i2c_pm_ops, fimc_is_i2c_suspend, +static UNIVERSAL_DEV_PM_OPS(fimc_is_i2c_pm_ops, fimc_is_i2c_suspend, fimc_is_i2c_resume, NULL); static const struct of_device_id fimc_is_i2c_of_match[] = { diff --git a/drivers/media/platform/exynos4-is/fimc-is-param.c b/drivers/media/platform/exynos4-is/fimc-is-param.c index 53fe2a2b4db3..c7e7f694c6ed 100644 --- a/drivers/media/platform/exynos4-is/fimc-is-param.c +++ b/drivers/media/platform/exynos4-is/fimc-is-param.c @@ -38,7 +38,7 @@ static void __hw_param_copy(void *dst, void *src) memcpy(dst, src, FIMC_IS_PARAM_MAX_SIZE); } -void __fimc_is_hw_update_param_global_shotmode(struct fimc_is *is) +static void __fimc_is_hw_update_param_global_shotmode(struct fimc_is *is) { struct param_global_shotmode *dst, *src; @@ -47,7 +47,7 @@ void __fimc_is_hw_update_param_global_shotmode(struct fimc_is *is) __hw_param_copy(dst, src); } -void __fimc_is_hw_update_param_sensor_framerate(struct fimc_is *is) +static void __fimc_is_hw_update_param_sensor_framerate(struct fimc_is *is) { struct param_sensor_framerate *dst, *src; @@ -168,8 +168,8 @@ unsigned int __get_pending_param_count(struct fimc_is *is) unsigned int count; spin_lock_irqsave(&is->slock, flags); - count = hweight32(config->p_region_index1); - count += hweight32(config->p_region_index2); + count = hweight32(config->p_region_index[0]); + count += hweight32(config->p_region_index[1]); spin_unlock_irqrestore(&is->slock, flags); return count; @@ -177,31 +177,30 @@ unsigned int __get_pending_param_count(struct fimc_is *is) int __is_hw_update_params(struct fimc_is *is) { - unsigned long *p_index1, *p_index2; + unsigned long *p_index; int i, id, ret = 0; id = is->config_index; - p_index1 = &is->config[id].p_region_index1; - p_index2 = &is->config[id].p_region_index2; + p_index = &is->config[id].p_region_index[0]; - if (test_bit(PARAM_GLOBAL_SHOTMODE, p_index1)) + if (test_bit(PARAM_GLOBAL_SHOTMODE, p_index)) __fimc_is_hw_update_param_global_shotmode(is); - if (test_bit(PARAM_SENSOR_FRAME_RATE, p_index1)) + if (test_bit(PARAM_SENSOR_FRAME_RATE, p_index)) __fimc_is_hw_update_param_sensor_framerate(is); for (i = PARAM_ISP_CONTROL; i < PARAM_DRC_CONTROL; i++) { - if (test_bit(i, p_index1)) + if (test_bit(i, p_index)) ret = __fimc_is_hw_update_param(is, i); } for (i = PARAM_DRC_CONTROL; i < PARAM_SCALERC_CONTROL; i++) { - if (test_bit(i, p_index1)) + if (test_bit(i, p_index)) ret = __fimc_is_hw_update_param(is, i); } for (i = PARAM_FD_CONTROL; i <= PARAM_FD_CONFIG; i++) { - if (test_bit((i - 32), p_index2)) + if (test_bit(i, p_index)) ret = __fimc_is_hw_update_param(is, i); } @@ -243,7 +242,7 @@ void __is_set_frame_size(struct fimc_is *is, struct v4l2_mbus_framefmt *mf) fd->otf_input.height = mf->height; if (test_bit(PARAM_ISP_OTF_INPUT, - &is->config[index].p_region_index1)) + &is->config[index].p_region_index[0])) return; /* Update field */ @@ -368,7 +367,7 @@ void __is_set_isp_adjust(struct fimc_is *is, u32 cmd, u32 val) unsigned long *p_index; struct isp_param *isp; - p_index = &is->config[index].p_region_index1; + p_index = &is->config[index].p_region_index[0]; isp = &is->config[index].isp; switch (cmd) { @@ -415,7 +414,7 @@ void __is_set_isp_metering(struct fimc_is *is, u32 id, u32 val) struct isp_param *isp; unsigned long *p_index; - p_index = &is->config[index].p_region_index1; + p_index = &is->config[index].p_region_index[0]; isp = &is->config[index].isp; switch (id) { @@ -476,7 +475,7 @@ void __is_set_fd_control(struct fimc_is *is, u32 val) struct fd_param *fd; unsigned long *p_index; - p_index = &is->config[index].p_region_index2; + p_index = &is->config[index].p_region_index[1]; fd = &is->config[index].fd; fd->control.cmd = val; @@ -491,7 +490,7 @@ void __is_set_fd_config_maxface(struct fimc_is *is, u32 val) struct fd_param *fd; unsigned long *p_index; - p_index = &is->config[index].p_region_index2; + p_index = &is->config[index].p_region_index[1]; fd = &is->config[index].fd; fd->config.max_number = val; @@ -511,7 +510,7 @@ void __is_set_fd_config_rollangle(struct fimc_is *is, u32 val) struct fd_param *fd; unsigned long *p_index; - p_index = &is->config[index].p_region_index2; + p_index = &is->config[index].p_region_index[1]; fd = &is->config[index].fd; fd->config.roll_angle = val; @@ -531,7 +530,7 @@ void __is_set_fd_config_yawangle(struct fimc_is *is, u32 val) struct fd_param *fd; unsigned long *p_index; - p_index = &is->config[index].p_region_index2; + p_index = &is->config[index].p_region_index[1]; fd = &is->config[index].fd; fd->config.yaw_angle = val; @@ -551,7 +550,7 @@ void __is_set_fd_config_smilemode(struct fimc_is *is, u32 val) struct fd_param *fd; unsigned long *p_index; - p_index = &is->config[index].p_region_index2; + p_index = &is->config[index].p_region_index[1]; fd = &is->config[index].fd; fd->config.smile_mode = val; @@ -571,7 +570,7 @@ void __is_set_fd_config_blinkmode(struct fimc_is *is, u32 val) struct fd_param *fd; unsigned long *p_index; - p_index = &is->config[index].p_region_index2; + p_index = &is->config[index].p_region_index[1]; fd = &is->config[index].fd; fd->config.blink_mode = val; @@ -591,7 +590,7 @@ void __is_set_fd_config_eyedetect(struct fimc_is *is, u32 val) struct fd_param *fd; unsigned long *p_index; - p_index = &is->config[index].p_region_index2; + p_index = &is->config[index].p_region_index[1]; fd = &is->config[index].fd; fd->config.eye_detect = val; @@ -611,7 +610,7 @@ void __is_set_fd_config_mouthdetect(struct fimc_is *is, u32 val) struct fd_param *fd; unsigned long *p_index; - p_index = &is->config[index].p_region_index2; + p_index = &is->config[index].p_region_index[1]; fd = &is->config[index].fd; fd->config.mouth_detect = val; @@ -631,7 +630,7 @@ void __is_set_fd_config_orientation(struct fimc_is *is, u32 val) struct fd_param *fd; unsigned long *p_index; - p_index = &is->config[index].p_region_index2; + p_index = &is->config[index].p_region_index[1]; fd = &is->config[index].fd; fd->config.orientation = val; @@ -651,7 +650,7 @@ void __is_set_fd_config_orientation_val(struct fimc_is *is, u32 val) struct fd_param *fd; unsigned long *p_index; - p_index = &is->config[index].p_region_index2; + p_index = &is->config[index].p_region_index[1]; fd = &is->config[index].fd; fd->config.orientation_value = val; @@ -672,7 +671,7 @@ void fimc_is_set_initial_params(struct fimc_is *is) struct isp_param *isp; struct drc_param *drc; struct fd_param *fd; - unsigned long *p_index1, *p_index2; + unsigned long *p_index; unsigned int index; index = is->config_index; @@ -681,8 +680,7 @@ void fimc_is_set_initial_params(struct fimc_is *is) isp = &is->config[index].isp; drc = &is->config[index].drc; fd = &is->config[index].fd; - p_index1 = &is->config[index].p_region_index1; - p_index2 = &is->config[index].p_region_index2; + p_index = &is->config[index].p_region_index[0]; /* Global */ global->shotmode.cmd = 1; @@ -695,7 +693,7 @@ void fimc_is_set_initial_params(struct fimc_is *is) fimc_is_set_param_bit(is, PARAM_ISP_CONTROL); isp->otf_input.cmd = OTF_INPUT_COMMAND_ENABLE; - if (!test_bit(PARAM_ISP_OTF_INPUT, p_index1)) { + if (!test_bit(PARAM_ISP_OTF_INPUT, p_index)) { isp->otf_input.width = DEFAULT_PREVIEW_STILL_WIDTH; isp->otf_input.height = DEFAULT_PREVIEW_STILL_HEIGHT; fimc_is_set_param_bit(is, PARAM_ISP_OTF_INPUT); @@ -738,20 +736,20 @@ void fimc_is_set_initial_params(struct fimc_is *is) isp->aa.target = ISP_AA_TARGET_AE | ISP_AA_TARGET_AWB; fimc_is_set_param_bit(is, PARAM_ISP_AA); - if (!test_bit(PARAM_ISP_FLASH, p_index1)) + if (!test_bit(PARAM_ISP_FLASH, p_index)) __is_set_isp_flash(is, ISP_FLASH_COMMAND_DISABLE, ISP_FLASH_REDEYE_DISABLE); - if (!test_bit(PARAM_ISP_AWB, p_index1)) + if (!test_bit(PARAM_ISP_AWB, p_index)) __is_set_isp_awb(is, ISP_AWB_COMMAND_AUTO, 0); - if (!test_bit(PARAM_ISP_IMAGE_EFFECT, p_index1)) + if (!test_bit(PARAM_ISP_IMAGE_EFFECT, p_index)) __is_set_isp_effect(is, ISP_IMAGE_EFFECT_DISABLE); - if (!test_bit(PARAM_ISP_ISO, p_index1)) + if (!test_bit(PARAM_ISP_ISO, p_index)) __is_set_isp_iso(is, ISP_ISO_COMMAND_AUTO, 0); - if (!test_bit(PARAM_ISP_ADJUST, p_index1)) { + if (!test_bit(PARAM_ISP_ADJUST, p_index)) { __is_set_isp_adjust(is, ISP_ADJUST_COMMAND_MANUAL_CONTRAST, 0); __is_set_isp_adjust(is, ISP_ADJUST_COMMAND_MANUAL_SATURATION, 0); @@ -762,7 +760,7 @@ void fimc_is_set_initial_params(struct fimc_is *is) __is_set_isp_adjust(is, ISP_ADJUST_COMMAND_MANUAL_HUE, 0); } - if (!test_bit(PARAM_ISP_METERING, p_index1)) { + if (!test_bit(PARAM_ISP_METERING, p_index)) { __is_set_isp_metering(is, 0, ISP_METERING_COMMAND_CENTER); __is_set_isp_metering(is, 1, 0); __is_set_isp_metering(is, 2, 0); @@ -770,11 +768,11 @@ void fimc_is_set_initial_params(struct fimc_is *is) __is_set_isp_metering(is, 4, 0); } - if (!test_bit(PARAM_ISP_AFC, p_index1)) + if (!test_bit(PARAM_ISP_AFC, p_index)) __is_set_isp_afc(is, ISP_AFC_COMMAND_AUTO, 0); isp->otf_output.cmd = OTF_OUTPUT_COMMAND_ENABLE; - if (!test_bit(PARAM_ISP_OTF_OUTPUT, p_index1)) { + if (!test_bit(PARAM_ISP_OTF_OUTPUT, p_index)) { isp->otf_output.width = DEFAULT_PREVIEW_STILL_WIDTH; isp->otf_output.height = DEFAULT_PREVIEW_STILL_HEIGHT; fimc_is_set_param_bit(is, PARAM_ISP_OTF_OUTPUT); @@ -784,7 +782,7 @@ void fimc_is_set_initial_params(struct fimc_is *is) isp->otf_output.order = 0; isp->otf_output.err = OTF_OUTPUT_ERROR_NONE; - if (!test_bit(PARAM_ISP_DMA1_OUTPUT, p_index1)) { + if (!test_bit(PARAM_ISP_DMA1_OUTPUT, p_index)) { isp->dma1_output.cmd = DMA_OUTPUT_COMMAND_DISABLE; isp->dma1_output.width = 0; isp->dma1_output.height = 0; @@ -800,7 +798,7 @@ void fimc_is_set_initial_params(struct fimc_is *is) fimc_is_set_param_bit(is, PARAM_ISP_DMA1_OUTPUT); } - if (!test_bit(PARAM_ISP_DMA2_OUTPUT, p_index1)) { + if (!test_bit(PARAM_ISP_DMA2_OUTPUT, p_index)) { isp->dma2_output.cmd = DMA_OUTPUT_COMMAND_DISABLE; isp->dma2_output.width = 0; isp->dma2_output.height = 0; @@ -817,7 +815,7 @@ void fimc_is_set_initial_params(struct fimc_is *is) } /* Sensor */ - if (!test_bit(PARAM_SENSOR_FRAME_RATE, p_index1)) { + if (!test_bit(PARAM_SENSOR_FRAME_RATE, p_index)) { if (is->config_index == 0) __is_set_sensor(is, 0); } @@ -827,7 +825,7 @@ void fimc_is_set_initial_params(struct fimc_is *is) __is_set_drc_control(is, CONTROL_BYPASS_ENABLE); drc->otf_input.cmd = OTF_INPUT_COMMAND_ENABLE; - if (!test_bit(PARAM_DRC_OTF_INPUT, p_index1)) { + if (!test_bit(PARAM_DRC_OTF_INPUT, p_index)) { drc->otf_input.width = DEFAULT_PREVIEW_STILL_WIDTH; drc->otf_input.height = DEFAULT_PREVIEW_STILL_HEIGHT; fimc_is_set_param_bit(is, PARAM_DRC_OTF_INPUT); @@ -850,7 +848,7 @@ void fimc_is_set_initial_params(struct fimc_is *is) fimc_is_set_param_bit(is, PARAM_DRC_DMA_INPUT); drc->otf_output.cmd = OTF_OUTPUT_COMMAND_ENABLE; - if (!test_bit(PARAM_DRC_OTF_OUTPUT, p_index1)) { + if (!test_bit(PARAM_DRC_OTF_OUTPUT, p_index)) { drc->otf_output.width = DEFAULT_PREVIEW_STILL_WIDTH; drc->otf_output.height = DEFAULT_PREVIEW_STILL_HEIGHT; fimc_is_set_param_bit(is, PARAM_DRC_OTF_OUTPUT); @@ -865,7 +863,7 @@ void fimc_is_set_initial_params(struct fimc_is *is) fd->control.bypass = CONTROL_BYPASS_DISABLE; fd->otf_input.cmd = OTF_INPUT_COMMAND_ENABLE; - if (!test_bit((PARAM_FD_OTF_INPUT - 32), p_index2)) { + if (!test_bit(PARAM_FD_OTF_INPUT, p_index)) { fd->otf_input.width = DEFAULT_PREVIEW_STILL_WIDTH; fd->otf_input.height = DEFAULT_PREVIEW_STILL_HEIGHT; fimc_is_set_param_bit(is, PARAM_FD_OTF_INPUT); diff --git a/drivers/media/platform/exynos4-is/fimc-is-regs.c b/drivers/media/platform/exynos4-is/fimc-is-regs.c index d05eaa2c8490..63c68ec7cfa4 100644 --- a/drivers/media/platform/exynos4-is/fimc-is-regs.c +++ b/drivers/media/platform/exynos4-is/fimc-is-regs.c @@ -89,8 +89,8 @@ int fimc_is_hw_set_param(struct fimc_is *is) mcuctl_write(is->config_index, is, MCUCTL_REG_ISSR(2)); mcuctl_write(param_count, is, MCUCTL_REG_ISSR(3)); - mcuctl_write(config->p_region_index1, is, MCUCTL_REG_ISSR(4)); - mcuctl_write(config->p_region_index2, is, MCUCTL_REG_ISSR(5)); + mcuctl_write(config->p_region_index[0], is, MCUCTL_REG_ISSR(4)); + mcuctl_write(config->p_region_index[1], is, MCUCTL_REG_ISSR(5)); fimc_is_hw_set_intgr0_gd0(is); return 0; diff --git a/drivers/media/platform/exynos4-is/fimc-is.c b/drivers/media/platform/exynos4-is/fimc-is.c index 0741945b79ed..967f6a939340 100644 --- a/drivers/media/platform/exynos4-is/fimc-is.c +++ b/drivers/media/platform/exynos4-is/fimc-is.c @@ -129,7 +129,7 @@ static int fimc_is_setup_clocks(struct fimc_is *is) ATCLK_MCUISP_FREQUENCY); } -int fimc_is_enable_clocks(struct fimc_is *is) +static int fimc_is_enable_clocks(struct fimc_is *is) { int i, ret; @@ -149,7 +149,7 @@ int fimc_is_enable_clocks(struct fimc_is *is) return 0; } -void fimc_is_disable_clocks(struct fimc_is *is) +static void fimc_is_disable_clocks(struct fimc_is *is) { int i; @@ -527,8 +527,8 @@ static void fimc_is_general_irq_handler(struct fimc_is *is) break; case HIC_SET_PARAMETER: - is->config[is->config_index].p_region_index1 = 0; - is->config[is->config_index].p_region_index2 = 0; + is->config[is->config_index].p_region_index[0] = 0; + is->config[is->config_index].p_region_index[1] = 0; set_bit(IS_ST_BLOCK_CMD_CLEARED, &is->state); pr_debug("HIC_SET_PARAMETER\n"); break; @@ -587,8 +587,8 @@ static void fimc_is_general_irq_handler(struct fimc_is *is) switch (is->i2h_cmd.args[0]) { case HIC_SET_PARAMETER: - is->config[is->config_index].p_region_index1 = 0; - is->config[is->config_index].p_region_index2 = 0; + is->config[is->config_index].p_region_index[0] = 0; + is->config[is->config_index].p_region_index[1] = 0; set_bit(IS_ST_BLOCK_CMD_CLEARED, &is->state); break; } diff --git a/drivers/media/platform/exynos4-is/fimc-is.h b/drivers/media/platform/exynos4-is/fimc-is.h index d7db133b493f..61bb0127e19d 100644 --- a/drivers/media/platform/exynos4-is/fimc-is.h +++ b/drivers/media/platform/exynos4-is/fimc-is.h @@ -33,8 +33,8 @@ #define FIMC_IS_DRV_NAME "exynos4-fimc-is" -#define FIMC_IS_FW_FILENAME "fimc_is_fw.bin" -#define FIMC_IS_SETFILE_6A3 "setfile.bin" +#define FIMC_IS_FW_FILENAME "exynos4_fimc_is_fw.bin" +#define FIMC_IS_SETFILE_6A3 "exynos4_s5k6a3_setfile.bin" #define FIMC_IS_FW_LOAD_TIMEOUT 1000 /* ms */ #define FIMC_IS_POWER_ON_TIMEOUT 1000 /* us */ @@ -225,8 +225,7 @@ struct chain_config { struct drc_param drc; struct fd_param fd; - unsigned long p_region_index1; - unsigned long p_region_index2; + unsigned long p_region_index[2]; }; /** @@ -302,10 +301,7 @@ static inline void fimc_is_set_param_bit(struct fimc_is *is, int num) { struct chain_config *cfg = &is->config[is->config_index]; - if (num >= 32) - set_bit(num - 32, &cfg->p_region_index2); - else - set_bit(num, &cfg->p_region_index1); + set_bit(num, &cfg->p_region_index[0]); } static inline void fimc_is_set_param_ctrl_cmd(struct fimc_is *is, int cmd) diff --git a/drivers/media/platform/exynos4-is/fimc-isp.c b/drivers/media/platform/exynos4-is/fimc-isp.c index 7ede30b5910f..cf520a7d7f71 100644 --- a/drivers/media/platform/exynos4-is/fimc-isp.c +++ b/drivers/media/platform/exynos4-is/fimc-isp.c @@ -30,8 +30,8 @@ #include "fimc-is-regs.h" #include "fimc-is.h" -static int debug; -module_param_named(debug_isp, debug, int, S_IRUGO | S_IWUSR); +int fimc_isp_debug; +module_param_named(debug_isp, fimc_isp_debug, int, S_IRUGO | S_IWUSR); static const struct fimc_fmt fimc_isp_formats[FIMC_ISP_NUM_FORMATS] = { { @@ -128,57 +128,70 @@ static int fimc_isp_subdev_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_format *fmt) { struct fimc_isp *isp = v4l2_get_subdevdata(sd); - struct fimc_is *is = fimc_isp_to_is(isp); struct v4l2_mbus_framefmt *mf = &fmt->format; - struct v4l2_mbus_framefmt cur_fmt; if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { - mf = v4l2_subdev_get_try_format(fh, fmt->pad); - fmt->format = *mf; + *mf = *v4l2_subdev_get_try_format(fh, fmt->pad); return 0; } mf->colorspace = V4L2_COLORSPACE_SRGB; mutex_lock(&isp->subdev_lock); - __is_get_frame_size(is, &cur_fmt); if (fmt->pad == FIMC_ISP_SD_PAD_SINK) { - /* full camera input frame size */ - mf->width = cur_fmt.width + FIMC_ISP_CAC_MARGIN_WIDTH; - mf->height = cur_fmt.height + FIMC_ISP_CAC_MARGIN_HEIGHT; - mf->code = V4L2_MBUS_FMT_SGRBG10_1X10; + /* ISP OTF input image format */ + *mf = isp->sink_fmt; } else { - /* crop size */ - mf->width = cur_fmt.width; - mf->height = cur_fmt.height; - mf->code = V4L2_MBUS_FMT_YUV10_1X30; + /* ISP OTF output image format */ + *mf = isp->src_fmt; + + if (fmt->pad == FIMC_ISP_SD_PAD_SRC_FIFO) { + mf->colorspace = V4L2_COLORSPACE_JPEG; + mf->code = V4L2_MBUS_FMT_YUV10_1X30; + } } mutex_unlock(&isp->subdev_lock); - v4l2_dbg(1, debug, sd, "%s: pad%d: fmt: 0x%x, %dx%d\n", - __func__, fmt->pad, mf->code, mf->width, mf->height); + isp_dbg(1, sd, "%s: pad%d: fmt: 0x%x, %dx%d\n", __func__, + fmt->pad, mf->code, mf->width, mf->height); return 0; } static void __isp_subdev_try_format(struct fimc_isp *isp, - struct v4l2_subdev_format *fmt) + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_format *fmt) { struct v4l2_mbus_framefmt *mf = &fmt->format; + struct v4l2_mbus_framefmt *format; + + mf->colorspace = V4L2_COLORSPACE_SRGB; if (fmt->pad == FIMC_ISP_SD_PAD_SINK) { v4l_bound_align_image(&mf->width, FIMC_ISP_SINK_WIDTH_MIN, FIMC_ISP_SINK_WIDTH_MAX, 0, &mf->height, FIMC_ISP_SINK_HEIGHT_MIN, FIMC_ISP_SINK_HEIGHT_MAX, 0, 0); - isp->subdev_fmt = *mf; + mf->code = V4L2_MBUS_FMT_SGRBG10_1X10; } else { + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) + format = v4l2_subdev_get_try_format(fh, + FIMC_ISP_SD_PAD_SINK); + else + format = &isp->sink_fmt; + /* Allow changing format only on sink pad */ - mf->width = isp->subdev_fmt.width - FIMC_ISP_CAC_MARGIN_WIDTH; - mf->height = isp->subdev_fmt.height - FIMC_ISP_CAC_MARGIN_HEIGHT; - mf->code = isp->subdev_fmt.code; + mf->width = format->width - FIMC_ISP_CAC_MARGIN_WIDTH; + mf->height = format->height - FIMC_ISP_CAC_MARGIN_HEIGHT; + + if (fmt->pad == FIMC_ISP_SD_PAD_SRC_FIFO) { + mf->code = V4L2_MBUS_FMT_YUV10_1X30; + mf->colorspace = V4L2_COLORSPACE_JPEG; + } else { + mf->code = format->code; + } } } @@ -191,27 +204,50 @@ static int fimc_isp_subdev_set_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf = &fmt->format; int ret = 0; - v4l2_dbg(1, debug, sd, "%s: pad%d: code: 0x%x, %dx%d\n", + isp_dbg(1, sd, "%s: pad%d: code: 0x%x, %dx%d\n", __func__, fmt->pad, mf->code, mf->width, mf->height); - mf->colorspace = V4L2_COLORSPACE_SRGB; - mutex_lock(&isp->subdev_lock); - __isp_subdev_try_format(isp, fmt); + __isp_subdev_try_format(isp, fh, fmt); if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { mf = v4l2_subdev_get_try_format(fh, fmt->pad); *mf = fmt->format; - mutex_unlock(&isp->subdev_lock); - return 0; + + /* Propagate format to the source pads */ + if (fmt->pad == FIMC_ISP_SD_PAD_SINK) { + struct v4l2_subdev_format format = *fmt; + unsigned int pad; + + for (pad = FIMC_ISP_SD_PAD_SRC_FIFO; + pad < FIMC_ISP_SD_PADS_NUM; pad++) { + format.pad = pad; + __isp_subdev_try_format(isp, fh, &format); + mf = v4l2_subdev_get_try_format(fh, pad); + *mf = format.format; + } + } + } else { + if (sd->entity.stream_count == 0) { + if (fmt->pad == FIMC_ISP_SD_PAD_SINK) { + struct v4l2_subdev_format format = *fmt; + + isp->sink_fmt = *mf; + + format.pad = FIMC_ISP_SD_PAD_SRC_DMA; + __isp_subdev_try_format(isp, fh, &format); + + isp->src_fmt = format.format; + __is_set_frame_size(is, &isp->src_fmt); + } else { + isp->src_fmt = *mf; + } + } else { + ret = -EBUSY; + } } - if (sd->entity.stream_count == 0) - __is_set_frame_size(is, mf); - else - ret = -EBUSY; mutex_unlock(&isp->subdev_lock); - return ret; } @@ -221,7 +257,7 @@ static int fimc_isp_subdev_s_stream(struct v4l2_subdev *sd, int on) struct fimc_is *is = fimc_isp_to_is(isp); int ret; - v4l2_dbg(1, debug, sd, "%s: on: %d\n", __func__, on); + isp_dbg(1, sd, "%s: on: %d\n", __func__, on); if (!test_bit(IS_ST_INIT_DONE, &is->state)) return -EBUSY; @@ -235,8 +271,8 @@ static int fimc_isp_subdev_s_stream(struct v4l2_subdev *sd, int on) return ret; } - v4l2_dbg(1, debug, sd, "changing mode to %d\n", - is->config_index); + isp_dbg(1, sd, "changing mode to %d\n", is->config_index); + ret = fimc_is_itf_mode_change(is); if (ret) return -EINVAL; @@ -317,8 +353,8 @@ static int fimc_isp_subdev_s_power(struct v4l2_subdev *sd, int on) clear_bit(IS_ST_PWR_ON, &is->state); clear_bit(IS_ST_INIT_DONE, &is->state); is->state = 0; - is->config[is->config_index].p_region_index1 = 0; - is->config[is->config_index].p_region_index2 = 0; + is->config[is->config_index].p_region_index[0] = 0; + is->config[is->config_index].p_region_index[1] = 0; set_bit(IS_ST_IDLE, &is->state); wmb(); } @@ -609,6 +645,22 @@ static const struct v4l2_ctrl_ops fimc_isp_ctrl_ops = { .s_ctrl = fimc_is_s_ctrl, }; +static void __isp_subdev_set_default_format(struct fimc_isp *isp) +{ + struct fimc_is *is = fimc_isp_to_is(isp); + + isp->sink_fmt.width = DEFAULT_PREVIEW_STILL_WIDTH + + FIMC_ISP_CAC_MARGIN_WIDTH; + isp->sink_fmt.height = DEFAULT_PREVIEW_STILL_HEIGHT + + FIMC_ISP_CAC_MARGIN_HEIGHT; + isp->sink_fmt.code = V4L2_MBUS_FMT_SGRBG10_1X10; + + isp->src_fmt.width = DEFAULT_PREVIEW_STILL_WIDTH; + isp->src_fmt.height = DEFAULT_PREVIEW_STILL_HEIGHT; + isp->src_fmt.code = V4L2_MBUS_FMT_SGRBG10_1X10; + __is_set_frame_size(is, &isp->src_fmt); +} + int fimc_isp_subdev_create(struct fimc_isp *isp) { const struct v4l2_ctrl_ops *ops = &fimc_isp_ctrl_ops; @@ -689,6 +741,8 @@ int fimc_isp_subdev_create(struct fimc_isp *isp) sd->entity.ops = &fimc_is_subdev_media_ops; v4l2_set_subdevdata(sd, isp); + __isp_subdev_set_default_format(isp); + return 0; } diff --git a/drivers/media/platform/exynos4-is/fimc-isp.h b/drivers/media/platform/exynos4-is/fimc-isp.h index 800aba7ab4a7..03bf95ab017b 100644 --- a/drivers/media/platform/exynos4-is/fimc-isp.h +++ b/drivers/media/platform/exynos4-is/fimc-isp.h @@ -26,6 +26,11 @@ #include <media/v4l2-mediabus.h> #include <media/s5p_fimc.h> +extern int fimc_isp_debug; + +#define isp_dbg(level, dev, fmt, arg...) \ + v4l2_dbg(level, fimc_isp_debug, dev, fmt, ## arg) + /* FIXME: revisit these constraints */ #define FIMC_ISP_SINK_WIDTH_MIN (16 + 8) #define FIMC_ISP_SINK_HEIGHT_MIN (12 + 8) @@ -118,7 +123,6 @@ struct fimc_is_video { unsigned int frame_count; unsigned int reqbufs_count; int streaming; - unsigned long payload[FIMC_ISP_MAX_PLANES]; const struct fimc_fmt *format; }; @@ -128,15 +132,9 @@ struct fimc_is_video { * @alloc_ctx: videobuf2 memory allocator context * @subdev: ISP v4l2_subdev * @subdev_pads: the ISP subdev media pads - * @ctrl_handler: v4l2 controls handler * @test_pattern: test pattern controls - * @pipeline: video capture pipeline data structure + * @ctrls: v4l2 controls structure * @video_lock: mutex serializing video device and the subdev operations - * @fmt: pointer to color format description structure - * @payload: image size in bytes (w x h x bpp) - * @inp_frame: camera input frame structure - * @out_frame: DMA output frame structure - * @source_subdev_grp_id: group id of remote source subdev * @cac_margin_x: horizontal CAC margin in pixels * @cac_margin_y: vertical CAC margin in pixels * @state: driver state flags @@ -147,17 +145,14 @@ struct fimc_isp { struct vb2_alloc_ctx *alloc_ctx; struct v4l2_subdev subdev; struct media_pad subdev_pads[FIMC_ISP_SD_PADS_NUM]; - struct v4l2_mbus_framefmt subdev_fmt; + struct v4l2_mbus_framefmt src_fmt; + struct v4l2_mbus_framefmt sink_fmt; struct v4l2_ctrl *test_pattern; struct fimc_isp_ctrls ctrls; struct mutex video_lock; struct mutex subdev_lock; - struct fimc_isp_frame inp_frame; - struct fimc_isp_frame out_frame; - unsigned int source_subdev_grp_id; - unsigned int cac_margin_x; unsigned int cac_margin_y; diff --git a/drivers/media/platform/exynos4-is/fimc-lite-reg.c b/drivers/media/platform/exynos4-is/fimc-lite-reg.c index 8cc0d39a2fea..72a343e3b5e8 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite-reg.c +++ b/drivers/media/platform/exynos4-is/fimc-lite-reg.c @@ -2,15 +2,16 @@ * Register interface file for EXYNOS FIMC-LITE (camera interface) driver * * Copyright (C) 2012 Samsung Electronics Co., Ltd. - * Sylwester Nawrocki <s.nawrocki@samsung.com> + * Author: Sylwester Nawrocki <s.nawrocki@samsung.com> * * 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. */ -#include <linux/io.h> +#include <linux/bitops.h> #include <linux/delay.h> +#include <linux/io.h> #include <media/s5p_fimc.h> #include "fimc-lite-reg.h" @@ -68,7 +69,8 @@ void flite_hw_set_interrupt_mask(struct fimc_lite *dev) if (atomic_read(&dev->out_path) == FIMC_IO_DMA) { intsrc = FLITE_REG_CIGCTRL_IRQ_OVFEN | FLITE_REG_CIGCTRL_IRQ_LASTEN | - FLITE_REG_CIGCTRL_IRQ_STARTEN; + FLITE_REG_CIGCTRL_IRQ_STARTEN | + FLITE_REG_CIGCTRL_IRQ_ENDEN; } else { /* An output to the FIMC-IS */ intsrc = FLITE_REG_CIGCTRL_IRQ_OVFEN | @@ -137,7 +139,7 @@ void flite_hw_set_source_format(struct fimc_lite *dev, struct flite_frame *f) } if (i == 0 && src_pixfmt_map[i][0] != pixelcode) { - v4l2_err(&dev->vfd, + v4l2_err(&dev->ve.vdev, "Unsupported pixel code, falling back to %#08x\n", src_pixfmt_map[i][0]); } @@ -215,6 +217,18 @@ void flite_hw_set_camera_bus(struct fimc_lite *dev, flite_hw_set_camera_port(dev, si->mux_id); } +static void flite_hw_set_pack12(struct fimc_lite *dev, int on) +{ + u32 cfg = readl(dev->regs + FLITE_REG_CIODMAFMT); + + cfg &= ~FLITE_REG_CIODMAFMT_PACK12; + + if (on) + cfg |= FLITE_REG_CIODMAFMT_PACK12; + + writel(cfg, dev->regs + FLITE_REG_CIODMAFMT); +} + static void flite_hw_set_out_order(struct fimc_lite *dev, struct flite_frame *f) { static const u32 pixcode[4][2] = { @@ -250,6 +264,38 @@ void flite_hw_set_dma_window(struct fimc_lite *dev, struct flite_frame *f) writel(cfg, dev->regs + FLITE_REG_CIOOFF); } +void flite_hw_set_dma_buffer(struct fimc_lite *dev, struct flite_buffer *buf) +{ + unsigned int index; + u32 cfg; + + if (dev->dd->max_dma_bufs == 1) + index = 0; + else + index = buf->index; + + if (index == 0) + writel(buf->paddr, dev->regs + FLITE_REG_CIOSA); + else + writel(buf->paddr, dev->regs + FLITE_REG_CIOSAN(index - 1)); + + cfg = readl(dev->regs + FLITE_REG_CIFCNTSEQ); + cfg |= BIT(index); + writel(cfg, dev->regs + FLITE_REG_CIFCNTSEQ); +} + +void flite_hw_mask_dma_buffer(struct fimc_lite *dev, u32 index) +{ + u32 cfg; + + if (dev->dd->max_dma_bufs == 1) + index = 0; + + cfg = readl(dev->regs + FLITE_REG_CIFCNTSEQ); + cfg &= ~BIT(index); + writel(cfg, dev->regs + FLITE_REG_CIFCNTSEQ); +} + /* Enable/disable output DMA, set output pixel size and offsets (composition) */ void flite_hw_set_output_dma(struct fimc_lite *dev, struct flite_frame *f, bool enable) @@ -267,6 +313,7 @@ void flite_hw_set_output_dma(struct fimc_lite *dev, struct flite_frame *f, flite_hw_set_out_order(dev, f); flite_hw_set_dma_window(dev, f); + flite_hw_set_pack12(dev, 0); } void flite_hw_dump_regs(struct fimc_lite *dev, const char *label) diff --git a/drivers/media/platform/exynos4-is/fimc-lite-reg.h b/drivers/media/platform/exynos4-is/fimc-lite-reg.h index 390383941c19..10a7d7bbcc27 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite-reg.h +++ b/drivers/media/platform/exynos4-is/fimc-lite-reg.h @@ -120,6 +120,9 @@ /* b0: 1 - camera B, 0 - camera A */ #define FLITE_REG_CIGENERAL_CAM_B (1 << 0) +#define FLITE_REG_CIFCNTSEQ 0x100 +#define FLITE_REG_CIOSAN(x) (0x200 + (4 * (x))) + /* ---------------------------------------------------------------------------- * Function declarations */ @@ -142,9 +145,12 @@ void flite_hw_set_output_dma(struct fimc_lite *dev, struct flite_frame *f, void flite_hw_set_dma_window(struct fimc_lite *dev, struct flite_frame *f); void flite_hw_set_test_pattern(struct fimc_lite *dev, bool on); void flite_hw_dump_regs(struct fimc_lite *dev, const char *label); +void flite_hw_set_dma_buffer(struct fimc_lite *dev, struct flite_buffer *buf); +void flite_hw_mask_dma_buffer(struct fimc_lite *dev, u32 index); -static inline void flite_hw_set_output_addr(struct fimc_lite *dev, u32 paddr) +static inline void flite_hw_set_dma_buf_mask(struct fimc_lite *dev, u32 mask) { - writel(paddr, dev->regs + FLITE_REG_CIOSA); + writel(mask, dev->regs + FLITE_REG_CIFCNTSEQ); } + #endif /* FIMC_LITE_REG_H */ diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c index 14bb7bc8adbe..08fbfedea90f 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite.c +++ b/drivers/media/platform/exynos4-is/fimc-lite.c @@ -1,8 +1,8 @@ /* * Samsung EXYNOS FIMC-LITE (camera host interface) driver * - * Copyright (C) 2012 Samsung Electronics Co., Ltd. - * Sylwester Nawrocki <s.nawrocki@samsung.com> + * Copyright (C) 2012 - 2013 Samsung Electronics Co., Ltd. + * Author: Sylwester Nawrocki <s.nawrocki@samsung.com> * * 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 @@ -32,6 +32,7 @@ #include <media/videobuf2-dma-contig.h> #include <media/s5p_fimc.h> +#include "common.h" #include "fimc-core.h" #include "fimc-lite.h" #include "fimc-lite-reg.h" @@ -43,6 +44,7 @@ static const struct fimc_fmt fimc_lite_formats[] = { { .name = "YUV 4:2:2 packed, YCbYCr", .fourcc = V4L2_PIX_FMT_YUYV, + .colorspace = V4L2_COLORSPACE_JPEG, .depth = { 16 }, .color = FIMC_FMT_YCBYCR422, .memplanes = 1, @@ -51,6 +53,7 @@ static const struct fimc_fmt fimc_lite_formats[] = { }, { .name = "YUV 4:2:2 packed, CbYCrY", .fourcc = V4L2_PIX_FMT_UYVY, + .colorspace = V4L2_COLORSPACE_JPEG, .depth = { 16 }, .color = FIMC_FMT_CBYCRY422, .memplanes = 1, @@ -59,6 +62,7 @@ static const struct fimc_fmt fimc_lite_formats[] = { }, { .name = "YUV 4:2:2 packed, CrYCbY", .fourcc = V4L2_PIX_FMT_VYUY, + .colorspace = V4L2_COLORSPACE_JPEG, .depth = { 16 }, .color = FIMC_FMT_CRYCBY422, .memplanes = 1, @@ -67,6 +71,7 @@ static const struct fimc_fmt fimc_lite_formats[] = { }, { .name = "YUV 4:2:2 packed, YCrYCb", .fourcc = V4L2_PIX_FMT_YVYU, + .colorspace = V4L2_COLORSPACE_JPEG, .depth = { 16 }, .color = FIMC_FMT_YCRYCB422, .memplanes = 1, @@ -75,6 +80,7 @@ static const struct fimc_fmt fimc_lite_formats[] = { }, { .name = "RAW8 (GRBG)", .fourcc = V4L2_PIX_FMT_SGRBG8, + .colorspace = V4L2_COLORSPACE_SRGB, .depth = { 8 }, .color = FIMC_FMT_RAW8, .memplanes = 1, @@ -83,6 +89,7 @@ static const struct fimc_fmt fimc_lite_formats[] = { }, { .name = "RAW10 (GRBG)", .fourcc = V4L2_PIX_FMT_SGRBG10, + .colorspace = V4L2_COLORSPACE_SRGB, .depth = { 10 }, .color = FIMC_FMT_RAW10, .memplanes = 1, @@ -91,6 +98,7 @@ static const struct fimc_fmt fimc_lite_formats[] = { }, { .name = "RAW12 (GRBG)", .fourcc = V4L2_PIX_FMT_SGRBG12, + .colorspace = V4L2_COLORSPACE_SRGB, .depth = { 12 }, .color = FIMC_FMT_RAW12, .memplanes = 1, @@ -131,30 +139,6 @@ static const struct fimc_fmt *fimc_lite_find_format(const u32 *pixelformat, return def_fmt; } -/* Called with the media graph mutex held or @me stream_count > 0. */ -static struct v4l2_subdev *__find_remote_sensor(struct media_entity *me) -{ - struct media_pad *pad = &me->pads[0]; - struct v4l2_subdev *sd; - - while (pad->flags & MEDIA_PAD_FL_SINK) { - /* source pad */ - pad = media_entity_remote_source(pad); - if (pad == NULL || - media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) - break; - - sd = media_entity_to_v4l2_subdev(pad->entity); - - if (sd->grp_id == GRP_ID_FIMC_IS_SENSOR || - sd->grp_id == GRP_ID_SENSOR) - return sd; - /* sink pad */ - pad = &sd->entity.pads[0]; - } - return NULL; -} - static int fimc_lite_hw_init(struct fimc_lite *fimc, bool isp_output) { struct fimc_source_info *si; @@ -176,6 +160,7 @@ static int fimc_lite_hw_init(struct fimc_lite *fimc, bool isp_output) flite_hw_set_camera_bus(fimc, si); flite_hw_set_source_format(fimc, &fimc->inp_frame); flite_hw_set_window_offset(fimc, &fimc->inp_frame); + flite_hw_set_dma_buf_mask(fimc, 0); flite_hw_set_output_dma(fimc, &fimc->out_frame, !isp_output); flite_hw_set_interrupt_mask(fimc); flite_hw_set_test_pattern(fimc, fimc->test_pattern->val); @@ -233,7 +218,7 @@ static int fimc_lite_reinit(struct fimc_lite *fimc, bool suspend) if (!streaming) return 0; - return fimc_pipeline_call(fimc, set_stream, &fimc->pipeline, 0); + return fimc_pipeline_call(&fimc->ve, set_stream, 0); } static int fimc_lite_stop_capture(struct fimc_lite *fimc, bool suspend) @@ -299,19 +284,23 @@ static irqreturn_t flite_irq_handler(int irq, void *priv) if ((intsrc & FLITE_REG_CISTATUS_IRQ_SRC_FRMSTART) && test_bit(ST_FLITE_RUN, &fimc->state) && - !list_empty(&fimc->active_buf_q) && !list_empty(&fimc->pending_buf_q)) { + vbuf = fimc_lite_pending_queue_pop(fimc); + flite_hw_set_dma_buffer(fimc, vbuf); + fimc_lite_active_queue_add(fimc, vbuf); + } + + if ((intsrc & FLITE_REG_CISTATUS_IRQ_SRC_FRMEND) && + test_bit(ST_FLITE_RUN, &fimc->state) && + !list_empty(&fimc->active_buf_q)) { vbuf = fimc_lite_active_queue_pop(fimc); ktime_get_ts(&ts); tv = &vbuf->vb.v4l2_buf.timestamp; tv->tv_sec = ts.tv_sec; tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC; vbuf->vb.v4l2_buf.sequence = fimc->frame_count++; + flite_hw_mask_dma_buffer(fimc, vbuf->index); vb2_buffer_done(&vbuf->vb, VB2_BUF_STATE_DONE); - - vbuf = fimc_lite_pending_queue_pop(fimc); - flite_hw_set_output_addr(fimc, vbuf->paddr); - fimc_lite_active_queue_add(fimc, vbuf); } if (test_bit(ST_FLITE_CONFIG, &fimc->state)) @@ -330,10 +319,16 @@ done: static int start_streaming(struct vb2_queue *q, unsigned int count) { struct fimc_lite *fimc = q->drv_priv; + unsigned long flags; int ret; + spin_lock_irqsave(&fimc->slock, flags); + + fimc->buf_index = 0; fimc->frame_count = 0; + spin_unlock_irqrestore(&fimc->slock, flags); + ret = fimc_lite_hw_init(fimc, false); if (ret) { fimc_lite_reinit(fimc, false); @@ -347,8 +342,7 @@ static int start_streaming(struct vb2_queue *q, unsigned int count) flite_hw_capture_start(fimc); if (!test_and_set_bit(ST_SENSOR_STREAM, &fimc->state)) - fimc_pipeline_call(fimc, set_stream, - &fimc->pipeline, 1); + fimc_pipeline_call(&fimc->ve, set_stream, 1); } if (debug > 0) flite_hw_dump_regs(fimc, __func__); @@ -415,7 +409,7 @@ static int buffer_prepare(struct vb2_buffer *vb) unsigned long size = fimc->payload[i]; if (vb2_plane_size(vb, i) < size) { - v4l2_err(&fimc->vfd, + v4l2_err(&fimc->ve.vdev, "User buffer too small (%ld < %ld)\n", vb2_plane_size(vb, i), size); return -EINVAL; @@ -436,10 +430,14 @@ static void buffer_queue(struct vb2_buffer *vb) spin_lock_irqsave(&fimc->slock, flags); buf->paddr = vb2_dma_contig_plane_dma_addr(vb, 0); + buf->index = fimc->buf_index++; + if (fimc->buf_index >= fimc->reqbufs_count) + fimc->buf_index = 0; + if (!test_bit(ST_FLITE_SUSPENDED, &fimc->state) && !test_bit(ST_FLITE_STREAM, &fimc->state) && list_empty(&fimc->active_buf_q)) { - flite_hw_set_output_addr(fimc, buf->paddr); + flite_hw_set_dma_buffer(fimc, buf); fimc_lite_active_queue_add(fimc, buf); } else { fimc_lite_pending_queue_add(fimc, buf); @@ -452,8 +450,7 @@ static void buffer_queue(struct vb2_buffer *vb) spin_unlock_irqrestore(&fimc->slock, flags); if (!test_and_set_bit(ST_SENSOR_STREAM, &fimc->state)) - fimc_pipeline_call(fimc, set_stream, - &fimc->pipeline, 1); + fimc_pipeline_call(&fimc->ve, set_stream, 1); return; } spin_unlock_irqrestore(&fimc->slock, flags); @@ -481,11 +478,9 @@ static void fimc_lite_clear_event_counters(struct fimc_lite *fimc) static int fimc_lite_open(struct file *file) { struct fimc_lite *fimc = video_drvdata(file); - struct media_entity *me = &fimc->vfd.entity; + struct media_entity *me = &fimc->ve.vdev.entity; int ret; - mutex_lock(&me->parent->graph_mutex); - mutex_lock(&fimc->lock); if (atomic_read(&fimc->out_path) != FIMC_IO_DMA) { ret = -EBUSY; @@ -505,11 +500,18 @@ static int fimc_lite_open(struct file *file) atomic_read(&fimc->out_path) != FIMC_IO_DMA) goto unlock; - ret = fimc_pipeline_call(fimc, open, &fimc->pipeline, - me, true); + mutex_lock(&me->parent->graph_mutex); + + ret = fimc_pipeline_call(&fimc->ve, open, me, true); + + /* Mark video pipeline ending at this video node as in use. */ + if (ret == 0) + me->use_count++; + + mutex_unlock(&me->parent->graph_mutex); + if (!ret) { fimc_lite_clear_event_counters(fimc); - fimc->ref_count++; goto unlock; } @@ -519,26 +521,29 @@ err_pm: clear_bit(ST_FLITE_IN_USE, &fimc->state); unlock: mutex_unlock(&fimc->lock); - mutex_unlock(&me->parent->graph_mutex); return ret; } static int fimc_lite_release(struct file *file) { struct fimc_lite *fimc = video_drvdata(file); + struct media_entity *entity = &fimc->ve.vdev.entity; mutex_lock(&fimc->lock); if (v4l2_fh_is_singular_file(file) && atomic_read(&fimc->out_path) == FIMC_IO_DMA) { if (fimc->streaming) { - media_entity_pipeline_stop(&fimc->vfd.entity); + media_entity_pipeline_stop(entity); fimc->streaming = false; } - clear_bit(ST_FLITE_IN_USE, &fimc->state); fimc_lite_stop_capture(fimc, false); - fimc_pipeline_call(fimc, close, &fimc->pipeline); - fimc->ref_count--; + fimc_pipeline_call(&fimc->ve, close); + clear_bit(ST_FLITE_IN_USE, &fimc->state); + + mutex_lock(&entity->parent->graph_mutex); + entity->use_count--; + mutex_unlock(&entity->parent->graph_mutex); } vb2_fop_release(file); @@ -562,37 +567,54 @@ static const struct v4l2_file_operations fimc_lite_fops = { * Format and crop negotiation helpers */ -static const struct fimc_fmt *fimc_lite_try_format(struct fimc_lite *fimc, - u32 *width, u32 *height, - u32 *code, u32 *fourcc, int pad) +static const struct fimc_fmt *fimc_lite_subdev_try_fmt(struct fimc_lite *fimc, + struct v4l2_subdev_fh *fh, + struct v4l2_subdev_format *format) { struct flite_drvdata *dd = fimc->dd; - const struct fimc_fmt *fmt; - unsigned int flags = 0; + struct v4l2_mbus_framefmt *mf = &format->format; + const struct fimc_fmt *fmt = NULL; + + if (format->pad == FLITE_SD_PAD_SINK) { + v4l_bound_align_image(&mf->width, 8, dd->max_width, + ffs(dd->out_width_align) - 1, + &mf->height, 0, dd->max_height, 0, 0); + + fmt = fimc_lite_find_format(NULL, &mf->code, 0, 0); + if (WARN_ON(!fmt)) + return NULL; - if (pad == FLITE_SD_PAD_SINK) { - v4l_bound_align_image(width, 8, dd->max_width, - ffs(dd->out_width_align) - 1, - height, 0, dd->max_height, 0, 0); + mf->colorspace = fmt->colorspace; + mf->code = fmt->mbus_code; } else { - v4l_bound_align_image(width, 8, fimc->inp_frame.rect.width, - ffs(dd->out_width_align) - 1, - height, 0, fimc->inp_frame.rect.height, - 0, 0); - flags = fimc->inp_frame.fmt->flags; - } + struct flite_frame *sink = &fimc->inp_frame; + struct v4l2_mbus_framefmt *sink_fmt; + struct v4l2_rect *rect; - fmt = fimc_lite_find_format(fourcc, code, flags, 0); - if (WARN_ON(!fmt)) - return NULL; + if (format->which == V4L2_SUBDEV_FORMAT_TRY) { + sink_fmt = v4l2_subdev_get_try_format(fh, + FLITE_SD_PAD_SINK); - if (code) - *code = fmt->mbus_code; - if (fourcc) - *fourcc = fmt->fourcc; + mf->code = sink_fmt->code; + mf->colorspace = sink_fmt->colorspace; - v4l2_dbg(1, debug, &fimc->subdev, "code: 0x%x, %dx%d\n", - code ? *code : 0, *width, *height); + rect = v4l2_subdev_get_try_crop(fh, + FLITE_SD_PAD_SINK); + } else { + mf->code = sink->fmt->mbus_code; + mf->colorspace = sink->fmt->colorspace; + rect = &sink->rect; + } + + /* Allow changing format only on sink pad */ + mf->width = rect->width; + mf->height = rect->height; + } + + mf->field = V4L2_FIELD_NONE; + + v4l2_dbg(1, debug, &fimc->subdev, "code: %#x (%d), %dx%d\n", + mf->code, mf->colorspace, mf->width, mf->height); return fmt; } @@ -637,13 +659,18 @@ static void fimc_lite_try_compose(struct fimc_lite *fimc, struct v4l2_rect *r) /* * Video node ioctl operations */ -static int fimc_vidioc_querycap_capture(struct file *file, void *priv, +static int fimc_lite_querycap(struct file *file, void *priv, struct v4l2_capability *cap) { + struct fimc_lite *fimc = video_drvdata(file); + strlcpy(cap->driver, FIMC_LITE_DRV_NAME, sizeof(cap->driver)); - cap->bus_info[0] = 0; - cap->card[0] = 0; - cap->capabilities = V4L2_CAP_STREAMING; + strlcpy(cap->card, FIMC_LITE_DRV_NAME, sizeof(cap->card)); + snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", + dev_name(&fimc->pdev->dev)); + + cap->device_caps = V4L2_CAP_STREAMING; + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } @@ -679,7 +706,7 @@ static int fimc_lite_g_fmt_mplane(struct file *file, void *fh, pixm->width = frame->f_width; pixm->height = frame->f_height; pixm->field = V4L2_FIELD_NONE; - pixm->colorspace = V4L2_COLORSPACE_JPEG; + pixm->colorspace = fmt->colorspace; return 0; } @@ -722,7 +749,7 @@ static int fimc_lite_try_fmt(struct fimc_lite *fimc, fmt->depth[0]) / 8; pixm->num_planes = fmt->memplanes; pixm->pixelformat = fmt->fourcc; - pixm->colorspace = V4L2_COLORSPACE_JPEG; + pixm->colorspace = fmt->colorspace; pixm->field = V4L2_FIELD_NONE; return 0; } @@ -786,7 +813,7 @@ static int fimc_pipeline_validate(struct fimc_lite *fimc) return -EPIPE; } /* Retrieve format at the source pad */ - pad = media_entity_remote_source(pad); + pad = media_entity_remote_pad(pad); if (pad == NULL || media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) break; @@ -810,14 +837,13 @@ static int fimc_lite_streamon(struct file *file, void *priv, enum v4l2_buf_type type) { struct fimc_lite *fimc = video_drvdata(file); - struct media_entity *entity = &fimc->vfd.entity; - struct fimc_pipeline *p = &fimc->pipeline; + struct media_entity *entity = &fimc->ve.vdev.entity; int ret; if (fimc_lite_active(fimc)) return -EBUSY; - ret = media_entity_pipeline_start(entity, p->m_pipeline); + ret = media_entity_pipeline_start(entity, &fimc->ve.pipe->mp); if (ret < 0) return ret; @@ -825,7 +851,7 @@ static int fimc_lite_streamon(struct file *file, void *priv, if (ret < 0) goto err_p_stop; - fimc->sensor = __find_remote_sensor(&fimc->subdev.entity); + fimc->sensor = fimc_find_remote_sensor(&fimc->subdev.entity); ret = vb2_ioctl_streamon(file, priv, type); if (!ret) { @@ -848,7 +874,7 @@ static int fimc_lite_streamoff(struct file *file, void *priv, if (ret < 0) return ret; - media_entity_pipeline_stop(&fimc->vfd.entity); + media_entity_pipeline_stop(&fimc->ve.vdev.entity); fimc->streaming = false; return 0; } @@ -938,7 +964,7 @@ static int fimc_lite_s_selection(struct file *file, void *fh, } static const struct v4l2_ioctl_ops fimc_lite_ioctl_ops = { - .vidioc_querycap = fimc_vidioc_querycap_capture, + .vidioc_querycap = fimc_lite_querycap, .vidioc_enum_fmt_vid_cap_mplane = fimc_lite_enum_fmt_mplane, .vidioc_try_fmt_vid_cap_mplane = fimc_lite_try_fmt_mplane, .vidioc_s_fmt_vid_cap_mplane = fimc_lite_s_fmt_mplane, @@ -972,8 +998,6 @@ static int fimc_lite_link_setup(struct media_entity *entity, __func__, remote->entity->name, local->entity->name, flags, fimc->source_subdev_grp_id); - mutex_lock(&fimc->lock); - switch (local->index) { case FLITE_SD_PAD_SINK: if (remote_ent_type != MEDIA_ENT_T_V4L2_SUBDEV) { @@ -1015,7 +1039,6 @@ static int fimc_lite_link_setup(struct media_entity *entity, } mb(); - mutex_unlock(&fimc->lock); return ret; } @@ -1036,6 +1059,15 @@ static int fimc_lite_subdev_enum_mbus_code(struct v4l2_subdev *sd, return 0; } +static struct v4l2_mbus_framefmt *__fimc_lite_subdev_get_try_fmt( + struct v4l2_subdev_fh *fh, unsigned int pad) +{ + if (pad != FLITE_SD_PAD_SINK) + pad = FLITE_SD_PAD_SOURCE_DMA; + + return v4l2_subdev_get_try_format(fh, pad); +} + static int fimc_lite_subdev_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, struct v4l2_subdev_format *fmt) @@ -1045,13 +1077,13 @@ static int fimc_lite_subdev_get_fmt(struct v4l2_subdev *sd, struct flite_frame *f = &fimc->inp_frame; if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { - mf = v4l2_subdev_get_try_format(fh, fmt->pad); + mf = __fimc_lite_subdev_get_try_fmt(fh, fmt->pad); fmt->format = *mf; return 0; } - mf->colorspace = V4L2_COLORSPACE_JPEG; mutex_lock(&fimc->lock); + mf->colorspace = f->fmt->colorspace; mf->code = f->fmt->mbus_code; if (fmt->pad == FLITE_SD_PAD_SINK) { @@ -1080,7 +1112,6 @@ static int fimc_lite_subdev_set_fmt(struct v4l2_subdev *sd, v4l2_dbg(1, debug, sd, "pad%d: code: 0x%x, %dx%d\n", fmt->pad, mf->code, mf->width, mf->height); - mf->colorspace = V4L2_COLORSPACE_JPEG; mutex_lock(&fimc->lock); if ((atomic_read(&fimc->out_path) == FIMC_IO_ISP && @@ -1091,12 +1122,20 @@ static int fimc_lite_subdev_set_fmt(struct v4l2_subdev *sd, return -EBUSY; } - ffmt = fimc_lite_try_format(fimc, &mf->width, &mf->height, - &mf->code, NULL, fmt->pad); + ffmt = fimc_lite_subdev_try_fmt(fimc, fh, fmt); if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { - mf = v4l2_subdev_get_try_format(fh, fmt->pad); + struct v4l2_mbus_framefmt *src_fmt; + + mf = __fimc_lite_subdev_get_try_fmt(fh, fmt->pad); *mf = fmt->format; + + if (fmt->pad == FLITE_SD_PAD_SINK) { + unsigned int pad = FLITE_SD_PAD_SOURCE_DMA; + src_fmt = __fimc_lite_subdev_get_try_fmt(fh, pad); + *src_fmt = *mf; + } + mutex_unlock(&fimc->lock); return 0; } @@ -1114,11 +1153,6 @@ static int fimc_lite_subdev_set_fmt(struct v4l2_subdev *sd, source->rect = sink->rect; source->f_width = mf->width; source->f_height = mf->height; - } else { - /* Allow changing format only on sink pad */ - mf->code = sink->fmt->mbus_code; - mf->width = sink->rect.width; - mf->height = sink->rect.height; } mutex_unlock(&fimc->lock); @@ -1207,7 +1241,7 @@ static int fimc_lite_subdev_s_stream(struct v4l2_subdev *sd, int on) * The pipeline links are protected through entity.stream_count * so there is no need to take the media graph mutex here. */ - fimc->sensor = __find_remote_sensor(&sd->entity); + fimc->sensor = fimc_find_remote_sensor(&sd->entity); if (atomic_read(&fimc->out_path) != FIMC_IO_ISP) return -ENOIOCTLCMD; @@ -1252,13 +1286,10 @@ static int fimc_lite_subdev_registered(struct v4l2_subdev *sd) { struct fimc_lite *fimc = v4l2_get_subdevdata(sd); struct vb2_queue *q = &fimc->vb_queue; - struct video_device *vfd = &fimc->vfd; + struct video_device *vfd = &fimc->ve.vdev; int ret; memset(vfd, 0, sizeof(*vfd)); - - fimc->inp_frame.fmt = &fimc_lite_formats[0]; - fimc->out_frame.fmt = &fimc_lite_formats[0]; atomic_set(&fimc->out_path, FIMC_IO_DMA); snprintf(vfd->name, sizeof(vfd->name), "fimc-lite.%d.capture", @@ -1295,12 +1326,12 @@ static int fimc_lite_subdev_registered(struct v4l2_subdev *sd) return ret; video_set_drvdata(vfd, fimc); - fimc->pipeline_ops = v4l2_get_subdev_hostdata(sd); + fimc->ve.pipe = v4l2_get_subdev_hostdata(sd); ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1); if (ret < 0) { media_entity_cleanup(&vfd->entity); - fimc->pipeline_ops = NULL; + fimc->ve.pipe = NULL; return ret; } @@ -1316,11 +1347,15 @@ static void fimc_lite_subdev_unregistered(struct v4l2_subdev *sd) if (fimc == NULL) return; - if (video_is_registered(&fimc->vfd)) { - video_unregister_device(&fimc->vfd); - media_entity_cleanup(&fimc->vfd.entity); - fimc->pipeline_ops = NULL; + mutex_lock(&fimc->lock); + + if (video_is_registered(&fimc->ve.vdev)) { + video_unregister_device(&fimc->ve.vdev); + media_entity_cleanup(&fimc->ve.vdev.entity); + fimc->ve.pipe = NULL; } + + mutex_unlock(&fimc->lock); } static const struct v4l2_subdev_internal_ops fimc_lite_subdev_internal_ops = { @@ -1370,6 +1405,23 @@ static const struct v4l2_ctrl_config fimc_lite_ctrl = { .step = 1, }; +static void fimc_lite_set_default_config(struct fimc_lite *fimc) +{ + struct flite_frame *sink = &fimc->inp_frame; + struct flite_frame *source = &fimc->out_frame; + + sink->fmt = &fimc_lite_formats[0]; + sink->f_width = FLITE_DEFAULT_WIDTH; + sink->f_height = FLITE_DEFAULT_HEIGHT; + + sink->rect.width = FLITE_DEFAULT_WIDTH; + sink->rect.height = FLITE_DEFAULT_HEIGHT; + sink->rect.left = 0; + sink->rect.top = 0; + + *source = *sink; +} + static int fimc_lite_create_capture_subdev(struct fimc_lite *fimc) { struct v4l2_ctrl_handler *handler = &fimc->ctrl_handler; @@ -1417,12 +1469,12 @@ static void fimc_lite_unregister_capture_subdev(struct fimc_lite *fimc) static void fimc_lite_clk_put(struct fimc_lite *fimc) { - if (IS_ERR_OR_NULL(fimc->clock)) + if (IS_ERR(fimc->clock)) return; clk_unprepare(fimc->clock); clk_put(fimc->clock); - fimc->clock = NULL; + fimc->clock = ERR_PTR(-EINVAL); } static int fimc_lite_clk_get(struct fimc_lite *fimc) @@ -1436,7 +1488,7 @@ static int fimc_lite_clk_get(struct fimc_lite *fimc) ret = clk_prepare(fimc->clock); if (ret < 0) { clk_put(fimc->clock); - fimc->clock = NULL; + fimc->clock = ERR_PTR(-EINVAL); } return ret; } @@ -1461,13 +1513,14 @@ static int fimc_lite_probe(struct platform_device *pdev) if (of_id) drv_data = (struct flite_drvdata *)of_id->data; fimc->index = of_alias_get_id(dev->of_node, "fimc-lite"); - } else { - drv_data = fimc_lite_get_drvdata(pdev); - fimc->index = pdev->id; } - if (!drv_data || fimc->index < 0 || fimc->index >= FIMC_LITE_MAX_DEVS) + if (!drv_data || fimc->index >= drv_data->num_instances || + fimc->index < 0) { + dev_err(dev, "Wrong %s node alias\n", + dev->of_node->full_name); return -EINVAL; + } fimc->dd = drv_data; fimc->pdev = pdev; @@ -1514,8 +1567,11 @@ static int fimc_lite_probe(struct platform_device *pdev) ret = PTR_ERR(fimc->alloc_ctx); goto err_pm; } + pm_runtime_put(dev); + fimc_lite_set_default_config(fimc); + dev_dbg(dev, "FIMC-LITE.%d registered successfully\n", fimc->index); return 0; @@ -1565,8 +1621,8 @@ static int fimc_lite_resume(struct device *dev) return 0; INIT_LIST_HEAD(&fimc->active_buf_q); - fimc_pipeline_call(fimc, open, &fimc->pipeline, - &fimc->vfd.entity, false); + fimc_pipeline_call(&fimc->ve, open, + &fimc->ve.vdev.entity, false); fimc_lite_hw_init(fimc, atomic_read(&fimc->out_path) == FIMC_IO_ISP); clear_bit(ST_FLITE_SUSPENDED, &fimc->state); @@ -1592,7 +1648,7 @@ static int fimc_lite_suspend(struct device *dev) if (ret < 0 || !fimc_lite_active(fimc)) return ret; - return fimc_pipeline_call(fimc, close, &fimc->pipeline); + return fimc_pipeline_call(&fimc->ve, close); } #endif /* CONFIG_PM_SLEEP */ @@ -1624,22 +1680,30 @@ static struct flite_drvdata fimc_lite_drvdata_exynos4 = { .out_width_align = 8, .win_hor_offs_align = 2, .out_hor_offs_align = 8, + .max_dma_bufs = 1, + .num_instances = 2, }; -static struct platform_device_id fimc_lite_driver_ids[] = { - { - .name = "exynos-fimc-lite", - .driver_data = (unsigned long)&fimc_lite_drvdata_exynos4, - }, - { /* sentinel */ }, +/* EXYNOS5250 */ +static struct flite_drvdata fimc_lite_drvdata_exynos5 = { + .max_width = 8192, + .max_height = 8192, + .out_width_align = 8, + .win_hor_offs_align = 2, + .out_hor_offs_align = 8, + .max_dma_bufs = 32, + .num_instances = 3, }; -MODULE_DEVICE_TABLE(platform, fimc_lite_driver_ids); static const struct of_device_id flite_of_match[] = { { .compatible = "samsung,exynos4212-fimc-lite", .data = &fimc_lite_drvdata_exynos4, }, + { + .compatible = "samsung,exynos5250-fimc-lite", + .data = &fimc_lite_drvdata_exynos5, + }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, flite_of_match); @@ -1647,7 +1711,6 @@ MODULE_DEVICE_TABLE(of, flite_of_match); static struct platform_driver fimc_lite_driver = { .probe = fimc_lite_probe, .remove = fimc_lite_remove, - .id_table = fimc_lite_driver_ids, .driver = { .of_match_table = flite_of_match, .name = FIMC_LITE_DRV_NAME, diff --git a/drivers/media/platform/exynos4-is/fimc-lite.h b/drivers/media/platform/exynos4-is/fimc-lite.h index 47da5e049247..7428b2d22b52 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite.h +++ b/drivers/media/platform/exynos4-is/fimc-lite.h @@ -27,8 +27,10 @@ #define FIMC_LITE_DRV_NAME "exynos-fimc-lite" #define FLITE_CLK_NAME "flite" -#define FIMC_LITE_MAX_DEVS 2 +#define FIMC_LITE_MAX_DEVS 3 #define FLITE_REQ_BUFS_MIN 2 +#define FLITE_DEFAULT_WIDTH 640 +#define FLITE_DEFAULT_HEIGHT 480 /* Bit index definitions for struct fimc_lite::state */ enum { @@ -48,17 +50,28 @@ enum { #define FLITE_SD_PAD_SOURCE_ISP 2 #define FLITE_SD_PADS_NUM 3 +/** + * struct flite_drvdata - FIMC-LITE IP variant data structure + * @max_width: maximum camera interface input width in pixels + * @max_height: maximum camera interface input height in pixels + * @out_width_align: minimum output width alignment in pixels + * @win_hor_offs_align: minimum camera interface crop window horizontal + * offset alignment in pixels + * @out_hor_offs_align: minimum output DMA compose rectangle horizontal + * offset alignment in pixels + * @max_dma_bufs: number of output DMA buffer start address registers + * @num_instances: total number of FIMC-LITE IP instances available + */ struct flite_drvdata { unsigned short max_width; unsigned short max_height; unsigned short out_width_align; unsigned short win_hor_offs_align; unsigned short out_hor_offs_align; + unsigned short max_dma_bufs; + unsigned short num_instances; }; -#define fimc_lite_get_drvdata(_pdev) \ - ((struct flite_drvdata *) platform_get_device_id(_pdev)->driver_data) - struct fimc_lite_events { unsigned int data_overflow; }; @@ -83,20 +96,22 @@ struct flite_frame { * struct flite_buffer - video buffer structure * @vb: vb2 buffer * @list: list head for the buffers queue - * @paddr: precalculated physical address + * @paddr: DMA buffer start address + * @index: DMA start address register's index */ struct flite_buffer { struct vb2_buffer vb; struct list_head list; dma_addr_t paddr; + unsigned short index; }; /** * struct fimc_lite - fimc lite structure * @pdev: pointer to FIMC-LITE platform device * @dd: SoC specific driver data structure + * @ve: exynos video device entity structure * @v4l2_dev: pointer to top the level v4l2_device - * @vfd: video device node * @fh: v4l2 file handle * @alloc_ctx: videobuf2 memory allocator context * @subdev: FIMC-LITE subdev @@ -122,16 +137,16 @@ struct flite_buffer { * @pending_buf_q: pending buffers queue head * @active_buf_q: the queue head of buffers scheduled in hardware * @vb_queue: vb2 buffers queue + * @buf_index: helps to keep track of the DMA start address register index * @active_buf_count: number of video buffers scheduled in hardware * @frame_count: the captured frames counter * @reqbufs_count: the number of buffers requested with REQBUFS ioctl - * @ref_count: driver's private reference counter */ struct fimc_lite { struct platform_device *pdev; struct flite_drvdata *dd; + struct exynos_video_entity ve; struct v4l2_device *v4l2_dev; - struct video_device vfd; struct v4l2_fh fh; struct vb2_alloc_ctx *alloc_ctx; struct v4l2_subdev subdev; @@ -141,8 +156,6 @@ struct fimc_lite { struct v4l2_ctrl_handler ctrl_handler; struct v4l2_ctrl *test_pattern; int index; - struct fimc_pipeline pipeline; - const struct fimc_pipeline_ops *pipeline_ops; struct mutex lock; spinlock_t slock; @@ -161,9 +174,9 @@ struct fimc_lite { struct list_head pending_buf_q; struct list_head active_buf_q; struct vb2_queue vb_queue; + unsigned short buf_index; unsigned int frame_count; unsigned int reqbufs_count; - int ref_count; struct fimc_lite_events events; bool streaming; diff --git a/drivers/media/platform/exynos4-is/fimc-m2m.c b/drivers/media/platform/exynos4-is/fimc-m2m.c index bde1f47f7ed3..8d33b68c76ba 100644 --- a/drivers/media/platform/exynos4-is/fimc-m2m.c +++ b/drivers/media/platform/exynos4-is/fimc-m2m.c @@ -27,6 +27,7 @@ #include <media/videobuf2-core.h> #include <media/videobuf2-dma-contig.h> +#include "common.h" #include "fimc-core.h" #include "fimc-reg.h" #include "media-dev.h" diff --git a/drivers/media/platform/exynos4-is/fimc-reg.c b/drivers/media/platform/exynos4-is/fimc-reg.c index f079f36099de..1db8cb4c46ef 100644 --- a/drivers/media/platform/exynos4-is/fimc-reg.c +++ b/drivers/media/platform/exynos4-is/fimc-reg.c @@ -618,7 +618,7 @@ int fimc_hw_set_camera_source(struct fimc_dev *fimc, } if (i == ARRAY_SIZE(pix_desc)) { - v4l2_err(&vc->vfd, + v4l2_err(&vc->ve.vdev, "Camera color format not supported: %d\n", vc->ci_fmt.code); return -EINVAL; @@ -698,7 +698,7 @@ int fimc_hw_set_camera_type(struct fimc_dev *fimc, cfg |= FIMC_REG_CIGCTRL_CAM_JPEG; break; default: - v4l2_err(&vid_cap->vfd, + v4l2_err(&vid_cap->ve.vdev, "Not supported camera pixel format: %#x\n", vid_cap->ci_fmt.code); return -EINVAL; @@ -721,7 +721,8 @@ int fimc_hw_set_camera_type(struct fimc_dev *fimc, WARN_ONCE(1, "ISP Writeback input is not supported\n"); break; default: - v4l2_err(&vid_cap->vfd, "Invalid FIMC bus type selected: %d\n", + v4l2_err(&vid_cap->ve.vdev, + "Invalid FIMC bus type selected: %d\n", source->fimc_bus_type); return -EINVAL; } diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index 15ef8f28239b..19f556c5957f 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c @@ -1,8 +1,8 @@ /* * S5P/EXYNOS4 SoC series camera host interface media device driver * - * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. - * Sylwester Nawrocki <s.nawrocki@samsung.com> + * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. + * Author: Sylwester Nawrocki <s.nawrocki@samsung.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 @@ -39,6 +39,26 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd, struct fimc_source_info *si, bool on); + +/* Set up image sensor subdev -> FIMC capture node notifications. */ +static void __setup_sensor_notification(struct fimc_md *fmd, + struct v4l2_subdev *sensor, + struct v4l2_subdev *fimc_sd) +{ + struct fimc_source_info *src_inf; + struct fimc_sensor_info *md_si; + unsigned long flags; + + src_inf = v4l2_get_subdev_hostdata(sensor); + if (!src_inf || WARN_ON(fmd == NULL)) + return; + + md_si = source_to_sensor_info(src_inf); + spin_lock_irqsave(&fmd->slock, flags); + md_si->host = v4l2_get_subdevdata(fimc_sd); + spin_unlock_irqrestore(&fmd->slock, flags); +} + /** * fimc_pipeline_prepare - update pipeline information with subdevice pointers * @me: media entity terminating the pipeline @@ -46,9 +66,11 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd, * Caller holds the graph mutex. */ static void fimc_pipeline_prepare(struct fimc_pipeline *p, - struct media_entity *me) + struct media_entity *me) { + struct fimc_md *fmd = entity_to_fimc_mdev(me); struct v4l2_subdev *sd; + struct v4l2_subdev *sensor = NULL; int i; for (i = 0; i < IDX_MAX; i++) @@ -62,7 +84,7 @@ static void fimc_pipeline_prepare(struct fimc_pipeline *p, struct media_pad *spad = &me->pads[i]; if (!(spad->flags & MEDIA_PAD_FL_SINK)) continue; - pad = media_entity_remote_source(spad); + pad = media_entity_remote_pad(spad); if (pad) break; } @@ -73,8 +95,10 @@ static void fimc_pipeline_prepare(struct fimc_pipeline *p, sd = media_entity_to_v4l2_subdev(pad->entity); switch (sd->grp_id) { - case GRP_ID_FIMC_IS_SENSOR: case GRP_ID_SENSOR: + sensor = sd; + /* fall through */ + case GRP_ID_FIMC_IS_SENSOR: p->subdevs[IDX_SENSOR] = sd; break; case GRP_ID_CSIS: @@ -84,7 +108,7 @@ static void fimc_pipeline_prepare(struct fimc_pipeline *p, p->subdevs[IDX_FLITE] = sd; break; case GRP_ID_FIMC: - /* No need to control FIMC subdev through subdev ops */ + p->subdevs[IDX_FIMC] = sd; break; case GRP_ID_FIMC_IS: p->subdevs[IDX_IS_ISP] = sd; @@ -96,6 +120,9 @@ static void fimc_pipeline_prepare(struct fimc_pipeline *p, if (me->num_pads == 1) break; } + + if (sensor && p->subdevs[IDX_FIMC]) + __setup_sensor_notification(fmd, sensor, p->subdevs[IDX_FIMC]); } /** @@ -168,10 +195,11 @@ error: * * Called with the graph mutex held. */ -static int __fimc_pipeline_open(struct fimc_pipeline *p, +static int __fimc_pipeline_open(struct exynos_media_pipeline *ep, struct media_entity *me, bool prepare) { struct fimc_md *fmd = entity_to_fimc_mdev(me); + struct fimc_pipeline *p = to_fimc_pipeline(ep); struct v4l2_subdev *sd; int ret; @@ -214,20 +242,21 @@ err_wbclk: * * Disable power of all subdevs and turn the external sensor clock off. */ -static int __fimc_pipeline_close(struct fimc_pipeline *p) +static int __fimc_pipeline_close(struct exynos_media_pipeline *ep) { + struct fimc_pipeline *p = to_fimc_pipeline(ep); struct v4l2_subdev *sd = p ? p->subdevs[IDX_SENSOR] : NULL; struct fimc_md *fmd; - int ret = 0; - - if (WARN_ON(sd == NULL)) - return -EINVAL; + int ret; - if (p->subdevs[IDX_SENSOR]) { - ret = fimc_pipeline_s_power(p, 0); - fimc_md_set_camclk(sd, false); + if (sd == NULL) { + pr_warn("%s(): No sensor subdev\n", __func__); + return 0; } + ret = fimc_pipeline_s_power(p, 0); + fimc_md_set_camclk(sd, false); + fmd = entity_to_fimc_mdev(&sd->entity); /* Disable PXLASYNC clock if this pipeline includes FIMC-IS */ @@ -242,12 +271,13 @@ static int __fimc_pipeline_close(struct fimc_pipeline *p) * @pipeline: video pipeline structure * @on: passed as the s_stream() callback argument */ -static int __fimc_pipeline_s_stream(struct fimc_pipeline *p, bool on) +static int __fimc_pipeline_s_stream(struct exynos_media_pipeline *ep, bool on) { static const u8 seq[2][IDX_MAX] = { { IDX_FIMC, IDX_SENSOR, IDX_IS_ISP, IDX_CSIS, IDX_FLITE }, { IDX_CSIS, IDX_FLITE, IDX_FIMC, IDX_SENSOR, IDX_IS_ISP }, }; + struct fimc_pipeline *p = to_fimc_pipeline(ep); int i, ret = 0; if (p->subdevs[IDX_SENSOR] == NULL) @@ -271,12 +301,38 @@ error: } /* Media pipeline operations for the FIMC/FIMC-LITE video device driver */ -static const struct fimc_pipeline_ops fimc_pipeline_ops = { +static const struct exynos_media_pipeline_ops fimc_pipeline_ops = { .open = __fimc_pipeline_open, .close = __fimc_pipeline_close, .set_stream = __fimc_pipeline_s_stream, }; +static struct exynos_media_pipeline *fimc_md_pipeline_create( + struct fimc_md *fmd) +{ + struct fimc_pipeline *p; + + p = kzalloc(sizeof(*p), GFP_KERNEL); + if (!p) + return NULL; + + list_add_tail(&p->list, &fmd->pipelines); + + p->ep.ops = &fimc_pipeline_ops; + return &p->ep; +} + +static void fimc_md_pipelines_free(struct fimc_md *fmd) +{ + while (!list_empty(&fmd->pipelines)) { + struct fimc_pipeline *p; + + p = list_entry(fmd->pipelines.next, typeof(*p), list); + list_del(&p->list); + kfree(p); + } +} + /* * Sensor subdevice helper functions */ @@ -592,6 +648,7 @@ static int register_fimc_lite_entity(struct fimc_md *fmd, struct fimc_lite *fimc_lite) { struct v4l2_subdev *sd; + struct exynos_media_pipeline *ep; int ret; if (WARN_ON(fimc_lite->index >= FIMC_LITE_MAX_DEVS || @@ -600,7 +657,12 @@ static int register_fimc_lite_entity(struct fimc_md *fmd, sd = &fimc_lite->subdev; sd->grp_id = GRP_ID_FLITE; - v4l2_set_subdev_hostdata(sd, (void *)&fimc_pipeline_ops); + + ep = fimc_md_pipeline_create(fmd); + if (!ep) + return -ENOMEM; + + v4l2_set_subdev_hostdata(sd, ep); ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd); if (!ret) @@ -614,6 +676,7 @@ static int register_fimc_lite_entity(struct fimc_md *fmd, static int register_fimc_entity(struct fimc_md *fmd, struct fimc_dev *fimc) { struct v4l2_subdev *sd; + struct exynos_media_pipeline *ep; int ret; if (WARN_ON(fimc->id >= FIMC_MAX_DEVS || fmd->fimc[fimc->id])) @@ -621,7 +684,12 @@ static int register_fimc_entity(struct fimc_md *fmd, struct fimc_dev *fimc) sd = &fimc->vid_cap.subdev; sd->grp_id = GRP_ID_FIMC; - v4l2_set_subdev_hostdata(sd, (void *)&fimc_pipeline_ops); + + ep = fimc_md_pipeline_create(fmd); + if (!ep) + return -ENOMEM; + + v4l2_set_subdev_hostdata(sd, ep); ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd); if (!ret) { @@ -736,8 +804,6 @@ static int fimc_md_pdev_match(struct device *dev, void *data) if (!strcmp(pdev->name, CSIS_DRIVER_NAME)) { plat_entity = IDX_CSIS; - } else if (!strcmp(pdev->name, FIMC_LITE_DRV_NAME)) { - plat_entity = IDX_FLITE; } else { p = strstr(pdev->name, "fimc"); if (p && *(p + 4) == 0) @@ -797,17 +863,19 @@ static void fimc_md_unregister_entities(struct fimc_md *fmd) int i; for (i = 0; i < FIMC_MAX_DEVS; i++) { - if (fmd->fimc[i] == NULL) + struct fimc_dev *dev = fmd->fimc[i]; + if (dev == NULL) continue; - v4l2_device_unregister_subdev(&fmd->fimc[i]->vid_cap.subdev); - fmd->fimc[i]->pipeline_ops = NULL; + v4l2_device_unregister_subdev(&dev->vid_cap.subdev); + dev->vid_cap.ve.pipe = NULL; fmd->fimc[i] = NULL; } for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) { - if (fmd->fimc_lite[i] == NULL) + struct fimc_lite *dev = fmd->fimc_lite[i]; + if (dev == NULL) continue; - v4l2_device_unregister_subdev(&fmd->fimc_lite[i]->subdev); - fmd->fimc_lite[i]->pipeline_ops = NULL; + v4l2_device_unregister_subdev(&dev->subdev); + dev->ve.pipe = NULL; fmd->fimc_lite[i] = NULL; } for (i = 0; i < CSIS_MAX_ENTITIES; i++) { @@ -880,18 +948,6 @@ static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd, v4l2_info(&fmd->v4l2_dev, "created link [%s] %c> [%s]\n", source->name, flags ? '=' : '-', sink->name); - - if (flags == 0 || sensor == NULL) - continue; - - if (!WARN_ON(si == NULL)) { - unsigned long irq_flags; - struct fimc_sensor_info *inf = source_to_sensor_info(si); - - spin_lock_irqsave(&fmd->slock, irq_flags); - inf->host = fmd->fimc[i]; - spin_unlock_irqrestore(&fmd->slock, irq_flags); - } } for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) { @@ -929,7 +985,7 @@ static int __fimc_md_create_flite_source_links(struct fimc_md *fmd) continue; source = &fimc->subdev.entity; - sink = &fimc->vfd.entity; + sink = &fimc->ve.vdev.entity; /* FIMC-LITE's subdev and video node */ ret = media_entity_create_link(source, FLITE_SD_PAD_SOURCE_DMA, sink, 0, 0); @@ -1066,7 +1122,7 @@ static int fimc_md_create_links(struct fimc_md *fmd) continue; source = &fmd->fimc[i]->vid_cap.subdev.entity; - sink = &fmd->fimc[i]->vid_cap.vfd.entity; + sink = &fmd->fimc[i]->vid_cap.ve.vdev.entity; ret = media_entity_create_link(source, FIMC_SD_PAD_SOURCE, sink, 0, flags); @@ -1231,66 +1287,98 @@ int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on) return __fimc_md_set_camclk(fmd, si, on); } -static int fimc_md_link_notify(struct media_pad *source, - struct media_pad *sink, u32 flags) +static int __fimc_md_modify_pipeline(struct media_entity *entity, bool enable) { - struct fimc_lite *fimc_lite = NULL; - struct fimc_dev *fimc = NULL; - struct fimc_pipeline *pipeline; - struct v4l2_subdev *sd; - struct mutex *lock; - int i, ret = 0; - int ref_count; + struct exynos_video_entity *ve; + struct fimc_pipeline *p; + struct video_device *vdev; + int ret; - if (media_entity_type(sink->entity) != MEDIA_ENT_T_V4L2_SUBDEV) + vdev = media_entity_to_video_device(entity); + if (vdev->entity.use_count == 0) return 0; - sd = media_entity_to_v4l2_subdev(sink->entity); - - switch (sd->grp_id) { - case GRP_ID_FLITE: - fimc_lite = v4l2_get_subdevdata(sd); - if (WARN_ON(fimc_lite == NULL)) - return 0; - pipeline = &fimc_lite->pipeline; - lock = &fimc_lite->lock; - break; - case GRP_ID_FIMC: - fimc = v4l2_get_subdevdata(sd); - if (WARN_ON(fimc == NULL)) - return 0; - pipeline = &fimc->pipeline; - lock = &fimc->lock; - break; - default: + ve = vdev_to_exynos_video_entity(vdev); + p = to_fimc_pipeline(ve->pipe); + /* + * Nothing to do if we are disabling the pipeline, some link + * has been disconnected and p->subdevs array is cleared now. + */ + if (!enable && p->subdevs[IDX_SENSOR] == NULL) return 0; + + if (enable) + ret = __fimc_pipeline_open(ve->pipe, entity, true); + else + ret = __fimc_pipeline_close(ve->pipe); + + if (ret == 0 && !enable) + memset(p->subdevs, 0, sizeof(p->subdevs)); + + return ret; +} + +/* Locking: called with entity->parent->graph_mutex mutex held. */ +static int __fimc_md_modify_pipelines(struct media_entity *entity, bool enable) +{ + struct media_entity *entity_err = entity; + struct media_entity_graph graph; + int ret; + + /* + * Walk current graph and call the pipeline open/close routine for each + * opened video node that belongs to the graph of entities connected + * through active links. This is needed as we cannot power on/off the + * subdevs in random order. + */ + media_entity_graph_walk_start(&graph, entity); + + while ((entity = media_entity_graph_walk_next(&graph))) { + if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE) + continue; + + ret = __fimc_md_modify_pipeline(entity, enable); + + if (ret < 0) + goto err; } - mutex_lock(lock); - ref_count = fimc ? fimc->vid_cap.refcnt : fimc_lite->ref_count; + return 0; + err: + media_entity_graph_walk_start(&graph, entity_err); - if (!(flags & MEDIA_LNK_FL_ENABLED)) { - if (ref_count > 0) { - ret = __fimc_pipeline_close(pipeline); - if (!ret && fimc) - fimc_ctrls_delete(fimc->vid_cap.ctx); - } - for (i = 0; i < IDX_MAX; i++) - pipeline->subdevs[i] = NULL; - } else if (ref_count > 0) { - /* - * Link activation. Enable power of pipeline elements only if - * the pipeline is already in use, i.e. its video node is open. - * Recreate the controls destroyed during the link deactivation. - */ - ret = __fimc_pipeline_open(pipeline, - source->entity, true); - if (!ret && fimc) - ret = fimc_capture_ctrls_create(fimc); + while ((entity_err = media_entity_graph_walk_next(&graph))) { + if (media_entity_type(entity_err) != MEDIA_ENT_T_DEVNODE) + continue; + + __fimc_md_modify_pipeline(entity_err, !enable); + + if (entity_err == entity) + break; + } + + return ret; +} + +static int fimc_md_link_notify(struct media_link *link, unsigned int flags, + unsigned int notification) +{ + struct media_entity *sink = link->sink->entity; + int ret = 0; + + /* Before link disconnection */ + if (notification == MEDIA_DEV_NOTIFY_PRE_LINK_CH) { + if (!(flags & MEDIA_LNK_FL_ENABLED)) + ret = __fimc_md_modify_pipelines(sink, false); + else + ; /* TODO: Link state change validation */ + /* After link activation */ + } else if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH && + (link->flags & MEDIA_LNK_FL_ENABLED)) { + ret = __fimc_md_modify_pipelines(sink, true); } - mutex_unlock(lock); - return ret ? -EPIPE : ret; + return ret ? -EPIPE : 0; } static ssize_t fimc_md_sysfs_show(struct device *dev, @@ -1370,6 +1458,7 @@ static int fimc_md_probe(struct platform_device *pdev) spin_lock_init(&fmd->slock); fmd->pdev = pdev; + INIT_LIST_HEAD(&fmd->pipelines); strlcpy(fmd->media_dev.model, "SAMSUNG S5P FIMC", sizeof(fmd->media_dev.model)); @@ -1457,6 +1546,7 @@ static int fimc_md_remove(struct platform_device *pdev) return 0; device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode); fimc_md_unregister_entities(fmd); + fimc_md_pipelines_free(fmd); media_device_unregister(&fmd->media_dev); fimc_md_put_clocks(fmd); return 0; diff --git a/drivers/media/platform/exynos4-is/media-dev.h b/drivers/media/platform/exynos4-is/media-dev.h index 44d86b61d660..62599fd7756f 100644 --- a/drivers/media/platform/exynos4-is/media-dev.h +++ b/drivers/media/platform/exynos4-is/media-dev.h @@ -18,6 +18,7 @@ #include <media/media-entity.h> #include <media/v4l2-device.h> #include <media/v4l2-subdev.h> +#include <media/s5p_fimc.h> #include "fimc-core.h" #include "fimc-lite.h" @@ -40,6 +41,29 @@ enum { FIMC_MAX_WBCLKS }; +enum fimc_subdev_index { + IDX_SENSOR, + IDX_CSIS, + IDX_FLITE, + IDX_IS_ISP, + IDX_FIMC, + IDX_MAX, +}; + +/* + * This structure represents a chain of media entities, including a data + * source entity (e.g. an image sensor subdevice), a data capture entity + * - a video capture device node and any remaining entities. + */ +struct fimc_pipeline { + struct exynos_media_pipeline ep; + struct list_head list; + struct media_entity *vdev_entity; + struct v4l2_subdev *subdevs[IDX_MAX]; +}; + +#define to_fimc_pipeline(_ep) container_of(_ep, struct fimc_pipeline, ep) + struct fimc_csis_info { struct v4l2_subdev *sd; int id; @@ -104,17 +128,11 @@ struct fimc_md { struct pinctrl_state *state_idle; } pinctl; bool user_subdev_api; + spinlock_t slock; + struct list_head pipelines; }; -#define is_subdev_pad(pad) (pad == NULL || \ - media_entity_type(pad->entity) == MEDIA_ENT_T_V4L2_SUBDEV) - -#define me_subtype(me) \ - ((me->type) & (MEDIA_ENT_TYPE_MASK | MEDIA_ENT_SUBTYPE_MASK)) - -#define subdev_has_devnode(__sd) (__sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE) - static inline struct fimc_sensor_info *source_to_sensor_info(struct fimc_source_info *si) { @@ -127,14 +145,14 @@ static inline struct fimc_md *entity_to_fimc_mdev(struct media_entity *me) container_of(me->parent, struct fimc_md, media_dev); } -static inline void fimc_md_graph_lock(struct fimc_dev *fimc) +static inline void fimc_md_graph_lock(struct exynos_video_entity *ve) { - mutex_lock(&fimc->vid_cap.vfd.entity.parent->graph_mutex); + mutex_lock(&ve->vdev.entity.parent->graph_mutex); } -static inline void fimc_md_graph_unlock(struct fimc_dev *fimc) +static inline void fimc_md_graph_unlock(struct exynos_video_entity *ve) { - mutex_unlock(&fimc->vid_cap.vfd.entity.parent->graph_mutex); + mutex_unlock(&ve->vdev.entity.parent->graph_mutex); } int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on); @@ -149,4 +167,16 @@ static inline bool fimc_md_is_isp_available(struct device_node *node) #define fimc_md_is_isp_available(node) (false) #endif /* CONFIG_OF */ +static inline struct v4l2_subdev *__fimc_md_get_subdev( + struct exynos_media_pipeline *ep, + unsigned int index) +{ + struct fimc_pipeline *p = to_fimc_pipeline(ep); + + if (!p || index >= IDX_MAX) + return NULL; + else + return p->subdevs[index]; +} + #endif diff --git a/drivers/media/platform/exynos4-is/mipi-csis.c b/drivers/media/platform/exynos4-is/mipi-csis.c index 254d70fe762a..0914230b42de 100644 --- a/drivers/media/platform/exynos4-is/mipi-csis.c +++ b/drivers/media/platform/exynos4-is/mipi-csis.c @@ -1,8 +1,8 @@ /* - * Samsung S5P/EXYNOS4 SoC series MIPI-CSI receiver driver + * Samsung S5P/EXYNOS SoC series MIPI-CSI receiver driver * - * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. - * Sylwester Nawrocki <s.nawrocki@samsung.com> + * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. + * Author: Sylwester Nawrocki <s.nawrocki@samsung.com> * * 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 @@ -66,11 +66,12 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)"); /* Interrupt mask */ #define S5PCSIS_INTMSK 0x10 -#define S5PCSIS_INTMSK_EN_ALL 0xf000103f #define S5PCSIS_INTMSK_EVEN_BEFORE (1 << 31) #define S5PCSIS_INTMSK_EVEN_AFTER (1 << 30) #define S5PCSIS_INTMSK_ODD_BEFORE (1 << 29) #define S5PCSIS_INTMSK_ODD_AFTER (1 << 28) +#define S5PCSIS_INTMSK_FRAME_START (1 << 27) +#define S5PCSIS_INTMSK_FRAME_END (1 << 26) #define S5PCSIS_INTMSK_ERR_SOT_HS (1 << 12) #define S5PCSIS_INTMSK_ERR_LOST_FS (1 << 5) #define S5PCSIS_INTMSK_ERR_LOST_FE (1 << 4) @@ -78,6 +79,8 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)"); #define S5PCSIS_INTMSK_ERR_ECC (1 << 2) #define S5PCSIS_INTMSK_ERR_CRC (1 << 1) #define S5PCSIS_INTMSK_ERR_UNKNOWN (1 << 0) +#define S5PCSIS_INTMSK_EXYNOS4_EN_ALL 0xf000103f +#define S5PCSIS_INTMSK_EXYNOS5_EN_ALL 0xfc00103f /* Interrupt source */ #define S5PCSIS_INTSRC 0x14 @@ -88,6 +91,8 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)"); #define S5PCSIS_INTSRC_ODD_AFTER (1 << 28) #define S5PCSIS_INTSRC_ODD (0x3 << 28) #define S5PCSIS_INTSRC_NON_IMAGE_DATA (0xff << 28) +#define S5PCSIS_INTSRC_FRAME_START (1 << 27) +#define S5PCSIS_INTSRC_FRAME_END (1 << 26) #define S5PCSIS_INTSRC_ERR_SOT_HS (0xf << 12) #define S5PCSIS_INTSRC_ERR_LOST_FS (1 << 5) #define S5PCSIS_INTSRC_ERR_LOST_FE (1 << 4) @@ -151,6 +156,9 @@ static const struct s5pcsis_event s5pcsis_events[] = { { S5PCSIS_INTSRC_EVEN_AFTER, "Non-image data after even frame" }, { S5PCSIS_INTSRC_ODD_BEFORE, "Non-image data before odd frame" }, { S5PCSIS_INTSRC_ODD_AFTER, "Non-image data after odd frame" }, + /* Frame start/end */ + { S5PCSIS_INTSRC_FRAME_START, "Frame Start" }, + { S5PCSIS_INTSRC_FRAME_END, "Frame End" }, }; #define S5PCSIS_NUM_EVENTS ARRAY_SIZE(s5pcsis_events) @@ -159,6 +167,11 @@ struct csis_pktbuf { unsigned int len; }; +struct csis_drvdata { + /* Mask of all used interrupts in S5PCSIS_INTMSK register */ + u32 interrupt_mask; +}; + /** * struct csis_state - the driver's internal state data structure * @lock: mutex serializing the subdev and power management operations, @@ -171,6 +184,7 @@ struct csis_pktbuf { * @supplies: CSIS regulator supplies * @clock: CSIS clocks * @irq: requested s5p-mipi-csis irq number + * @interrupt_mask: interrupt mask of the all used interrupts * @flags: the state variable for power and streaming control * @clock_frequency: device bus clock frequency * @hs_settle: HS-RX settle time @@ -193,6 +207,7 @@ struct csis_state { struct regulator_bulk_data supplies[CSIS_NUM_SUPPLIES]; struct clk *clock[NUM_CSIS_CLOCKS]; int irq; + u32 interrupt_mask; u32 flags; u32 clk_frequency; @@ -274,9 +289,10 @@ static const struct csis_pix_format *find_csis_format( static void s5pcsis_enable_interrupts(struct csis_state *state, bool on) { u32 val = s5pcsis_read(state, S5PCSIS_INTMSK); - - val = on ? val | S5PCSIS_INTMSK_EN_ALL : - val & ~S5PCSIS_INTMSK_EN_ALL; + if (on) + val |= state->interrupt_mask; + else + val &= ~state->interrupt_mask; s5pcsis_write(state, S5PCSIS_INTMSK, val); } @@ -771,8 +787,12 @@ static int s5pcsis_parse_dt(struct platform_device *pdev, #define s5pcsis_parse_dt(pdev, state) (-ENOSYS) #endif +static const struct of_device_id s5pcsis_of_match[]; + static int s5pcsis_probe(struct platform_device *pdev) { + const struct of_device_id *of_id; + const struct csis_drvdata *drv_data; struct device *dev = &pdev->dev; struct resource *mem_res; struct csis_state *state; @@ -787,10 +807,19 @@ static int s5pcsis_probe(struct platform_device *pdev) spin_lock_init(&state->slock); state->pdev = pdev; - if (dev->of_node) + if (dev->of_node) { + of_id = of_match_node(s5pcsis_of_match, dev->of_node); + if (WARN_ON(of_id == NULL)) + return -EINVAL; + + drv_data = of_id->data; + state->interrupt_mask = drv_data->interrupt_mask; + ret = s5pcsis_parse_dt(pdev, state); - else + } else { ret = s5pcsis_get_platform_data(pdev, state); + } + if (ret < 0) return ret; @@ -994,9 +1023,25 @@ static const struct dev_pm_ops s5pcsis_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(s5pcsis_suspend, s5pcsis_resume) }; +static const struct csis_drvdata exynos4_csis_drvdata = { + .interrupt_mask = S5PCSIS_INTMSK_EXYNOS4_EN_ALL, +}; + +static const struct csis_drvdata exynos5_csis_drvdata = { + .interrupt_mask = S5PCSIS_INTMSK_EXYNOS5_EN_ALL, +}; + static const struct of_device_id s5pcsis_of_match[] = { - { .compatible = "samsung,s5pv210-csis" }, - { .compatible = "samsung,exynos4210-csis" }, + { + .compatible = "samsung,s5pv210-csis", + .data = &exynos4_csis_drvdata, + }, { + .compatible = "samsung,exynos4210-csis", + .data = &exynos4_csis_drvdata, + }, { + .compatible = "samsung,exynos5250-csis", + .data = &exynos5_csis_drvdata, + }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, s5pcsis_of_match); diff --git a/drivers/media/platform/fsl-viu.c b/drivers/media/platform/fsl-viu.c index 3a6a0dcdc3e4..221ec428a01e 100644 --- a/drivers/media/platform/fsl-viu.c +++ b/drivers/media/platform/fsl-viu.c @@ -1475,7 +1475,6 @@ static struct video_device viu_template = { .release = video_device_release, .tvnorms = V4L2_STD_NTSC_M | V4L2_STD_PAL, - .current_norm = V4L2_STD_NTSC_M, }; static int viu_of_probe(struct platform_device *op) @@ -1546,6 +1545,7 @@ static int viu_of_probe(struct platform_device *op) viu_dev->vidq.timeout.function = viu_vid_timeout; viu_dev->vidq.timeout.data = (unsigned long)viu_dev; init_timer(&viu_dev->vidq.timeout); + viu_dev->std = V4L2_STD_NTSC_M; viu_dev->first = 1; /* Allocate memory for video device */ diff --git a/drivers/media/platform/indycam.c b/drivers/media/platform/indycam.c index 548236333cce..f1d192bbcb4c 100644 --- a/drivers/media/platform/indycam.c +++ b/drivers/media/platform/indycam.c @@ -23,7 +23,6 @@ #include <linux/videodev2.h> #include <linux/i2c.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> #include "indycam.h" @@ -283,20 +282,9 @@ static int indycam_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) /* I2C-interface */ -static int indycam_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - struct indycam *camera = to_indycam(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_INDYCAM, - camera->version); -} - /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops indycam_core_ops = { - .g_chip_ident = indycam_g_chip_ident, .g_ctrl = indycam_g_ctrl, .s_ctrl = indycam_s_ctrl, }; diff --git a/drivers/media/platform/m2m-deinterlace.c b/drivers/media/platform/m2m-deinterlace.c index 758564649589..540516ca872c 100644 --- a/drivers/media/platform/m2m-deinterlace.c +++ b/drivers/media/platform/m2m-deinterlace.c @@ -1033,6 +1033,7 @@ static int deinterlace_probe(struct platform_device *pdev) *vfd = deinterlace_videodev; vfd->lock = &pcdev->dev_mutex; + vfd->v4l2_dev = &pcdev->v4l2_dev; ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); if (ret) { diff --git a/drivers/media/platform/marvell-ccic/cafe-driver.c b/drivers/media/platform/marvell-ccic/cafe-driver.c index d030f9beae88..1f079ff33d4b 100644 --- a/drivers/media/platform/marvell-ccic/cafe-driver.c +++ b/drivers/media/platform/marvell-ccic/cafe-driver.c @@ -27,7 +27,6 @@ #include <linux/slab.h> #include <linux/videodev2.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> #include <linux/device.h> #include <linux/wait.h> #include <linux/delay.h> @@ -469,7 +468,7 @@ static int cafe_pci_probe(struct pci_dev *pdev, goto out; cam->pdev = pdev; mcam = &cam->mcam; - mcam->chip_id = V4L2_IDENT_CAFE; + mcam->chip_id = MCAM_CAFE; spin_lock_init(&mcam->dev_lock); init_waitqueue_head(&cam->smbus_wait); mcam->plat_power_up = cafe_ctlr_power_up; @@ -501,6 +500,7 @@ static int cafe_pci_probe(struct pci_dev *pdev, printk(KERN_ERR "Unable to ioremap cafe-ccic regs\n"); goto out_disable; } + mcam->regs_size = pci_resource_len(pdev, 0); ret = request_irq(pdev->irq, cafe_irq, IRQF_SHARED, "cafe-ccic", cam); if (ret) goto out_iounmap; diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c index 64ab91edfb81..0821ed08c122 100644 --- a/drivers/media/platform/marvell-ccic/mcam-core.c +++ b/drivers/media/platform/marvell-ccic/mcam-core.c @@ -23,7 +23,6 @@ #include <media/v4l2-device.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-ctrls.h> -#include <media/v4l2-chip-ident.h> #include <media/ov7670.h> #include <media/videobuf2-vmalloc.h> #include <media/videobuf2-dma-contig.h> @@ -336,7 +335,7 @@ static void mcam_ctlr_dma_vmalloc(struct mcam_camera *cam) mcam_reg_clear_bit(cam, REG_CTRL1, C1_TWOBUFS); } else mcam_reg_set_bit(cam, REG_CTRL1, C1_TWOBUFS); - if (cam->chip_id == V4L2_IDENT_CAFE) + if (cam->chip_id == MCAM_CAFE) mcam_reg_write(cam, REG_UBAR, 0); /* 32 bits only */ } @@ -796,7 +795,6 @@ static int __mcam_cam_reset(struct mcam_camera *cam) */ static int mcam_cam_init(struct mcam_camera *cam) { - struct v4l2_dbg_chip_ident chip; int ret; mutex_lock(&cam->s_mutex); @@ -804,24 +802,8 @@ static int mcam_cam_init(struct mcam_camera *cam) cam_warn(cam, "Cam init with device in funky state %d", cam->state); ret = __mcam_cam_reset(cam); - if (ret) - goto out; - chip.ident = V4L2_IDENT_NONE; - chip.match.type = V4L2_CHIP_MATCH_I2C_ADDR; - chip.match.addr = cam->sensor_addr; - ret = sensor_call(cam, core, g_chip_ident, &chip); - if (ret) - goto out; - cam->sensor_type = chip.ident; - if (cam->sensor_type != V4L2_IDENT_OV7670) { - cam_err(cam, "Unsupported sensor type 0x%x", cam->sensor_type); - ret = -EINVAL; - goto out; - } -/* Get/set parameters? */ - ret = 0; + /* Get/set parameters? */ cam->state = S_IDLE; -out: mcam_ctlr_power_down(cam); mutex_unlock(&cam->s_mutex); return ret; @@ -1362,6 +1344,12 @@ static int mcam_vidioc_s_std(struct file *filp, void *priv, v4l2_std_id a) return 0; } +static int mcam_vidioc_g_std(struct file *filp, void *priv, v4l2_std_id *a) +{ + *a = V4L2_STD_NTSC_M; + return 0; +} + /* * G/S_PARM. Most of this is done by the sensor, but we are * the level which controls the number of read buffers. @@ -1392,20 +1380,6 @@ static int mcam_vidioc_s_parm(struct file *filp, void *priv, return ret; } -static int mcam_vidioc_g_chip_ident(struct file *file, void *priv, - struct v4l2_dbg_chip_ident *chip) -{ - struct mcam_camera *cam = priv; - - chip->ident = V4L2_IDENT_NONE; - chip->revision = 0; - if (v4l2_chip_match_host(&chip->match)) { - chip->ident = cam->chip_id; - return 0; - } - return sensor_call(cam, core, g_chip_ident, chip); -} - static int mcam_vidioc_enum_framesizes(struct file *filp, void *priv, struct v4l2_frmsizeenum *sizes) { @@ -1436,12 +1410,11 @@ static int mcam_vidioc_g_register(struct file *file, void *priv, { struct mcam_camera *cam = priv; - if (v4l2_chip_match_host(®->match)) { - reg->val = mcam_reg_read(cam, reg->reg); - reg->size = 4; - return 0; - } - return sensor_call(cam, core, g_register, reg); + if (reg->reg > cam->regs_size - 4) + return -EINVAL; + reg->val = mcam_reg_read(cam, reg->reg); + reg->size = 4; + return 0; } static int mcam_vidioc_s_register(struct file *file, void *priv, @@ -1449,11 +1422,10 @@ static int mcam_vidioc_s_register(struct file *file, void *priv, { struct mcam_camera *cam = priv; - if (v4l2_chip_match_host(®->match)) { - mcam_reg_write(cam, reg->reg, reg->val); - return 0; - } - return sensor_call(cam, core, s_register, reg); + if (reg->reg > cam->regs_size - 4) + return -EINVAL; + mcam_reg_write(cam, reg->reg, reg->val); + return 0; } #endif @@ -1467,6 +1439,7 @@ static const struct v4l2_ioctl_ops mcam_v4l_ioctl_ops = { .vidioc_g_input = mcam_vidioc_g_input, .vidioc_s_input = mcam_vidioc_s_input, .vidioc_s_std = mcam_vidioc_s_std, + .vidioc_g_std = mcam_vidioc_g_std, .vidioc_reqbufs = mcam_vidioc_reqbufs, .vidioc_querybuf = mcam_vidioc_querybuf, .vidioc_qbuf = mcam_vidioc_qbuf, @@ -1477,7 +1450,6 @@ static const struct v4l2_ioctl_ops mcam_v4l_ioctl_ops = { .vidioc_s_parm = mcam_vidioc_s_parm, .vidioc_enum_framesizes = mcam_vidioc_enum_framesizes, .vidioc_enum_frameintervals = mcam_vidioc_enum_frameintervals, - .vidioc_g_chip_ident = mcam_vidioc_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = mcam_vidioc_g_register, .vidioc_s_register = mcam_vidioc_s_register, @@ -1593,7 +1565,6 @@ static const struct v4l2_file_operations mcam_v4l_fops = { static struct video_device mcam_v4l_template = { .name = "mcam", .tvnorms = V4L2_STD_NTSC_M, - .current_norm = V4L2_STD_NTSC_M, /* make mplayer happy */ .fops = &mcam_v4l_fops, .ioctl_ops = &mcam_v4l_ioctl_ops, @@ -1695,7 +1666,7 @@ int mccic_register(struct mcam_camera *cam) if (buffer_mode >= 0) cam->buffer_mode = buffer_mode; if (cam->buffer_mode == B_DMA_sg && - cam->chip_id == V4L2_IDENT_CAFE) { + cam->chip_id == MCAM_CAFE) { printk(KERN_ERR "marvell-cam: Cafe can't do S/G I/O, " "attempting vmalloc mode instead\n"); cam->buffer_mode = B_vmalloc; diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h index 01dec9e5fc2b..520c8ded9443 100644 --- a/drivers/media/platform/marvell-ccic/mcam-core.h +++ b/drivers/media/platform/marvell-ccic/mcam-core.h @@ -53,6 +53,11 @@ enum mcam_buffer_mode { B_DMA_sg = 2 }; +enum mcam_chip_id { + MCAM_CAFE, + MCAM_ARMADA610, +}; + /* * Is a given buffer mode supported by the current kernel configuration? */ @@ -96,9 +101,10 @@ struct mcam_camera { */ struct i2c_adapter *i2c_adapter; unsigned char __iomem *regs; + unsigned regs_size; /* size in bytes of the register space */ spinlock_t dev_lock; struct device *dev; /* For messages, dma alloc */ - unsigned int chip_id; + enum mcam_chip_id chip_id; short int clock_speed; /* Sensor clock speed, default 30 */ short int use_smbus; /* SMBUS or straight I2c? */ enum mcam_buffer_mode buffer_mode; @@ -152,7 +158,6 @@ struct mcam_camera { void (*frame_complete)(struct mcam_camera *cam, int frame); /* Current operating parameters */ - u32 sensor_type; /* Currently ov7670 only */ struct v4l2_pix_format pix_format; enum v4l2_mbus_pixelcode mbus_code; diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c b/drivers/media/platform/marvell-ccic/mmp-driver.c index c4c17fe76c0d..a634888271cd 100644 --- a/drivers/media/platform/marvell-ccic/mmp-driver.c +++ b/drivers/media/platform/marvell-ccic/mmp-driver.c @@ -18,7 +18,6 @@ #include <linux/slab.h> #include <linux/videodev2.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> #include <media/mmp-camera.h> #include <linux/device.h> #include <linux/platform_device.h> @@ -185,7 +184,7 @@ static int mmpcam_probe(struct platform_device *pdev) mcam->plat_power_down = mmpcam_power_down; mcam->dev = &pdev->dev; mcam->use_smbus = 0; - mcam->chip_id = V4L2_IDENT_ARMADA610; + mcam->chip_id = MCAM_ARMADA610; mcam->buffer_mode = B_DMA_sg; spin_lock_init(&mcam->dev_lock); /* @@ -203,6 +202,7 @@ static int mmpcam_probe(struct platform_device *pdev) ret = -ENODEV; goto out_free; } + mcam->regs_size = resource_size(res); /* * Power/clock memory is elsewhere; get it too. Perhaps this * should really be managed outside of this driver? diff --git a/drivers/media/platform/mem2mem_testdev.c b/drivers/media/platform/mem2mem_testdev.c index 4cc7f65d7d76..6a17676f9d72 100644 --- a/drivers/media/platform/mem2mem_testdev.c +++ b/drivers/media/platform/mem2mem_testdev.c @@ -1051,6 +1051,7 @@ static int m2mtest_probe(struct platform_device *pdev) *vfd = m2mtest_videodev; vfd->lock = &dev->dev_mutex; + vfd->v4l2_dev = &dev->v4l2_dev; ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); if (ret) { @@ -1061,7 +1062,7 @@ static int m2mtest_probe(struct platform_device *pdev) video_set_drvdata(vfd, dev); snprintf(vfd->name, sizeof(vfd->name), "%s", m2mtest_videodev.name); dev->vfd = vfd; - v4l2_info(&dev->v4l2_dev, MEM2MEM_TEST_MODULE_NAME + v4l2_info(&dev->v4l2_dev, "Device registered as /dev/video%d\n", vfd->num); setup_timer(&dev->timer, device_isr, (long)dev); diff --git a/drivers/media/platform/mx2_emmaprp.c b/drivers/media/platform/mx2_emmaprp.c index f7440e585b6b..c690435853bd 100644 --- a/drivers/media/platform/mx2_emmaprp.c +++ b/drivers/media/platform/mx2_emmaprp.c @@ -937,6 +937,7 @@ static int emmaprp_probe(struct platform_device *pdev) *vfd = emmaprp_videodev; vfd->lock = &pcdev->dev_mutex; + vfd->v4l2_dev = &pcdev->v4l2_dev; video_set_drvdata(vfd, pcdev); snprintf(vfd->name, sizeof(vfd->name), "%s", emmaprp_videodev.name); diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c index d338b19da544..dfd0a21a0658 100644 --- a/drivers/media/platform/omap/omap_vout.c +++ b/drivers/media/platform/omap/omap_vout.c @@ -335,8 +335,6 @@ static int video_mode_to_dss_mode(struct omap_vout_device *vout) ovl = ovid->overlays[0]; switch (pix->pixelformat) { - case 0: - break; case V4L2_PIX_FMT_YUYV: mode = OMAP_DSS_COLOR_YUV2; break; @@ -358,6 +356,7 @@ static int video_mode_to_dss_mode(struct omap_vout_device *vout) break; default: mode = -EINVAL; + break; } return mode; } diff --git a/drivers/media/platform/omap24xxcam.c b/drivers/media/platform/omap24xxcam.c index debb44ceb185..d2b440c842b3 100644 --- a/drivers/media/platform/omap24xxcam.c +++ b/drivers/media/platform/omap24xxcam.c @@ -1656,7 +1656,7 @@ static int omap24xxcam_device_register(struct v4l2_int_device *s) } vfd->release = video_device_release; - vfd->parent = cam->dev; + vfd->v4l2_dev = &cam->v4l2_dev; strlcpy(vfd->name, CAM_NAME, sizeof(vfd->name)); vfd->fops = &omap24xxcam_fops; @@ -1752,6 +1752,11 @@ static int omap24xxcam_probe(struct platform_device *pdev) cam->dev = &pdev->dev; + if (v4l2_device_register(&pdev->dev, &cam->v4l2_dev)) { + dev_err(&pdev->dev, "v4l2_device_register failed\n"); + goto err; + } + /* * Impose a lower limit on the amount of memory allocated for * capture. We require at least enough memory to double-buffer @@ -1849,6 +1854,8 @@ static int omap24xxcam_remove(struct platform_device *pdev) cam->mmio_base_phys = 0; } + v4l2_device_unregister(&cam->v4l2_dev); + kfree(cam); return 0; diff --git a/drivers/media/platform/omap24xxcam.h b/drivers/media/platform/omap24xxcam.h index c4395956a493..7f6f79155537 100644 --- a/drivers/media/platform/omap24xxcam.h +++ b/drivers/media/platform/omap24xxcam.h @@ -29,6 +29,7 @@ #include <media/videobuf-dma-sg.h> #include <media/v4l2-int-device.h> +#include <media/v4l2-device.h> /* * @@ -462,6 +463,8 @@ struct omap24xxcam_device { */ struct mutex mutex; + struct v4l2_device v4l2_dev; + /*** general driver state information ***/ atomic_t users; /* diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 1d7dbd5c0fba..df3a0ec7fd2c 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -792,9 +792,9 @@ int omap3isp_pipeline_pm_use(struct media_entity *entity, int use) /* * isp_pipeline_link_notify - Link management notification callback - * @source: Pad at the start of the link - * @sink: Pad at the end of the link + * @link: The link * @flags: New link flags that will be applied + * @notification: The link's state change notification type (MEDIA_DEV_NOTIFY_*) * * React to link management on powered pipelines by updating the use count of * all entities in the source and sink sides of the link. Entities are powered @@ -804,29 +804,38 @@ int omap3isp_pipeline_pm_use(struct media_entity *entity, int use) * off is assumed to never fail. This function will not fail for disconnection * events. */ -static int isp_pipeline_link_notify(struct media_pad *source, - struct media_pad *sink, u32 flags) +static int isp_pipeline_link_notify(struct media_link *link, u32 flags, + unsigned int notification) { - int source_use = isp_pipeline_pm_use_count(source->entity); - int sink_use = isp_pipeline_pm_use_count(sink->entity); + struct media_entity *source = link->source->entity; + struct media_entity *sink = link->sink->entity; + int source_use = isp_pipeline_pm_use_count(source); + int sink_use = isp_pipeline_pm_use_count(sink); int ret; - if (!(flags & MEDIA_LNK_FL_ENABLED)) { + if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH && + !(link->flags & MEDIA_LNK_FL_ENABLED)) { /* Powering off entities is assumed to never fail. */ - isp_pipeline_pm_power(source->entity, -sink_use); - isp_pipeline_pm_power(sink->entity, -source_use); + isp_pipeline_pm_power(source, -sink_use); + isp_pipeline_pm_power(sink, -source_use); return 0; } - ret = isp_pipeline_pm_power(source->entity, sink_use); - if (ret < 0) - return ret; + if (notification == MEDIA_DEV_NOTIFY_POST_LINK_CH && + (flags & MEDIA_LNK_FL_ENABLED)) { - ret = isp_pipeline_pm_power(sink->entity, source_use); - if (ret < 0) - isp_pipeline_pm_power(source->entity, -sink_use); + ret = isp_pipeline_pm_power(source, sink_use); + if (ret < 0) + return ret; - return ret; + ret = isp_pipeline_pm_power(sink, source_use); + if (ret < 0) + isp_pipeline_pm_power(source, -sink_use); + + return ret; + } + + return 0; } /* ----------------------------------------------------------------------------- @@ -877,7 +886,7 @@ static int isp_pipeline_enable(struct isp_pipeline *pipe, if (!(pad->flags & MEDIA_PAD_FL_SINK)) break; - pad = media_entity_remote_source(pad); + pad = media_entity_remote_pad(pad); if (pad == NULL || media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) break; @@ -967,7 +976,7 @@ static int isp_pipeline_disable(struct isp_pipeline *pipe) if (!(pad->flags & MEDIA_PAD_FL_SINK)) break; - pad = media_entity_remote_source(pad); + pad = media_entity_remote_pad(pad); if (pad == NULL || media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) break; @@ -1083,7 +1092,7 @@ static int isp_pipeline_is_last(struct media_entity *me) pipe = to_isp_pipeline(me); if (pipe->stream_state == ISP_PIPELINE_STREAM_STOPPED) return 0; - pad = media_entity_remote_source(&pipe->output->pad); + pad = media_entity_remote_pad(&pipe->output->pad); return pad->entity == me; } @@ -2249,6 +2258,7 @@ static int isp_probe(struct platform_device *pdev) ret = iommu_attach_device(isp->domain, &pdev->dev); if (ret) { dev_err(&pdev->dev, "can't attach iommu device: %d\n", ret); + ret = -EPROBE_DEFER; goto free_domain; } @@ -2287,12 +2297,11 @@ detach_dev: iommu_detach_device(isp->domain, &pdev->dev); free_domain: iommu_domain_free(isp->domain); + isp->domain = NULL; error_isp: isp_xclk_cleanup(isp); omap3isp_put(isp); error: - platform_set_drvdata(pdev, NULL); - mutex_destroy(&isp->isp_mutex); return ret; diff --git a/drivers/media/platform/omap3isp/ispccdc.c b/drivers/media/platform/omap3isp/ispccdc.c index 60e60aa64fb4..907a205da5a5 100644 --- a/drivers/media/platform/omap3isp/ispccdc.c +++ b/drivers/media/platform/omap3isp/ispccdc.c @@ -1120,7 +1120,7 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc) u32 syn_mode; u32 ccdc_pattern; - pad = media_entity_remote_source(&ccdc->pads[CCDC_PAD_SINK]); + pad = media_entity_remote_pad(&ccdc->pads[CCDC_PAD_SINK]); sensor = media_entity_to_v4l2_subdev(pad->entity); if (ccdc->input == CCDC_INPUT_PARALLEL) pdata = &((struct isp_v4l2_subdevs_group *)sensor->host_priv) diff --git a/drivers/media/platform/omap3isp/ispccp2.c b/drivers/media/platform/omap3isp/ispccp2.c index c5d84c977e29..e71651429dda 100644 --- a/drivers/media/platform/omap3isp/ispccp2.c +++ b/drivers/media/platform/omap3isp/ispccp2.c @@ -158,13 +158,17 @@ static void ccp2_pwr_cfg(struct isp_ccp2_device *ccp2) * @ccp2: pointer to ISP CCP2 device * @enable: enable/disable flag */ -static void ccp2_if_enable(struct isp_ccp2_device *ccp2, u8 enable) +static int ccp2_if_enable(struct isp_ccp2_device *ccp2, u8 enable) { struct isp_device *isp = to_isp_device(ccp2); + int ret; int i; - if (enable && ccp2->vdds_csib) - regulator_enable(ccp2->vdds_csib); + if (enable && ccp2->vdds_csib) { + ret = regulator_enable(ccp2->vdds_csib); + if (ret < 0) + return ret; + } /* Enable/Disable all the LCx channels */ for (i = 0; i < CCP2_LCx_CHANS_NUM; i++) @@ -179,6 +183,8 @@ static void ccp2_if_enable(struct isp_ccp2_device *ccp2, u8 enable) if (!enable && ccp2->vdds_csib) regulator_disable(ccp2->vdds_csib); + + return 0; } /* @@ -360,7 +366,7 @@ static int ccp2_if_configure(struct isp_ccp2_device *ccp2) ccp2_pwr_cfg(ccp2); - pad = media_entity_remote_source(&ccp2->pads[CCP2_PAD_SINK]); + pad = media_entity_remote_pad(&ccp2->pads[CCP2_PAD_SINK]); sensor = media_entity_to_v4l2_subdev(pad->entity); pdata = sensor->host_priv; @@ -851,7 +857,12 @@ static int ccp2_s_stream(struct v4l2_subdev *sd, int enable) ccp2_print_status(ccp2); /* Enable CSI1/CCP2 interface */ - ccp2_if_enable(ccp2, 1); + ret = ccp2_if_enable(ccp2, 1); + if (ret < 0) { + if (ccp2->phy) + omap3isp_csiphy_release(ccp2->phy); + return ret; + } break; case ISP_PIPELINE_STREAM_SINGLESHOT: diff --git a/drivers/media/platform/omap3isp/ispcsi2.c b/drivers/media/platform/omap3isp/ispcsi2.c index 783f4b05b153..6db245d84bbb 100644 --- a/drivers/media/platform/omap3isp/ispcsi2.c +++ b/drivers/media/platform/omap3isp/ispcsi2.c @@ -573,7 +573,7 @@ static int csi2_configure(struct isp_csi2_device *csi2) if (csi2->contexts[0].enabled || csi2->ctrl.if_enable) return -EBUSY; - pad = media_entity_remote_source(&csi2->pads[CSI2_PAD_SINK]); + pad = media_entity_remote_pad(&csi2->pads[CSI2_PAD_SINK]); sensor = media_entity_to_v4l2_subdev(pad->entity); pdata = sensor->host_priv; diff --git a/drivers/media/platform/omap3isp/ispqueue.h b/drivers/media/platform/omap3isp/ispqueue.h index 908dfd712e8e..3e048ad65647 100644 --- a/drivers/media/platform/omap3isp/ispqueue.h +++ b/drivers/media/platform/omap3isp/ispqueue.h @@ -28,6 +28,7 @@ #include <linux/kernel.h> #include <linux/list.h> +#include <linux/mm_types.h> #include <linux/mutex.h> #include <linux/videodev2.h> #include <linux/wait.h> diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c index 8dac17511e61..a908d006f527 100644 --- a/drivers/media/platform/omap3isp/ispvideo.c +++ b/drivers/media/platform/omap3isp/ispvideo.c @@ -219,7 +219,7 @@ isp_video_remote_subdev(struct isp_video *video, u32 *pad) { struct media_pad *remote; - remote = media_entity_remote_source(&video->pad); + remote = media_entity_remote_pad(&video->pad); if (remote == NULL || media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV) @@ -314,7 +314,7 @@ static int isp_video_validate_pipeline(struct isp_pipeline *pipe) * entity can be found, and stop checking the pipeline if the * source entity isn't a subdev. */ - pad = media_entity_remote_source(pad); + pad = media_entity_remote_pad(pad); if (pad == NULL) return -EPIPE; @@ -901,7 +901,7 @@ static int isp_video_check_external_subdevs(struct isp_video *video, continue; /* ISP entities have always sink pad == 0. Find source. */ - source_pad = media_entity_remote_source(&ents[i]->pads[0]); + source_pad = media_entity_remote_pad(&ents[i]->pads[0]); if (source_pad == NULL) continue; diff --git a/drivers/media/platform/s3c-camif/camif-capture.c b/drivers/media/platform/s3c-camif/camif-capture.c index 70438a0f62ae..40b298ab87f1 100644 --- a/drivers/media/platform/s3c-camif/camif-capture.c +++ b/drivers/media/platform/s3c-camif/camif-capture.c @@ -845,7 +845,7 @@ static int camif_pipeline_validate(struct camif_dev *camif) int ret; /* Retrieve format at the sensor subdev source pad */ - pad = media_entity_remote_source(&camif->pads[0]); + pad = media_entity_remote_pad(&camif->pads[0]); if (!pad || media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV) return -EPIPE; diff --git a/drivers/media/platform/s3c-camif/camif-core.c b/drivers/media/platform/s3c-camif/camif-core.c index 0d0fab1a7b5e..b38574702fe9 100644 --- a/drivers/media/platform/s3c-camif/camif-core.c +++ b/drivers/media/platform/s3c-camif/camif-core.c @@ -341,10 +341,11 @@ static void camif_clk_put(struct camif_dev *camif) int i; for (i = 0; i < CLK_MAX_NUM; i++) { - if (IS_ERR_OR_NULL(camif->clock[i])) + if (IS_ERR(camif->clock[i])) continue; clk_unprepare(camif->clock[i]); clk_put(camif->clock[i]); + camif->clock[i] = ERR_PTR(-EINVAL); } } @@ -352,6 +353,9 @@ static int camif_clk_get(struct camif_dev *camif) { int ret, i; + for (i = 1; i < CLK_MAX_NUM; i++) + camif->clock[i] = ERR_PTR(-EINVAL); + for (i = 0; i < CLK_MAX_NUM; i++) { camif->clock[i] = clk_get(camif->dev, camif_clocks[i]); if (IS_ERR(camif->clock[i])) { diff --git a/drivers/media/platform/s3c-camif/camif-regs.c b/drivers/media/platform/s3c-camif/camif-regs.c index 1a3b4fc05ec6..a9e3b16460b8 100644 --- a/drivers/media/platform/s3c-camif/camif-regs.c +++ b/drivers/media/platform/s3c-camif/camif-regs.c @@ -379,7 +379,7 @@ static void camif_hw_set_prescaler(struct camif_vp *vp) camif_write(camif, S3C_CAMIF_REG_CISCPREDST(vp->id, vp->offset), cfg); } -void camif_s3c244x_hw_set_scaler(struct camif_vp *vp) +static void camif_s3c244x_hw_set_scaler(struct camif_vp *vp) { struct camif_dev *camif = vp->camif; struct camif_scaler *scaler = &vp->scaler; @@ -426,7 +426,7 @@ void camif_s3c244x_hw_set_scaler(struct camif_vp *vp) scaler->main_h_ratio, scaler->main_v_ratio); } -void camif_s3c64xx_hw_set_scaler(struct camif_vp *vp) +static void camif_s3c64xx_hw_set_scaler(struct camif_vp *vp) { struct camif_dev *camif = vp->camif; struct camif_scaler *scaler = &vp->scaler; @@ -601,6 +601,6 @@ void camif_hw_dump_regs(struct camif_dev *camif, const char *label) pr_info("--- %s ---\n", label); for (i = 0; i < ARRAY_SIZE(registers); i++) { u32 cfg = readl(camif->io_base + registers[i].offset); - printk(KERN_INFO "%s:\t0x%08x\n", registers[i].name, cfg); + dev_info(camif->dev, "%s:\t0x%08x\n", registers[i].name, cfg); } } diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index d12faa691af8..a130dcdb7206 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -1424,7 +1424,7 @@ static void *mfc_get_drv_data(struct platform_device *pdev) if (pdev->dev.of_node) { const struct of_device_id *match; - match = of_match_node(of_match_ptr(exynos_mfc_match), + match = of_match_node(exynos_mfc_match, pdev->dev.of_node); if (match) driver_data = (struct s5p_mfc_variant *)match->data; diff --git a/drivers/media/platform/s5p-tv/hdmi_drv.c b/drivers/media/platform/s5p-tv/hdmi_drv.c index 4e86626dad4b..1b34c3629858 100644 --- a/drivers/media/platform/s5p-tv/hdmi_drv.c +++ b/drivers/media/platform/s5p-tv/hdmi_drv.c @@ -576,16 +576,22 @@ static int hdmi_s_stream(struct v4l2_subdev *sd, int enable) return hdmi_streamoff(hdev); } -static void hdmi_resource_poweron(struct hdmi_resources *res) +static int hdmi_resource_poweron(struct hdmi_resources *res) { + int ret; + /* turn HDMI power on */ - regulator_bulk_enable(res->regul_count, res->regul_bulk); + ret = regulator_bulk_enable(res->regul_count, res->regul_bulk); + if (ret < 0) + return ret; /* power-on hdmi physical interface */ clk_enable(res->hdmiphy); /* use VPP as parent clock; HDMIPHY is not working yet */ clk_set_parent(res->sclk_hdmi, res->sclk_pixel); /* turn clocks on */ clk_enable(res->sclk_hdmi); + + return 0; } static void hdmi_resource_poweroff(struct hdmi_resources *res) @@ -728,11 +734,13 @@ static int hdmi_runtime_resume(struct device *dev) { struct v4l2_subdev *sd = dev_get_drvdata(dev); struct hdmi_device *hdev = sd_to_hdmi_dev(sd); - int ret = 0; + int ret; dev_dbg(dev, "%s\n", __func__); - hdmi_resource_poweron(&hdev->res); + ret = hdmi_resource_poweron(&hdev->res); + if (ret < 0) + return ret; /* starting MHL */ ret = v4l2_subdev_call(hdev->mhl_sd, core, s_power, 1); @@ -755,6 +763,15 @@ static const struct dev_pm_ops hdmi_pm_ops = { .runtime_resume = hdmi_runtime_resume, }; +static void hdmi_resource_clear_clocks(struct hdmi_resources *res) +{ + res->hdmi = ERR_PTR(-EINVAL); + res->sclk_hdmi = ERR_PTR(-EINVAL); + res->sclk_pixel = ERR_PTR(-EINVAL); + res->sclk_hdmiphy = ERR_PTR(-EINVAL); + res->hdmiphy = ERR_PTR(-EINVAL); +} + static void hdmi_resources_cleanup(struct hdmi_device *hdev) { struct hdmi_resources *res = &hdev->res; @@ -765,17 +782,18 @@ static void hdmi_resources_cleanup(struct hdmi_device *hdev) regulator_bulk_free(res->regul_count, res->regul_bulk); /* kfree is NULL-safe */ kfree(res->regul_bulk); - if (!IS_ERR_OR_NULL(res->hdmiphy)) + if (!IS_ERR(res->hdmiphy)) clk_put(res->hdmiphy); - if (!IS_ERR_OR_NULL(res->sclk_hdmiphy)) + if (!IS_ERR(res->sclk_hdmiphy)) clk_put(res->sclk_hdmiphy); - if (!IS_ERR_OR_NULL(res->sclk_pixel)) + if (!IS_ERR(res->sclk_pixel)) clk_put(res->sclk_pixel); - if (!IS_ERR_OR_NULL(res->sclk_hdmi)) + if (!IS_ERR(res->sclk_hdmi)) clk_put(res->sclk_hdmi); - if (!IS_ERR_OR_NULL(res->hdmi)) + if (!IS_ERR(res->hdmi)) clk_put(res->hdmi); memset(res, 0, sizeof(*res)); + hdmi_resource_clear_clocks(res); } static int hdmi_resources_init(struct hdmi_device *hdev) @@ -793,8 +811,9 @@ static int hdmi_resources_init(struct hdmi_device *hdev) dev_dbg(dev, "HDMI resource init\n"); memset(res, 0, sizeof(*res)); - /* get clocks, power */ + hdmi_resource_clear_clocks(res); + /* get clocks, power */ res->hdmi = clk_get(dev, "hdmi"); if (IS_ERR(res->hdmi)) { dev_err(dev, "failed to get clock 'hdmi'\n"); diff --git a/drivers/media/platform/s5p-tv/mixer_drv.c b/drivers/media/platform/s5p-tv/mixer_drv.c index 5733033a6ead..51805a5e2beb 100644 --- a/drivers/media/platform/s5p-tv/mixer_drv.c +++ b/drivers/media/platform/s5p-tv/mixer_drv.c @@ -211,6 +211,15 @@ fail: return ret; } +static void mxr_resource_clear_clocks(struct mxr_resources *res) +{ + res->mixer = ERR_PTR(-EINVAL); + res->vp = ERR_PTR(-EINVAL); + res->sclk_mixer = ERR_PTR(-EINVAL); + res->sclk_hdmi = ERR_PTR(-EINVAL); + res->sclk_dac = ERR_PTR(-EINVAL); +} + static void mxr_release_plat_resources(struct mxr_device *mdev) { free_irq(mdev->res.irq, mdev); @@ -222,15 +231,15 @@ static void mxr_release_clocks(struct mxr_device *mdev) { struct mxr_resources *res = &mdev->res; - if (!IS_ERR_OR_NULL(res->sclk_dac)) + if (!IS_ERR(res->sclk_dac)) clk_put(res->sclk_dac); - if (!IS_ERR_OR_NULL(res->sclk_hdmi)) + if (!IS_ERR(res->sclk_hdmi)) clk_put(res->sclk_hdmi); - if (!IS_ERR_OR_NULL(res->sclk_mixer)) + if (!IS_ERR(res->sclk_mixer)) clk_put(res->sclk_mixer); - if (!IS_ERR_OR_NULL(res->vp)) + if (!IS_ERR(res->vp)) clk_put(res->vp); - if (!IS_ERR_OR_NULL(res->mixer)) + if (!IS_ERR(res->mixer)) clk_put(res->mixer); } @@ -239,6 +248,8 @@ static int mxr_acquire_clocks(struct mxr_device *mdev) struct mxr_resources *res = &mdev->res; struct device *dev = mdev->dev; + mxr_resource_clear_clocks(res); + res->mixer = clk_get(dev, "mixer"); if (IS_ERR(res->mixer)) { mxr_err(mdev, "failed to get clock 'mixer'\n"); @@ -299,6 +310,7 @@ static void mxr_release_resources(struct mxr_device *mdev) mxr_release_clocks(mdev); mxr_release_plat_resources(mdev); memset(&mdev->res, 0, sizeof(mdev->res)); + mxr_resource_clear_clocks(&mdev->res); } static void mxr_release_layers(struct mxr_device *mdev) diff --git a/drivers/media/platform/s5p-tv/mixer_video.c b/drivers/media/platform/s5p-tv/mixer_video.c index ef0efdf422fe..641b1f071e06 100644 --- a/drivers/media/platform/s5p-tv/mixer_video.c +++ b/drivers/media/platform/s5p-tv/mixer_video.c @@ -81,8 +81,9 @@ int mxr_acquire_video(struct mxr_device *mdev, } mdev->alloc_ctx = vb2_dma_contig_init_ctx(mdev->dev); - if (IS_ERR_OR_NULL(mdev->alloc_ctx)) { + if (IS_ERR(mdev->alloc_ctx)) { mxr_err(mdev, "could not acquire vb2 allocator\n"); + ret = PTR_ERR(mdev->alloc_ctx); goto fail_v4l2_dev; } diff --git a/drivers/media/platform/s5p-tv/sdo_drv.c b/drivers/media/platform/s5p-tv/sdo_drv.c index ab6f9ef89423..0afa90f0f6ab 100644 --- a/drivers/media/platform/s5p-tv/sdo_drv.c +++ b/drivers/media/platform/s5p-tv/sdo_drv.c @@ -262,11 +262,21 @@ static int sdo_runtime_resume(struct device *dev) { struct v4l2_subdev *sd = dev_get_drvdata(dev); struct sdo_device *sdev = sd_to_sdev(sd); + int ret; dev_info(dev, "resume\n"); - clk_enable(sdev->sclk_dac); - regulator_enable(sdev->vdac); - regulator_enable(sdev->vdet); + + ret = clk_enable(sdev->sclk_dac); + if (ret < 0) + return ret; + + ret = regulator_enable(sdev->vdac); + if (ret < 0) + goto dac_clk_dis; + + ret = regulator_enable(sdev->vdet); + if (ret < 0) + goto vdac_r_dis; /* software reset */ sdo_write_mask(sdev, SDO_CLKCON, ~0, SDO_TVOUT_SW_RESET); @@ -285,6 +295,12 @@ static int sdo_runtime_resume(struct device *dev) SDO_COMPENSATION_CVBS_COMP_OFF); sdo_reg_debug(sdev); return 0; + +vdac_r_dis: + regulator_disable(sdev->vdac); +dac_clk_dis: + clk_disable(sdev->sclk_dac); + return ret; } static const struct dev_pm_ops sdo_pm_ops = { diff --git a/drivers/media/platform/s5p-tv/sii9234_drv.c b/drivers/media/platform/s5p-tv/sii9234_drv.c index 39b77d24b9c2..3dd762e5b67e 100644 --- a/drivers/media/platform/s5p-tv/sii9234_drv.c +++ b/drivers/media/platform/s5p-tv/sii9234_drv.c @@ -249,7 +249,9 @@ static int sii9234_runtime_resume(struct device *dev) int ret; dev_info(dev, "resume start\n"); - regulator_enable(ctx->power); + ret = regulator_enable(ctx->power); + if (ret < 0) + return ret; ret = sii9234_reset(ctx); if (ret) diff --git a/drivers/media/platform/sh_veu.c b/drivers/media/platform/sh_veu.c index 59a9deefb242..aa4cca371cbf 100644 --- a/drivers/media/platform/sh_veu.c +++ b/drivers/media/platform/sh_veu.c @@ -359,10 +359,7 @@ static int sh_veu_context_init(struct sh_veu_dev *veu) veu->m2m_ctx = v4l2_m2m_ctx_init(veu->m2m_dev, veu, sh_veu_queue_init); - if (IS_ERR(veu->m2m_ctx)) - return PTR_ERR(veu->m2m_ctx); - - return 0; + return PTR_RET(veu->m2m_ctx); } static int sh_veu_querycap(struct file *file, void *priv, diff --git a/drivers/media/platform/sh_vou.c b/drivers/media/platform/sh_vou.c index 7d0235069c87..7a9c5e9329f2 100644 --- a/drivers/media/platform/sh_vou.c +++ b/drivers/media/platform/sh_vou.c @@ -1248,32 +1248,6 @@ static unsigned int sh_vou_poll(struct file *file, poll_table *wait) return res; } -static int sh_vou_g_chip_ident(struct file *file, void *fh, - struct v4l2_dbg_chip_ident *id) -{ - struct sh_vou_device *vou_dev = video_drvdata(file); - - return v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, core, g_chip_ident, id); -} - -#ifdef CONFIG_VIDEO_ADV_DEBUG -static int sh_vou_g_register(struct file *file, void *fh, - struct v4l2_dbg_register *reg) -{ - struct sh_vou_device *vou_dev = video_drvdata(file); - - return v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, core, g_register, reg); -} - -static int sh_vou_s_register(struct file *file, void *fh, - const struct v4l2_dbg_register *reg) -{ - struct sh_vou_device *vou_dev = video_drvdata(file); - - return v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, core, s_register, reg); -} -#endif - /* sh_vou display ioctl operations */ static const struct v4l2_ioctl_ops sh_vou_ioctl_ops = { .vidioc_querycap = sh_vou_querycap, @@ -1292,11 +1266,6 @@ static const struct v4l2_ioctl_ops sh_vou_ioctl_ops = { .vidioc_cropcap = sh_vou_cropcap, .vidioc_g_crop = sh_vou_g_crop, .vidioc_s_crop = sh_vou_s_crop, - .vidioc_g_chip_ident = sh_vou_g_chip_ident, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = sh_vou_g_register, - .vidioc_s_register = sh_vou_s_register, -#endif }; static const struct v4l2_file_operations sh_vou_fops = { @@ -1313,7 +1282,6 @@ static const struct video_device sh_vou_video_template = { .fops = &sh_vou_fops, .ioctl_ops = &sh_vou_ioctl_ops, .tvnorms = V4L2_STD_525_60, /* PAL only supported in 8-bit non-bt656 mode */ - .current_norm = V4L2_STD_NTSC_M, .vfl_dir = VFL_DIR_TX, }; @@ -1352,7 +1320,7 @@ static int sh_vou_probe(struct platform_device *pdev) pix = &vou_dev->pix; /* Fill in defaults */ - vou_dev->std = sh_vou_video_template.current_norm; + vou_dev->std = V4L2_STD_NTSC_M; rect->left = 0; rect->top = 0; rect->width = VOU_MAX_IMAGE_WIDTH; diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig index b139b525bb16..626dcccc37da 100644 --- a/drivers/media/platform/soc_camera/Kconfig +++ b/drivers/media/platform/soc_camera/Kconfig @@ -8,6 +8,9 @@ config SOC_CAMERA over a bus like PCI or USB. For example some i2c camera connected directly to the data bus of an SoC. +config SOC_CAMERA_SCALE_CROP + tristate + config SOC_CAMERA_PLATFORM tristate "platform camera support" depends on SOC_CAMERA @@ -27,14 +30,10 @@ config VIDEO_MX1 ---help--- This is a v4l2 driver for the i.MX1/i.MXL CMOS Sensor Interface -config MX3_VIDEO - bool - config VIDEO_MX3 tristate "i.MX3x Camera Sensor Interface driver" depends on VIDEO_DEV && MX3_IPU && SOC_CAMERA select VIDEOBUF2_DMA_CONTIG - select MX3_VIDEO ---help--- This is a v4l2 driver for the i.MX3x Camera Sensor Interface @@ -55,6 +54,7 @@ config VIDEO_SH_MOBILE_CEU tristate "SuperH Mobile CEU Interface driver" depends on VIDEO_DEV && SOC_CAMERA && HAS_DMA && HAVE_CLK select VIDEOBUF2_DMA_CONTIG + select SOC_CAMERA_SCALE_CROP ---help--- This is a v4l2 driver for the SuperH Mobile CEU Interface @@ -66,14 +66,10 @@ config VIDEO_OMAP1 ---help--- This is a v4l2 driver for the TI OMAP1 camera interface -config VIDEO_MX2_HOSTSUPPORT - bool - config VIDEO_MX2 tristate "i.MX27 Camera Sensor Interface driver" depends on VIDEO_DEV && SOC_CAMERA && MACH_MX27 select VIDEOBUF2_DMA_CONTIG - select VIDEO_MX2_HOSTSUPPORT ---help--- This is a v4l2 driver for the i.MX27 Camera Sensor Interface diff --git a/drivers/media/platform/soc_camera/Makefile b/drivers/media/platform/soc_camera/Makefile index 136b7f8ff10d..39186224c16a 100644 --- a/drivers/media/platform/soc_camera/Makefile +++ b/drivers/media/platform/soc_camera/Makefile @@ -1,4 +1,8 @@ obj-$(CONFIG_SOC_CAMERA) += soc_camera.o soc_mediabus.o +obj-$(CONFIG_SOC_CAMERA_SCALE_CROP) += soc_scale_crop.o + +# a platform subdevice driver stub, allowing to support cameras by adding a +# couple of callback functions to the board code obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o # soc-camera host drivers have to be linked after camera drivers @@ -10,5 +14,3 @@ obj-$(CONFIG_VIDEO_OMAP1) += omap1_camera.o obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o obj-$(CONFIG_VIDEO_SH_MOBILE_CSI2) += sh_mobile_csi2.o - -ccflags-y += -I$(srctree)/drivers/media/i2c/soc_camera diff --git a/drivers/media/platform/soc_camera/atmel-isi.c b/drivers/media/platform/soc_camera/atmel-isi.c index 1abbb36d0755..104485632501 100644 --- a/drivers/media/platform/soc_camera/atmel-isi.c +++ b/drivers/media/platform/soc_camera/atmel-isi.c @@ -102,7 +102,6 @@ struct atmel_isi { struct list_head video_buffer_list; struct frame_buffer *active; - struct soc_camera_device *icd; struct soc_camera_host soc_host; }; @@ -367,7 +366,7 @@ static void start_dma(struct atmel_isi *isi, struct frame_buffer *buffer) /* Check if already in a frame */ if (isi_readl(isi, ISI_STATUS) & ISI_CTRL_CDC) { - dev_err(isi->icd->parent, "Already in frame handling.\n"); + dev_err(isi->soc_host.icd->parent, "Already in frame handling.\n"); return; } @@ -746,16 +745,26 @@ static int isi_camera_get_formats(struct soc_camera_device *icd, return formats; } -/* Called with .host_lock held */ static int isi_camera_add_device(struct soc_camera_device *icd) { - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + dev_dbg(icd->parent, "Atmel ISI Camera driver attached to camera %d\n", + icd->devnum); + + return 0; +} + +static void isi_camera_remove_device(struct soc_camera_device *icd) +{ + dev_dbg(icd->parent, "Atmel ISI Camera driver detached from camera %d\n", + icd->devnum); +} + +/* Called with .host_lock held */ +static int isi_camera_clock_start(struct soc_camera_host *ici) +{ struct atmel_isi *isi = ici->priv; int ret; - if (isi->icd) - return -EBUSY; - ret = clk_enable(isi->pclk); if (ret) return ret; @@ -766,25 +775,16 @@ static int isi_camera_add_device(struct soc_camera_device *icd) return ret; } - isi->icd = icd; - dev_dbg(icd->parent, "Atmel ISI Camera driver attached to camera %d\n", - icd->devnum); return 0; } + /* Called with .host_lock held */ -static void isi_camera_remove_device(struct soc_camera_device *icd) +static void isi_camera_clock_stop(struct soc_camera_host *ici) { - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct atmel_isi *isi = ici->priv; - BUG_ON(icd != isi->icd); - clk_disable(isi->mck); clk_disable(isi->pclk); - isi->icd = NULL; - - dev_dbg(icd->parent, "Atmel ISI Camera driver detached from camera %d\n", - icd->devnum); } static unsigned int isi_camera_poll(struct file *file, poll_table *pt) @@ -888,6 +888,8 @@ static struct soc_camera_host_ops isi_soc_camera_host_ops = { .owner = THIS_MODULE, .add = isi_camera_add_device, .remove = isi_camera_remove_device, + .clock_start = isi_camera_clock_start, + .clock_stop = isi_camera_clock_stop, .set_fmt = isi_camera_set_fmt, .try_fmt = isi_camera_try_fmt, .get_formats = isi_camera_get_formats, diff --git a/drivers/media/platform/soc_camera/mx1_camera.c b/drivers/media/platform/soc_camera/mx1_camera.c index a3fd8d63546c..fea3e61476ae 100644 --- a/drivers/media/platform/soc_camera/mx1_camera.c +++ b/drivers/media/platform/soc_camera/mx1_camera.c @@ -104,7 +104,6 @@ struct mx1_buffer { */ struct mx1_camera_dev { struct soc_camera_host soc_host; - struct soc_camera_device *icd; struct mx1_camera_pdata *pdata; struct mx1_buffer *active; struct resource *res; @@ -220,7 +219,7 @@ out: static int mx1_camera_setup_dma(struct mx1_camera_dev *pcdev) { struct videobuf_buffer *vbuf = &pcdev->active->vb; - struct device *dev = pcdev->icd->parent; + struct device *dev = pcdev->soc_host.icd->parent; int ret; if (unlikely(!pcdev->active)) { @@ -331,7 +330,7 @@ static void mx1_camera_wakeup(struct mx1_camera_dev *pcdev, static void mx1_camera_dma_irq(int channel, void *data) { struct mx1_camera_dev *pcdev = data; - struct device *dev = pcdev->icd->parent; + struct device *dev = pcdev->soc_host.icd->parent; struct mx1_buffer *buf; struct videobuf_buffer *vb; unsigned long flags; @@ -389,7 +388,7 @@ static int mclk_get_divisor(struct mx1_camera_dev *pcdev) */ div = (lcdclk + 2 * mclk - 1) / (2 * mclk) - 1; - dev_dbg(pcdev->icd->parent, + dev_dbg(pcdev->soc_host.icd->parent, "System clock %lukHz, target freq %dkHz, divisor %lu\n", lcdclk / 1000, mclk / 1000, div); @@ -400,7 +399,7 @@ static void mx1_camera_activate(struct mx1_camera_dev *pcdev) { unsigned int csicr1 = CSICR1_EN; - dev_dbg(pcdev->icd->parent, "Activate device\n"); + dev_dbg(pcdev->soc_host.v4l2_dev.dev, "Activate device\n"); clk_prepare_enable(pcdev->clk); @@ -416,7 +415,7 @@ static void mx1_camera_activate(struct mx1_camera_dev *pcdev) static void mx1_camera_deactivate(struct mx1_camera_dev *pcdev) { - dev_dbg(pcdev->icd->parent, "Deactivate device\n"); + dev_dbg(pcdev->soc_host.v4l2_dev.dev, "Deactivate device\n"); /* Disable all CSI interface */ __raw_writel(0x00, pcdev->base + CSICR1); @@ -424,36 +423,38 @@ static void mx1_camera_deactivate(struct mx1_camera_dev *pcdev) clk_disable_unprepare(pcdev->clk); } +static int mx1_camera_add_device(struct soc_camera_device *icd) +{ + dev_info(icd->parent, "MX1 Camera driver attached to camera %d\n", + icd->devnum); + + return 0; +} + +static void mx1_camera_remove_device(struct soc_camera_device *icd) +{ + dev_info(icd->parent, "MX1 Camera driver detached from camera %d\n", + icd->devnum); +} + /* * The following two functions absolutely depend on the fact, that * there can be only one camera on i.MX1/i.MXL camera sensor interface */ -static int mx1_camera_add_device(struct soc_camera_device *icd) +static int mx1_camera_clock_start(struct soc_camera_host *ici) { - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct mx1_camera_dev *pcdev = ici->priv; - if (pcdev->icd) - return -EBUSY; - - dev_info(icd->parent, "MX1 Camera driver attached to camera %d\n", - icd->devnum); - mx1_camera_activate(pcdev); - pcdev->icd = icd; - return 0; } -static void mx1_camera_remove_device(struct soc_camera_device *icd) +static void mx1_camera_clock_stop(struct soc_camera_host *ici) { - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct mx1_camera_dev *pcdev = ici->priv; unsigned int csicr1; - BUG_ON(icd != pcdev->icd); - /* disable interrupts */ csicr1 = __raw_readl(pcdev->base + CSICR1) & ~CSI_IRQ_MASK; __raw_writel(csicr1, pcdev->base + CSICR1); @@ -461,12 +462,7 @@ static void mx1_camera_remove_device(struct soc_camera_device *icd) /* Stop DMA engine */ imx_dma_disable(pcdev->dma_chan); - dev_info(icd->parent, "MX1 Camera driver detached from camera %d\n", - icd->devnum); - mx1_camera_deactivate(pcdev); - - pcdev->icd = NULL; } static int mx1_camera_set_bus_param(struct soc_camera_device *icd) @@ -679,6 +675,8 @@ static struct soc_camera_host_ops mx1_soc_camera_host_ops = { .owner = THIS_MODULE, .add = mx1_camera_add_device, .remove = mx1_camera_remove_device, + .clock_start = mx1_camera_clock_start, + .clock_stop = mx1_camera_clock_stop, .set_bus_param = mx1_camera_set_bus_param, .set_fmt = mx1_camera_set_fmt, .try_fmt = mx1_camera_try_fmt, diff --git a/drivers/media/platform/soc_camera/mx2_camera.c b/drivers/media/platform/soc_camera/mx2_camera.c index 5bbeb43e4531..45a0276be4e5 100644 --- a/drivers/media/platform/soc_camera/mx2_camera.c +++ b/drivers/media/platform/soc_camera/mx2_camera.c @@ -236,7 +236,6 @@ enum mx2_camera_type { struct mx2_camera_dev { struct device *dev; struct soc_camera_host soc_host; - struct soc_camera_device *icd; struct clk *clk_emma_ahb, *clk_emma_ipg; struct clk *clk_csi_ahb, *clk_csi_per; @@ -394,8 +393,8 @@ static void mx27_update_emma_buf(struct mx2_camera_dev *pcdev, writel(phys, pcdev->base_emma + PRP_DEST_Y_PTR - 0x14 * bufnum); if (prp->out_fmt == V4L2_PIX_FMT_YUV420) { - u32 imgsize = pcdev->icd->user_height * - pcdev->icd->user_width; + u32 imgsize = pcdev->soc_host.icd->user_height * + pcdev->soc_host.icd->user_width; writel(phys + imgsize, pcdev->base_emma + PRP_DEST_CB_PTR - 0x14 * bufnum); @@ -413,20 +412,30 @@ static void mx2_camera_deactivate(struct mx2_camera_dev *pcdev) writel(0, pcdev->base_emma + PRP_CNTL); } +static int mx2_camera_add_device(struct soc_camera_device *icd) +{ + dev_info(icd->parent, "Camera driver attached to camera %d\n", + icd->devnum); + + return 0; +} + +static void mx2_camera_remove_device(struct soc_camera_device *icd) +{ + dev_info(icd->parent, "Camera driver detached from camera %d\n", + icd->devnum); +} + /* * The following two functions absolutely depend on the fact, that * there can be only one camera on mx2 camera sensor interface */ -static int mx2_camera_add_device(struct soc_camera_device *icd) +static int mx2_camera_clock_start(struct soc_camera_host *ici) { - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct mx2_camera_dev *pcdev = ici->priv; int ret; u32 csicr1; - if (pcdev->icd) - return -EBUSY; - ret = clk_prepare_enable(pcdev->clk_csi_ahb); if (ret < 0) return ret; @@ -441,12 +450,8 @@ static int mx2_camera_add_device(struct soc_camera_device *icd) pcdev->csicr1 = csicr1; writel(pcdev->csicr1, pcdev->base_csi + CSICR1); - pcdev->icd = icd; pcdev->frame_count = 0; - dev_info(icd->parent, "Camera driver attached to camera %d\n", - icd->devnum); - return 0; exit_csi_ahb: @@ -455,19 +460,11 @@ exit_csi_ahb: return ret; } -static void mx2_camera_remove_device(struct soc_camera_device *icd) +static void mx2_camera_clock_stop(struct soc_camera_host *ici) { - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct mx2_camera_dev *pcdev = ici->priv; - BUG_ON(icd != pcdev->icd); - - dev_info(icd->parent, "Camera driver detached from camera %d\n", - icd->devnum); - mx2_camera_deactivate(pcdev); - - pcdev->icd = NULL; } /* @@ -1280,6 +1277,8 @@ static struct soc_camera_host_ops mx2_soc_camera_host_ops = { .owner = THIS_MODULE, .add = mx2_camera_add_device, .remove = mx2_camera_remove_device, + .clock_start = mx2_camera_clock_start, + .clock_stop = mx2_camera_clock_stop, .set_fmt = mx2_camera_set_fmt, .set_crop = mx2_camera_set_crop, .get_formats = mx2_camera_get_formats, diff --git a/drivers/media/platform/soc_camera/mx3_camera.c b/drivers/media/platform/soc_camera/mx3_camera.c index 5da337736cd8..1047e3e8db77 100644 --- a/drivers/media/platform/soc_camera/mx3_camera.c +++ b/drivers/media/platform/soc_camera/mx3_camera.c @@ -94,7 +94,6 @@ struct mx3_camera_dev { * Interface. If anyone ever builds hardware to enable more than one * camera _simultaneously_, they will have to modify this driver too */ - struct soc_camera_device *icd; struct clk *clk; void __iomem *base; @@ -461,8 +460,7 @@ static int mx3_camera_init_videobuf(struct vb2_queue *q, } /* First part of ipu_csi_init_interface() */ -static void mx3_camera_activate(struct mx3_camera_dev *mx3_cam, - struct soc_camera_device *icd) +static void mx3_camera_activate(struct mx3_camera_dev *mx3_cam) { u32 conf; long rate; @@ -506,51 +504,49 @@ static void mx3_camera_activate(struct mx3_camera_dev *mx3_cam, clk_prepare_enable(mx3_cam->clk); rate = clk_round_rate(mx3_cam->clk, mx3_cam->mclk); - dev_dbg(icd->parent, "Set SENS_CONF to %x, rate %ld\n", conf, rate); + dev_dbg(mx3_cam->soc_host.v4l2_dev.dev, "Set SENS_CONF to %x, rate %ld\n", conf, rate); if (rate) clk_set_rate(mx3_cam->clk, rate); } -/* Called with .host_lock held */ static int mx3_camera_add_device(struct soc_camera_device *icd) { - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); - struct mx3_camera_dev *mx3_cam = ici->priv; + dev_info(icd->parent, "MX3 Camera driver attached to camera %d\n", + icd->devnum); - if (mx3_cam->icd) - return -EBUSY; + return 0; +} - mx3_camera_activate(mx3_cam, icd); +static void mx3_camera_remove_device(struct soc_camera_device *icd) +{ + dev_info(icd->parent, "MX3 Camera driver detached from camera %d\n", + icd->devnum); +} - mx3_cam->buf_total = 0; - mx3_cam->icd = icd; +/* Called with .host_lock held */ +static int mx3_camera_clock_start(struct soc_camera_host *ici) +{ + struct mx3_camera_dev *mx3_cam = ici->priv; - dev_info(icd->parent, "MX3 Camera driver attached to camera %d\n", - icd->devnum); + mx3_camera_activate(mx3_cam); + + mx3_cam->buf_total = 0; return 0; } /* Called with .host_lock held */ -static void mx3_camera_remove_device(struct soc_camera_device *icd) +static void mx3_camera_clock_stop(struct soc_camera_host *ici) { - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct mx3_camera_dev *mx3_cam = ici->priv; struct idmac_channel **ichan = &mx3_cam->idmac_channel[0]; - BUG_ON(icd != mx3_cam->icd); - if (*ichan) { dma_release_channel(&(*ichan)->dma_chan); *ichan = NULL; } clk_disable_unprepare(mx3_cam->clk); - - mx3_cam->icd = NULL; - - dev_info(icd->parent, "MX3 Camera driver detached from camera %d\n", - icd->devnum); } static int test_platform_param(struct mx3_camera_dev *mx3_cam, @@ -1133,6 +1129,8 @@ static struct soc_camera_host_ops mx3_soc_camera_host_ops = { .owner = THIS_MODULE, .add = mx3_camera_add_device, .remove = mx3_camera_remove_device, + .clock_start = mx3_camera_clock_start, + .clock_stop = mx3_camera_clock_stop, .set_crop = mx3_camera_set_crop, .set_fmt = mx3_camera_set_fmt, .try_fmt = mx3_camera_try_fmt, diff --git a/drivers/media/platform/soc_camera/omap1_camera.c b/drivers/media/platform/soc_camera/omap1_camera.c index 9689a6e89b7f..6769193c7c7b 100644 --- a/drivers/media/platform/soc_camera/omap1_camera.c +++ b/drivers/media/platform/soc_camera/omap1_camera.c @@ -150,7 +150,6 @@ struct omap1_cam_buf { struct omap1_cam_dev { struct soc_camera_host soc_host; - struct soc_camera_device *icd; struct clk *clk; unsigned int irq; @@ -564,7 +563,7 @@ static void videobuf_done(struct omap1_cam_dev *pcdev, { struct omap1_cam_buf *buf = pcdev->active; struct videobuf_buffer *vb; - struct device *dev = pcdev->icd->parent; + struct device *dev = pcdev->soc_host.icd->parent; if (WARN_ON(!buf)) { suspend_capture(pcdev); @@ -790,7 +789,7 @@ out: static irqreturn_t cam_isr(int irq, void *data) { struct omap1_cam_dev *pcdev = data; - struct device *dev = pcdev->icd->parent; + struct device *dev = pcdev->soc_host.icd->parent; struct omap1_cam_buf *buf = pcdev->active; u32 it_status; unsigned long flags; @@ -894,19 +893,29 @@ static void sensor_reset(struct omap1_cam_dev *pcdev, bool reset) CAM_WRITE(pcdev, GPIO, !reset); } +static int omap1_cam_add_device(struct soc_camera_device *icd) +{ + dev_dbg(icd->parent, "OMAP1 Camera driver attached to camera %d\n", + icd->devnum); + + return 0; +} + +static void omap1_cam_remove_device(struct soc_camera_device *icd) +{ + dev_dbg(icd->parent, + "OMAP1 Camera driver detached from camera %d\n", icd->devnum); +} + /* * The following two functions absolutely depend on the fact, that * there can be only one camera on OMAP1 camera sensor interface */ -static int omap1_cam_add_device(struct soc_camera_device *icd) +static int omap1_cam_clock_start(struct soc_camera_host *ici) { - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct omap1_cam_dev *pcdev = ici->priv; u32 ctrlclock; - if (pcdev->icd) - return -EBUSY; - clk_enable(pcdev->clk); /* setup sensor clock */ @@ -941,21 +950,14 @@ static int omap1_cam_add_device(struct soc_camera_device *icd) sensor_reset(pcdev, false); - pcdev->icd = icd; - - dev_dbg(icd->parent, "OMAP1 Camera driver attached to camera %d\n", - icd->devnum); return 0; } -static void omap1_cam_remove_device(struct soc_camera_device *icd) +static void omap1_cam_clock_stop(struct soc_camera_host *ici) { - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct omap1_cam_dev *pcdev = ici->priv; u32 ctrlclock; - BUG_ON(icd != pcdev->icd); - suspend_capture(pcdev); disable_capture(pcdev); @@ -973,11 +975,6 @@ static void omap1_cam_remove_device(struct soc_camera_device *icd) CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock & ~MCLK_EN); clk_disable(pcdev->clk); - - pcdev->icd = NULL; - - dev_dbg(icd->parent, - "OMAP1 Camera driver detached from camera %d\n", icd->devnum); } /* Duplicate standard formats based on host capability of byte swapping */ @@ -1535,6 +1532,8 @@ static struct soc_camera_host_ops omap1_host_ops = { .owner = THIS_MODULE, .add = omap1_cam_add_device, .remove = omap1_cam_remove_device, + .clock_start = omap1_cam_clock_start, + .clock_stop = omap1_cam_clock_stop, .get_formats = omap1_cam_get_formats, .set_crop = omap1_cam_set_crop, .set_fmt = omap1_cam_set_fmt, diff --git a/drivers/media/platform/soc_camera/pxa_camera.c b/drivers/media/platform/soc_camera/pxa_camera.c index d665242e8207..d4df305fcc18 100644 --- a/drivers/media/platform/soc_camera/pxa_camera.c +++ b/drivers/media/platform/soc_camera/pxa_camera.c @@ -200,7 +200,6 @@ struct pxa_camera_dev { * interface. If anyone ever builds hardware to enable more than * one camera, they will have to modify this driver too */ - struct soc_camera_device *icd; struct clk *clk; unsigned int irq; @@ -956,40 +955,39 @@ static irqreturn_t pxa_camera_irq(int irq, void *data) return IRQ_HANDLED; } +static int pxa_camera_add_device(struct soc_camera_device *icd) +{ + dev_info(icd->parent, "PXA Camera driver attached to camera %d\n", + icd->devnum); + + return 0; +} + +static void pxa_camera_remove_device(struct soc_camera_device *icd) +{ + dev_info(icd->parent, "PXA Camera driver detached from camera %d\n", + icd->devnum); +} + /* * The following two functions absolutely depend on the fact, that * there can be only one camera on PXA quick capture interface * Called with .host_lock held */ -static int pxa_camera_add_device(struct soc_camera_device *icd) +static int pxa_camera_clock_start(struct soc_camera_host *ici) { - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct pxa_camera_dev *pcdev = ici->priv; - if (pcdev->icd) - return -EBUSY; - pxa_camera_activate(pcdev); - pcdev->icd = icd; - - dev_info(icd->parent, "PXA Camera driver attached to camera %d\n", - icd->devnum); - return 0; } /* Called with .host_lock held */ -static void pxa_camera_remove_device(struct soc_camera_device *icd) +static void pxa_camera_clock_stop(struct soc_camera_host *ici) { - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct pxa_camera_dev *pcdev = ici->priv; - BUG_ON(icd != pcdev->icd); - - dev_info(icd->parent, "PXA Camera driver detached from camera %d\n", - icd->devnum); - /* disable capture, disable interrupts */ __raw_writel(0x3ff, pcdev->base + CICR0); @@ -999,8 +997,6 @@ static void pxa_camera_remove_device(struct soc_camera_device *icd) DCSR(pcdev->dma_chans[2]) = 0; pxa_camera_deactivate(pcdev); - - pcdev->icd = NULL; } static int test_platform_param(struct pxa_camera_dev *pcdev, @@ -1596,8 +1592,8 @@ static int pxa_camera_suspend(struct device *dev) pcdev->save_cicr[i++] = __raw_readl(pcdev->base + CICR3); pcdev->save_cicr[i++] = __raw_readl(pcdev->base + CICR4); - if (pcdev->icd) { - struct v4l2_subdev *sd = soc_camera_to_subdev(pcdev->icd); + if (pcdev->soc_host.icd) { + struct v4l2_subdev *sd = soc_camera_to_subdev(pcdev->soc_host.icd); ret = v4l2_subdev_call(sd, core, s_power, 0); if (ret == -ENOIOCTLCMD) ret = 0; @@ -1622,8 +1618,8 @@ static int pxa_camera_resume(struct device *dev) __raw_writel(pcdev->save_cicr[i++], pcdev->base + CICR3); __raw_writel(pcdev->save_cicr[i++], pcdev->base + CICR4); - if (pcdev->icd) { - struct v4l2_subdev *sd = soc_camera_to_subdev(pcdev->icd); + if (pcdev->soc_host.icd) { + struct v4l2_subdev *sd = soc_camera_to_subdev(pcdev->soc_host.icd); ret = v4l2_subdev_call(sd, core, s_power, 1); if (ret == -ENOIOCTLCMD) ret = 0; @@ -1640,6 +1636,8 @@ static struct soc_camera_host_ops pxa_soc_camera_host_ops = { .owner = THIS_MODULE, .add = pxa_camera_add_device, .remove = pxa_camera_remove_device, + .clock_start = pxa_camera_clock_start, + .clock_stop = pxa_camera_clock_stop, .set_crop = pxa_camera_set_crop, .get_formats = pxa_camera_get_formats, .put_formats = pxa_camera_put_formats, 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 143d29fe0137..f2de0066089a 100644 --- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c +++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c @@ -27,6 +27,7 @@ #include <linux/kernel.h> #include <linux/mm.h> #include <linux/moduleparam.h> +#include <linux/of.h> #include <linux/time.h> #include <linux/slab.h> #include <linux/device.h> @@ -35,6 +36,7 @@ #include <linux/pm_runtime.h> #include <linux/sched.h> +#include <media/v4l2-async.h> #include <media/v4l2-common.h> #include <media/v4l2-dev.h> #include <media/soc_camera.h> @@ -44,6 +46,8 @@ #include <media/v4l2-mediabus.h> #include <media/soc_mediabus.h> +#include "soc_scale_crop.h" + /* register offsets for sh7722 / sh7723 */ #define CAPSR 0x00 /* Capture start register */ @@ -95,7 +99,10 @@ struct sh_mobile_ceu_buffer { struct sh_mobile_ceu_dev { struct soc_camera_host ici; - struct soc_camera_device *icd; + /* Asynchronous CSI2 linking */ + struct v4l2_async_subdev *csi2_asd; + struct v4l2_subdev *csi2_sd; + /* Synchronous probing compatibility */ struct platform_device *csi2_pdev; unsigned int irq; @@ -119,6 +126,7 @@ struct sh_mobile_ceu_dev { enum v4l2_field field; int sequence; + unsigned long flags; unsigned int image_mode:1; unsigned int is_16bit:1; @@ -163,7 +171,6 @@ static u32 ceu_read(struct sh_mobile_ceu_dev *priv, unsigned long reg_offs) static int sh_mobile_ceu_soft_reset(struct sh_mobile_ceu_dev *pcdev) { int i, success = 0; - struct soc_camera_device *icd = pcdev->icd; ceu_write(pcdev, CAPSR, 1 << 16); /* reset */ @@ -185,9 +192,8 @@ static int sh_mobile_ceu_soft_reset(struct sh_mobile_ceu_dev *pcdev) udelay(1); } - if (2 != success) { - dev_warn(icd->pdev, "soft reset time out\n"); + dev_warn(pcdev->ici.v4l2_dev.dev, "soft reset time out\n"); return -EIO; } @@ -277,7 +283,7 @@ static int sh_mobile_ceu_videobuf_setup(struct vb2_queue *vq, */ static int sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) { - struct soc_camera_device *icd = pcdev->icd; + struct soc_camera_device *icd = pcdev->ici.icd; dma_addr_t phys_addr_top, phys_addr_bottom; unsigned long top1, top2; unsigned long bottom1, bottom2; @@ -534,72 +540,92 @@ static struct v4l2_subdev *find_csi2(struct sh_mobile_ceu_dev *pcdev) { struct v4l2_subdev *sd; - if (!pcdev->csi2_pdev) - return NULL; + if (pcdev->csi2_sd) + return pcdev->csi2_sd; - v4l2_device_for_each_subdev(sd, &pcdev->ici.v4l2_dev) - if (&pcdev->csi2_pdev->dev == v4l2_get_subdevdata(sd)) - return sd; + if (pcdev->csi2_asd) { + char name[] = "sh-mobile-csi2"; + v4l2_device_for_each_subdev(sd, &pcdev->ici.v4l2_dev) + if (!strncmp(name, sd->name, sizeof(name) - 1)) { + pcdev->csi2_sd = sd; + return sd; + } + } return NULL; } -/* Called with .host_lock held */ +static struct v4l2_subdev *csi2_subdev(struct sh_mobile_ceu_dev *pcdev, + struct soc_camera_device *icd) +{ + struct v4l2_subdev *sd = pcdev->csi2_sd; + + return sd && sd->grp_id == soc_camera_grp_id(icd) ? sd : NULL; +} + static int sh_mobile_ceu_add_device(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; - struct v4l2_subdev *csi2_sd; + struct v4l2_subdev *csi2_sd = find_csi2(pcdev); int ret; - if (pcdev->icd) - return -EBUSY; - - dev_info(icd->parent, - "SuperH Mobile CEU driver attached to camera %d\n", - icd->devnum); - - pm_runtime_get_sync(ici->v4l2_dev.dev); - - pcdev->buf_total = 0; - - ret = sh_mobile_ceu_soft_reset(pcdev); - - csi2_sd = find_csi2(pcdev); if (csi2_sd) { csi2_sd->grp_id = soc_camera_grp_id(icd); v4l2_set_subdev_hostdata(csi2_sd, icd); } ret = v4l2_subdev_call(csi2_sd, core, s_power, 1); - if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) { - pm_runtime_put(ici->v4l2_dev.dev); + if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) return ret; - } /* * -ENODEV is special: either csi2_sd == NULL or the CSI-2 driver * has not found this soc-camera device among its clients */ - if (ret == -ENODEV && csi2_sd) + if (csi2_sd && ret == -ENODEV) csi2_sd->grp_id = 0; - pcdev->icd = icd; + + dev_info(icd->parent, + "SuperH Mobile CEU%s driver attached to camera %d\n", + csi2_sd && csi2_sd->grp_id ? "/CSI-2" : "", icd->devnum); return 0; } -/* Called with .host_lock held */ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; struct v4l2_subdev *csi2_sd = find_csi2(pcdev); - BUG_ON(icd != pcdev->icd); + dev_info(icd->parent, + "SuperH Mobile CEU driver detached from camera %d\n", + icd->devnum); v4l2_subdev_call(csi2_sd, core, s_power, 0); - if (csi2_sd) - csi2_sd->grp_id = 0; +} + +/* Called with .host_lock held */ +static int sh_mobile_ceu_clock_start(struct soc_camera_host *ici) +{ + struct sh_mobile_ceu_dev *pcdev = ici->priv; + int ret; + + pm_runtime_get_sync(ici->v4l2_dev.dev); + + pcdev->buf_total = 0; + + ret = sh_mobile_ceu_soft_reset(pcdev); + + return 0; +} + +/* Called with .host_lock held */ +static void sh_mobile_ceu_clock_stop(struct soc_camera_host *ici) +{ + struct sh_mobile_ceu_dev *pcdev = ici->priv; + /* disable capture, disable interrupts */ ceu_write(pcdev, CEIER, 0); sh_mobile_ceu_soft_reset(pcdev); @@ -614,12 +640,6 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) spin_unlock_irq(&pcdev->lock); pm_runtime_put(ici->v4l2_dev.dev); - - dev_info(icd->parent, - "SuperH Mobile CEU driver detached from camera %d\n", - icd->devnum); - - pcdev->icd = NULL; } /* @@ -705,7 +725,7 @@ static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd) } /* CSI2 special configuration */ - if (pcdev->pdata->csi2) { + if (csi2_subdev(pcdev, icd)) { in_width = ((in_width - 2) * 2); left_offset *= 2; } @@ -762,13 +782,7 @@ static void capture_restore(struct sh_mobile_ceu_dev *pcdev, u32 capsr) static struct v4l2_subdev *find_bus_subdev(struct sh_mobile_ceu_dev *pcdev, struct soc_camera_device *icd) { - if (pcdev->csi2_pdev) { - struct v4l2_subdev *csi2_sd = find_csi2(pcdev); - if (csi2_sd && csi2_sd->grp_id == soc_camera_grp_id(icd)) - return csi2_sd; - } - - return soc_camera_to_subdev(icd); + return csi2_subdev(pcdev, icd) ? : soc_camera_to_subdev(icd); } #define CEU_BUS_FLAGS (V4L2_MBUS_MASTER | \ @@ -809,7 +823,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd) /* Make choises, based on platform preferences */ if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) && (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) { - if (pcdev->pdata->flags & SH_CEU_FLAG_HSYNC_LOW) + if (pcdev->flags & SH_CEU_FLAG_HSYNC_LOW) common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH; else common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW; @@ -817,7 +831,7 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd) if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) && (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) { - if (pcdev->pdata->flags & SH_CEU_FLAG_VSYNC_LOW) + if (pcdev->flags & SH_CEU_FLAG_VSYNC_LOW) common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH; else common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW; @@ -872,11 +886,11 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd) value |= common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW ? 1 << 1 : 0; value |= common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW ? 1 << 0 : 0; - if (pcdev->pdata->csi2) /* CSI2 mode */ + if (csi2_subdev(pcdev, icd)) /* CSI2 mode */ value |= 3 << 12; else if (pcdev->is_16bit) value |= 1 << 12; - else if (pcdev->pdata->flags & SH_CEU_FLAG_LOWER_8BIT) + else if (pcdev->flags & SH_CEU_FLAG_LOWER_8BIT) value |= 2 << 12; ceu_write(pcdev, CAMCR, value); @@ -993,8 +1007,6 @@ static bool sh_mobile_ceu_packing_supported(const struct soc_mbus_pixelfmt *fmt) fmt->packing == SOC_MBUS_PACKING_EXTEND16); } -static int client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect); - static struct soc_camera_device *ctrl_to_icd(struct v4l2_ctrl *ctrl) { return container_of(ctrl->handler, struct soc_camera_device, @@ -1051,7 +1063,7 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, unsigned int return 0; } - if (!pcdev->pdata->csi2) { + if (!csi2_subdev(pcdev, icd)) { /* Are there any restrictions in the CSI-2 case? */ ret = sh_mobile_ceu_try_bus_param(icd, fmt->bits_per_sample); if (ret < 0) @@ -1072,7 +1084,7 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, unsigned int /* FIXME: subwindow is lost between close / open */ /* Cache current client geometry */ - ret = client_g_rect(sd, &rect); + ret = soc_camera_client_g_rect(sd, &rect); if (ret < 0) return ret; @@ -1182,334 +1194,8 @@ static void sh_mobile_ceu_put_formats(struct soc_camera_device *icd) icd->host_priv = NULL; } -/* Check if any dimension of r1 is smaller than respective one of r2 */ -static bool is_smaller(const struct v4l2_rect *r1, const struct v4l2_rect *r2) -{ - return r1->width < r2->width || r1->height < r2->height; -} - -/* Check if r1 fails to cover r2 */ -static bool is_inside(const struct v4l2_rect *r1, const struct v4l2_rect *r2) -{ - return r1->left > r2->left || r1->top > r2->top || - r1->left + r1->width < r2->left + r2->width || - r1->top + r1->height < r2->top + r2->height; -} - -static unsigned int scale_down(unsigned int size, unsigned int scale) -{ - return (size * 4096 + scale / 2) / scale; -} - -static unsigned int calc_generic_scale(unsigned int input, unsigned int output) -{ - return (input * 4096 + output / 2) / output; -} - -/* Get and store current client crop */ -static int client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect) -{ - struct v4l2_crop crop; - struct v4l2_cropcap cap; - int ret; - - crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - ret = v4l2_subdev_call(sd, video, g_crop, &crop); - if (!ret) { - *rect = crop.c; - return ret; - } - - /* Camera driver doesn't support .g_crop(), assume default rectangle */ - cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - ret = v4l2_subdev_call(sd, video, cropcap, &cap); - if (!ret) - *rect = cap.defrect; - - return ret; -} - -/* Client crop has changed, update our sub-rectangle to remain within the area */ -static void update_subrect(struct sh_mobile_ceu_cam *cam) -{ - struct v4l2_rect *rect = &cam->rect, *subrect = &cam->subrect; - - if (rect->width < subrect->width) - subrect->width = rect->width; - - if (rect->height < subrect->height) - subrect->height = rect->height; - - if (rect->left > subrect->left) - subrect->left = rect->left; - else if (rect->left + rect->width > - subrect->left + subrect->width) - subrect->left = rect->left + rect->width - - subrect->width; - - if (rect->top > subrect->top) - subrect->top = rect->top; - else if (rect->top + rect->height > - subrect->top + subrect->height) - subrect->top = rect->top + rect->height - - subrect->height; -} - -/* - * The common for both scaling and cropping iterative approach is: - * 1. try if the client can produce exactly what requested by the user - * 2. if (1) failed, try to double the client image until we get one big enough - * 3. if (2) failed, try to request the maximum image - */ -static int client_s_crop(struct soc_camera_device *icd, struct v4l2_crop *crop, - struct v4l2_crop *cam_crop) -{ - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - struct v4l2_rect *rect = &crop->c, *cam_rect = &cam_crop->c; - struct device *dev = sd->v4l2_dev->dev; - struct sh_mobile_ceu_cam *cam = icd->host_priv; - struct v4l2_cropcap cap; - int ret; - unsigned int width, height; - - v4l2_subdev_call(sd, video, s_crop, crop); - ret = client_g_rect(sd, cam_rect); - if (ret < 0) - return ret; - - /* - * Now cam_crop contains the current camera input rectangle, and it must - * be within camera cropcap bounds - */ - if (!memcmp(rect, cam_rect, sizeof(*rect))) { - /* Even if camera S_CROP failed, but camera rectangle matches */ - dev_dbg(dev, "Camera S_CROP successful for %dx%d@%d:%d\n", - rect->width, rect->height, rect->left, rect->top); - cam->rect = *cam_rect; - return 0; - } - - /* Try to fix cropping, that camera hasn't managed to set */ - dev_geo(dev, "Fix camera S_CROP for %dx%d@%d:%d to %dx%d@%d:%d\n", - cam_rect->width, cam_rect->height, - cam_rect->left, cam_rect->top, - rect->width, rect->height, rect->left, rect->top); - - /* We need sensor maximum rectangle */ - ret = v4l2_subdev_call(sd, video, cropcap, &cap); - if (ret < 0) - return ret; - - /* Put user requested rectangle within sensor bounds */ - soc_camera_limit_side(&rect->left, &rect->width, cap.bounds.left, 2, - cap.bounds.width); - soc_camera_limit_side(&rect->top, &rect->height, cap.bounds.top, 4, - cap.bounds.height); - - /* - * Popular special case - some cameras can only handle fixed sizes like - * QVGA, VGA,... Take care to avoid infinite loop. - */ - width = max(cam_rect->width, 2); - height = max(cam_rect->height, 2); - - /* - * Loop as long as sensor is not covering the requested rectangle and - * is still within its bounds - */ - while (!ret && (is_smaller(cam_rect, rect) || - is_inside(cam_rect, rect)) && - (cap.bounds.width > width || cap.bounds.height > height)) { - - width *= 2; - height *= 2; - - cam_rect->width = width; - cam_rect->height = height; - - /* - * We do not know what capabilities the camera has to set up - * left and top borders. We could try to be smarter in iterating - * them, e.g., if camera current left is to the right of the - * target left, set it to the middle point between the current - * left and minimum left. But that would add too much - * complexity: we would have to iterate each border separately. - * Instead we just drop to the left and top bounds. - */ - if (cam_rect->left > rect->left) - cam_rect->left = cap.bounds.left; - - if (cam_rect->left + cam_rect->width < rect->left + rect->width) - cam_rect->width = rect->left + rect->width - - cam_rect->left; - - if (cam_rect->top > rect->top) - cam_rect->top = cap.bounds.top; - - if (cam_rect->top + cam_rect->height < rect->top + rect->height) - cam_rect->height = rect->top + rect->height - - cam_rect->top; - - v4l2_subdev_call(sd, video, s_crop, cam_crop); - ret = client_g_rect(sd, cam_rect); - dev_geo(dev, "Camera S_CROP %d for %dx%d@%d:%d\n", ret, - cam_rect->width, cam_rect->height, - cam_rect->left, cam_rect->top); - } - - /* S_CROP must not modify the rectangle */ - if (is_smaller(cam_rect, rect) || is_inside(cam_rect, rect)) { - /* - * The camera failed to configure a suitable cropping, - * we cannot use the current rectangle, set to max - */ - *cam_rect = cap.bounds; - v4l2_subdev_call(sd, video, s_crop, cam_crop); - ret = client_g_rect(sd, cam_rect); - dev_geo(dev, "Camera S_CROP %d for max %dx%d@%d:%d\n", ret, - cam_rect->width, cam_rect->height, - cam_rect->left, cam_rect->top); - } - - if (!ret) { - cam->rect = *cam_rect; - update_subrect(cam); - } - - return ret; -} - -/* Iterative s_mbus_fmt, also updates cached client crop on success */ -static int client_s_fmt(struct soc_camera_device *icd, - struct v4l2_mbus_framefmt *mf, bool ceu_can_scale) -{ - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); - struct sh_mobile_ceu_dev *pcdev = ici->priv; - struct sh_mobile_ceu_cam *cam = icd->host_priv; - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - struct device *dev = icd->parent; - unsigned int width = mf->width, height = mf->height, tmp_w, tmp_h; - unsigned int max_width, max_height; - struct v4l2_cropcap cap; - bool ceu_1to1; - int ret; - - ret = v4l2_device_call_until_err(sd->v4l2_dev, - soc_camera_grp_id(icd), video, - s_mbus_fmt, mf); - if (ret < 0) - return ret; - - dev_geo(dev, "camera scaled to %ux%u\n", mf->width, mf->height); - - if (width == mf->width && height == mf->height) { - /* Perfect! The client has done it all. */ - ceu_1to1 = true; - goto update_cache; - } - - ceu_1to1 = false; - if (!ceu_can_scale) - goto update_cache; - - cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - ret = v4l2_subdev_call(sd, video, cropcap, &cap); - if (ret < 0) - return ret; - - max_width = min(cap.bounds.width, pcdev->max_width); - max_height = min(cap.bounds.height, pcdev->max_height); - - /* Camera set a format, but geometry is not precise, try to improve */ - tmp_w = mf->width; - tmp_h = mf->height; - - /* width <= max_width && height <= max_height - guaranteed by try_fmt */ - while ((width > tmp_w || height > tmp_h) && - tmp_w < max_width && tmp_h < max_height) { - tmp_w = min(2 * tmp_w, max_width); - tmp_h = min(2 * tmp_h, max_height); - mf->width = tmp_w; - mf->height = tmp_h; - ret = v4l2_device_call_until_err(sd->v4l2_dev, - soc_camera_grp_id(icd), video, - s_mbus_fmt, mf); - dev_geo(dev, "Camera scaled to %ux%u\n", - mf->width, mf->height); - if (ret < 0) { - /* This shouldn't happen */ - dev_err(dev, "Client failed to set format: %d\n", ret); - return ret; - } - } - -update_cache: - /* Update cache */ - ret = client_g_rect(sd, &cam->rect); - if (ret < 0) - return ret; - - if (ceu_1to1) - cam->subrect = cam->rect; - else - update_subrect(cam); - - return 0; -} - -/** - * @width - on output: user width, mapped back to input - * @height - on output: user height, mapped back to input - * @mf - in- / output camera output window - */ -static int client_scale(struct soc_camera_device *icd, - struct v4l2_mbus_framefmt *mf, - unsigned int *width, unsigned int *height, - bool ceu_can_scale) -{ - struct sh_mobile_ceu_cam *cam = icd->host_priv; - struct device *dev = icd->parent; - struct v4l2_mbus_framefmt mf_tmp = *mf; - unsigned int scale_h, scale_v; - int ret; - - /* - * 5. Apply iterative camera S_FMT for camera user window (also updates - * client crop cache and the imaginary sub-rectangle). - */ - ret = client_s_fmt(icd, &mf_tmp, ceu_can_scale); - if (ret < 0) - return ret; - - dev_geo(dev, "5: camera scaled to %ux%u\n", - mf_tmp.width, mf_tmp.height); - - /* 6. Retrieve camera output window (g_fmt) */ - - /* unneeded - it is already in "mf_tmp" */ - - /* 7. Calculate new client scales. */ - scale_h = calc_generic_scale(cam->rect.width, mf_tmp.width); - scale_v = calc_generic_scale(cam->rect.height, mf_tmp.height); - - mf->width = mf_tmp.width; - mf->height = mf_tmp.height; - mf->colorspace = mf_tmp.colorspace; - - /* - * 8. Calculate new CEU crop - apply camera scales to previously - * updated "effective" crop. - */ - *width = scale_down(cam->subrect.width, scale_h); - *height = scale_down(cam->subrect.height, scale_v); - - dev_geo(dev, "8: new client sub-window %ux%u\n", *width, *height); - - return 0; -} +#define scale_down(size, scale) soc_camera_shift_scale(size, 12, scale) +#define calc_generic_scale(in, out) soc_camera_calc_scale(in, 12, out) /* * CEU can scale and crop, but we don't want to waste bandwidth and kill the @@ -1547,7 +1233,8 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, * 1. - 2. Apply iterative camera S_CROP for new input window, read back * actual camera rectangle. */ - ret = client_s_crop(icd, &a_writable, &cam_crop); + ret = soc_camera_client_s_crop(sd, &a_writable, &cam_crop, + &cam->rect, &cam->subrect); if (ret < 0) return ret; @@ -1666,55 +1353,6 @@ static int sh_mobile_ceu_get_crop(struct soc_camera_device *icd, return 0; } -/* - * Calculate real client output window by applying new scales to the current - * client crop. New scales are calculated from the requested output format and - * CEU crop, mapped backed onto the client input (subrect). - */ -static void calculate_client_output(struct soc_camera_device *icd, - const struct v4l2_pix_format *pix, struct v4l2_mbus_framefmt *mf) -{ - struct sh_mobile_ceu_cam *cam = icd->host_priv; - struct device *dev = icd->parent; - struct v4l2_rect *cam_subrect = &cam->subrect; - unsigned int scale_v, scale_h; - - if (cam_subrect->width == cam->rect.width && - cam_subrect->height == cam->rect.height) { - /* No sub-cropping */ - mf->width = pix->width; - mf->height = pix->height; - return; - } - - /* 1.-2. Current camera scales and subwin - cached. */ - - dev_geo(dev, "2: subwin %ux%u@%u:%u\n", - cam_subrect->width, cam_subrect->height, - cam_subrect->left, cam_subrect->top); - - /* - * 3. Calculate new combined scales from input sub-window to requested - * user window. - */ - - /* - * TODO: CEU cannot scale images larger than VGA to smaller than SubQCIF - * (128x96) or larger than VGA - */ - scale_h = calc_generic_scale(cam_subrect->width, pix->width); - scale_v = calc_generic_scale(cam_subrect->height, pix->height); - - dev_geo(dev, "3: scales %u:%u\n", scale_h, scale_v); - - /* - * 4. Calculate desired client output window by applying combined scales - * to client (real) input window. - */ - mf->width = scale_down(cam->rect.width, scale_h); - mf->height = scale_down(cam->rect.height, scale_v); -} - /* Similar to set_crop multistage iterative algorithm */ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, struct v4l2_format *f) @@ -1727,8 +1365,8 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, struct v4l2_mbus_framefmt mf; __u32 pixfmt = pix->pixelformat; const struct soc_camera_format_xlate *xlate; - /* Keep Compiler Happy */ - unsigned int ceu_sub_width = 0, ceu_sub_height = 0; + unsigned int ceu_sub_width = pcdev->max_width, + ceu_sub_height = pcdev->max_height; u16 scale_v, scale_h; int ret; bool image_mode; @@ -1755,7 +1393,7 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, } /* 1.-4. Calculate desired client output geometry */ - calculate_client_output(icd, pix, &mf); + soc_camera_calc_client_output(icd, &cam->rect, &cam->subrect, pix, &mf, 12); mf.field = pix->field; mf.colorspace = pix->colorspace; mf.code = xlate->code; @@ -1777,8 +1415,9 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, dev_geo(dev, "4: request camera output %ux%u\n", mf.width, mf.height); /* 5. - 9. */ - ret = client_scale(icd, &mf, &ceu_sub_width, &ceu_sub_height, - image_mode && V4L2_FIELD_NONE == field); + ret = soc_camera_client_scale(icd, &cam->rect, &cam->subrect, + &mf, &ceu_sub_width, &ceu_sub_height, + image_mode && V4L2_FIELD_NONE == field, 12); dev_geo(dev, "5-9: client scale return %d\n", ret); @@ -2036,6 +1675,8 @@ static struct soc_camera_host_ops sh_mobile_ceu_host_ops = { .owner = THIS_MODULE, .add = sh_mobile_ceu_add_device, .remove = sh_mobile_ceu_remove_device, + .clock_start = sh_mobile_ceu_clock_start, + .clock_stop = sh_mobile_ceu_clock_stop, .get_formats = sh_mobile_ceu_get_formats, .put_formats = sh_mobile_ceu_put_formats, .get_crop = sh_mobile_ceu_get_crop, @@ -2079,7 +1720,7 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev) struct resource *res; void __iomem *base; unsigned int irq; - int err = 0; + int err, i; struct bus_wait wait = { .completion = COMPLETION_INITIALIZER_ONSTACK(wait.completion), .notifier.notifier_call = bus_notify, @@ -2104,13 +1745,36 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev) init_completion(&pcdev->complete); pcdev->pdata = pdev->dev.platform_data; - if (!pcdev->pdata) { + if (!pcdev->pdata && !pdev->dev.of_node) { dev_err(&pdev->dev, "CEU platform data not set.\n"); return -EINVAL; } - pcdev->max_width = pcdev->pdata->max_width ? : 2560; - pcdev->max_height = pcdev->pdata->max_height ? : 1920; + /* TODO: implement per-device bus flags */ + if (pcdev->pdata) { + pcdev->max_width = pcdev->pdata->max_width; + pcdev->max_height = pcdev->pdata->max_height; + pcdev->flags = pcdev->pdata->flags; + } + + if (!pcdev->max_width) { + unsigned int v; + err = of_property_read_u32(pdev->dev.of_node, "renesas,max-width", &v); + if (!err) + pcdev->max_width = v; + + if (!pcdev->max_width) + pcdev->max_width = 2560; + } + if (!pcdev->max_height) { + unsigned int v; + err = of_property_read_u32(pdev->dev.of_node, "renesas,max-height", &v); + if (!err) + pcdev->max_height = v; + + if (!pcdev->max_height) + pcdev->max_height = 1920; + } base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(base)) @@ -2160,31 +1824,60 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev) goto exit_free_clk; } - err = soc_camera_host_register(&pcdev->ici); - if (err) - goto exit_free_ctx; + if (pcdev->pdata && pcdev->pdata->asd_sizes) { + struct v4l2_async_subdev **asd; + char name[] = "sh-mobile-csi2"; + int j; + + /* + * CSI2 interfacing: several groups can use CSI2, pick up the + * first one + */ + asd = pcdev->pdata->asd; + for (j = 0; pcdev->pdata->asd_sizes[j]; j++) { + for (i = 0; i < pcdev->pdata->asd_sizes[j]; i++, asd++) { + dev_dbg(&pdev->dev, "%s(): subdev #%d, type %u\n", + __func__, i, (*asd)->bus_type); + if ((*asd)->bus_type == V4L2_ASYNC_BUS_PLATFORM && + !strncmp(name, (*asd)->match.platform.name, + sizeof(name) - 1)) { + pcdev->csi2_asd = *asd; + break; + } + } + if (pcdev->csi2_asd) + break; + } - /* CSI2 interfacing */ - csi2 = pcdev->pdata->csi2; + pcdev->ici.asd = pcdev->pdata->asd; + pcdev->ici.asd_sizes = pcdev->pdata->asd_sizes; + } + + /* Legacy CSI2 interfacing */ + csi2 = pcdev->pdata ? pcdev->pdata->csi2 : NULL; if (csi2) { + /* + * TODO: remove this once all users are converted to + * asynchronous CSI2 probing. If it has to be kept, csi2 + * platform device resources have to be added, using + * platform_device_add_resources() + */ struct platform_device *csi2_pdev = platform_device_alloc("sh-mobile-csi2", csi2->id); struct sh_csi2_pdata *csi2_pdata = csi2->platform_data; if (!csi2_pdev) { err = -ENOMEM; - goto exit_host_unregister; + goto exit_free_ctx; } pcdev->csi2_pdev = csi2_pdev; - err = platform_device_add_data(csi2_pdev, csi2_pdata, sizeof(*csi2_pdata)); + err = platform_device_add_data(csi2_pdev, csi2_pdata, + sizeof(*csi2_pdata)); if (err < 0) goto exit_pdev_put; - csi2_pdata = csi2_pdev->dev.platform_data; - csi2_pdata->v4l2_dev = &pcdev->ici.v4l2_dev; - csi2_pdev->resource = csi2->resource; csi2_pdev->num_resources = csi2->num_resources; @@ -2226,17 +1919,38 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev) err = -ENODEV; goto exit_pdev_unregister; } + + pcdev->csi2_sd = platform_get_drvdata(csi2_pdev); + } + + err = soc_camera_host_register(&pcdev->ici); + if (err) + goto exit_csi2_unregister; + + if (csi2) { + err = v4l2_device_register_subdev(&pcdev->ici.v4l2_dev, + pcdev->csi2_sd); + dev_dbg(&pdev->dev, "%s(): ret(register_subdev) = %d\n", + __func__, err); + if (err < 0) + goto exit_host_unregister; + /* v4l2_device_register_subdev() took a reference too */ + module_put(pcdev->csi2_sd->owner); } return 0; -exit_pdev_unregister: - platform_device_del(pcdev->csi2_pdev); -exit_pdev_put: - pcdev->csi2_pdev->resource = NULL; - platform_device_put(pcdev->csi2_pdev); exit_host_unregister: soc_camera_host_unregister(&pcdev->ici); +exit_csi2_unregister: + if (csi2) { + module_put(pcdev->csi2_pdev->dev.driver->owner); +exit_pdev_unregister: + platform_device_del(pcdev->csi2_pdev); +exit_pdev_put: + pcdev->csi2_pdev->resource = NULL; + platform_device_put(pcdev->csi2_pdev); + } exit_free_ctx: vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); exit_free_clk: @@ -2287,10 +2001,18 @@ static const struct dev_pm_ops sh_mobile_ceu_dev_pm_ops = { .runtime_resume = sh_mobile_ceu_runtime_nop, }; +static const struct of_device_id sh_mobile_ceu_of_match[] = { + { .compatible = "renesas,sh-mobile-ceu" }, + { } +}; +MODULE_DEVICE_TABLE(of, sh_mobile_ceu_of_match); + static struct platform_driver sh_mobile_ceu_driver = { .driver = { .name = "sh_mobile_ceu", + .owner = THIS_MODULE, .pm = &sh_mobile_ceu_dev_pm_ops, + .of_match_table = sh_mobile_ceu_of_match, }, .probe = sh_mobile_ceu_probe, .remove = sh_mobile_ceu_remove, @@ -2314,5 +2036,5 @@ module_exit(sh_mobile_ceu_exit); MODULE_DESCRIPTION("SuperH Mobile CEU driver"); MODULE_AUTHOR("Magnus Damm"); MODULE_LICENSE("GPL"); -MODULE_VERSION("0.0.6"); +MODULE_VERSION("0.1.0"); MODULE_ALIAS("platform:sh_mobile_ceu"); diff --git a/drivers/media/platform/soc_camera/sh_mobile_csi2.c b/drivers/media/platform/soc_camera/sh_mobile_csi2.c index 09cb4fc88f34..05dd21a35d63 100644 --- a/drivers/media/platform/soc_camera/sh_mobile_csi2.c +++ b/drivers/media/platform/soc_camera/sh_mobile_csi2.c @@ -36,7 +36,6 @@ struct sh_csi2 { struct v4l2_subdev subdev; - struct list_head list; unsigned int irq; unsigned long mipi_flags; void __iomem *base; @@ -44,6 +43,8 @@ struct sh_csi2 { struct sh_csi2_client_config *client; }; +static void sh_csi2_hwinit(struct sh_csi2 *priv); + static int sh_csi2_try_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf) { @@ -132,10 +133,58 @@ static int sh_csi2_s_fmt(struct v4l2_subdev *sd, static int sh_csi2_g_mbus_config(struct v4l2_subdev *sd, struct v4l2_mbus_config *cfg) { - cfg->flags = V4L2_MBUS_PCLK_SAMPLE_RISING | - V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_HIGH | - V4L2_MBUS_MASTER | V4L2_MBUS_DATA_ACTIVE_HIGH; - cfg->type = V4L2_MBUS_PARALLEL; + struct sh_csi2 *priv = container_of(sd, struct sh_csi2, subdev); + + if (!priv->mipi_flags) { + struct soc_camera_device *icd = v4l2_get_subdev_hostdata(sd); + struct v4l2_subdev *client_sd = soc_camera_to_subdev(icd); + struct sh_csi2_pdata *pdata = priv->pdev->dev.platform_data; + unsigned long common_flags, csi2_flags; + struct v4l2_mbus_config client_cfg = {.type = V4L2_MBUS_CSI2,}; + int ret; + + /* Check if we can support this camera */ + csi2_flags = V4L2_MBUS_CSI2_CONTINUOUS_CLOCK | + V4L2_MBUS_CSI2_1_LANE; + + switch (pdata->type) { + case SH_CSI2C: + if (priv->client->lanes != 1) + csi2_flags |= V4L2_MBUS_CSI2_2_LANE; + break; + case SH_CSI2I: + switch (priv->client->lanes) { + default: + csi2_flags |= V4L2_MBUS_CSI2_4_LANE; + case 3: + csi2_flags |= V4L2_MBUS_CSI2_3_LANE; + case 2: + csi2_flags |= V4L2_MBUS_CSI2_2_LANE; + } + } + + ret = v4l2_subdev_call(client_sd, video, g_mbus_config, &client_cfg); + if (ret == -ENOIOCTLCMD) + common_flags = csi2_flags; + else if (!ret) + common_flags = soc_mbus_config_compatible(&client_cfg, + csi2_flags); + else + common_flags = 0; + + if (!common_flags) + return -EINVAL; + + /* All good: camera MIPI configuration supported */ + priv->mipi_flags = common_flags; + } + + if (cfg) { + cfg->flags = V4L2_MBUS_PCLK_SAMPLE_RISING | + V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_HIGH | + V4L2_MBUS_MASTER | V4L2_MBUS_DATA_ACTIVE_HIGH; + cfg->type = V4L2_MBUS_PARALLEL; + } return 0; } @@ -146,8 +195,17 @@ static int sh_csi2_s_mbus_config(struct v4l2_subdev *sd, struct sh_csi2 *priv = container_of(sd, struct sh_csi2, subdev); struct soc_camera_device *icd = v4l2_get_subdev_hostdata(sd); struct v4l2_subdev *client_sd = soc_camera_to_subdev(icd); - struct v4l2_mbus_config client_cfg = {.type = V4L2_MBUS_CSI2, - .flags = priv->mipi_flags}; + struct v4l2_mbus_config client_cfg = {.type = V4L2_MBUS_CSI2,}; + int ret = sh_csi2_g_mbus_config(sd, NULL); + + if (ret < 0) + return ret; + + pm_runtime_get_sync(&priv->pdev->dev); + + sh_csi2_hwinit(priv); + + client_cfg.flags = priv->mipi_flags; return v4l2_subdev_call(client_sd, video, s_mbus_config, &client_cfg); } @@ -202,19 +260,19 @@ static void sh_csi2_hwinit(struct sh_csi2 *priv) static int sh_csi2_client_connect(struct sh_csi2 *priv) { - struct sh_csi2_pdata *pdata = priv->pdev->dev.platform_data; - struct soc_camera_device *icd = v4l2_get_subdev_hostdata(&priv->subdev); - struct v4l2_subdev *client_sd = soc_camera_to_subdev(icd); struct device *dev = v4l2_get_subdevdata(&priv->subdev); - struct v4l2_mbus_config cfg; - unsigned long common_flags, csi2_flags; - int i, ret; + struct sh_csi2_pdata *pdata = dev->platform_data; + struct soc_camera_device *icd = v4l2_get_subdev_hostdata(&priv->subdev); + int i; if (priv->client) return -EBUSY; for (i = 0; i < pdata->num_clients; i++) - if (&pdata->clients[i].pdev->dev == icd->pdev) + if ((pdata->clients[i].pdev && + &pdata->clients[i].pdev->dev == icd->pdev) || + (icd->control && + strcmp(pdata->clients[i].name, dev_name(icd->control)))) break; dev_dbg(dev, "%s(%p): found #%d\n", __func__, dev, i); @@ -222,46 +280,8 @@ static int sh_csi2_client_connect(struct sh_csi2 *priv) if (i == pdata->num_clients) return -ENODEV; - /* Check if we can support this camera */ - csi2_flags = V4L2_MBUS_CSI2_CONTINUOUS_CLOCK | V4L2_MBUS_CSI2_1_LANE; - - switch (pdata->type) { - case SH_CSI2C: - if (pdata->clients[i].lanes != 1) - csi2_flags |= V4L2_MBUS_CSI2_2_LANE; - break; - case SH_CSI2I: - switch (pdata->clients[i].lanes) { - default: - csi2_flags |= V4L2_MBUS_CSI2_4_LANE; - case 3: - csi2_flags |= V4L2_MBUS_CSI2_3_LANE; - case 2: - csi2_flags |= V4L2_MBUS_CSI2_2_LANE; - } - } - - cfg.type = V4L2_MBUS_CSI2; - ret = v4l2_subdev_call(client_sd, video, g_mbus_config, &cfg); - if (ret == -ENOIOCTLCMD) - common_flags = csi2_flags; - else if (!ret) - common_flags = soc_mbus_config_compatible(&cfg, - csi2_flags); - else - common_flags = 0; - - if (!common_flags) - return -EINVAL; - - /* All good: camera MIPI configuration supported */ - priv->mipi_flags = common_flags; priv->client = pdata->clients + i; - pm_runtime_get_sync(dev); - - sh_csi2_hwinit(priv); - return 0; } @@ -304,11 +324,18 @@ static int sh_csi2_probe(struct platform_device *pdev) /* Platform data specify the PHY, lanes, ECC, CRC */ struct sh_csi2_pdata *pdata = pdev->dev.platform_data; + if (!pdata) + return -EINVAL; + + priv = devm_kzalloc(&pdev->dev, sizeof(struct sh_csi2), GFP_KERNEL); + if (!priv) + return -ENOMEM; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); /* Interrupt unused so far */ irq = platform_get_irq(pdev, 0); - if (!res || (int)irq <= 0 || !pdata) { + if (!res || (int)irq <= 0) { dev_err(&pdev->dev, "Not enough CSI2 platform resources.\n"); return -ENODEV; } @@ -319,10 +346,6 @@ static int sh_csi2_probe(struct platform_device *pdev) return -EINVAL; } - priv = devm_kzalloc(&pdev->dev, sizeof(struct sh_csi2), GFP_KERNEL); - if (!priv) - return -ENOMEM; - priv->irq = irq; priv->base = devm_ioremap_resource(&pdev->dev, res); @@ -330,37 +353,35 @@ static int sh_csi2_probe(struct platform_device *pdev) return PTR_ERR(priv->base); priv->pdev = pdev; - platform_set_drvdata(pdev, priv); + priv->subdev.owner = THIS_MODULE; + priv->subdev.dev = &pdev->dev; + platform_set_drvdata(pdev, &priv->subdev); v4l2_subdev_init(&priv->subdev, &sh_csi2_subdev_ops); v4l2_set_subdevdata(&priv->subdev, &pdev->dev); snprintf(priv->subdev.name, V4L2_SUBDEV_NAME_SIZE, "%s.mipi-csi", - dev_name(pdata->v4l2_dev->dev)); - ret = v4l2_device_register_subdev(pdata->v4l2_dev, &priv->subdev); - dev_dbg(&pdev->dev, "%s(%p): ret(register_subdev) = %d\n", __func__, priv, ret); + dev_name(&pdev->dev)); + + ret = v4l2_async_register_subdev(&priv->subdev); if (ret < 0) - goto esdreg; + return ret; pm_runtime_enable(&pdev->dev); dev_dbg(&pdev->dev, "CSI2 probed.\n"); return 0; - -esdreg: - platform_set_drvdata(pdev, NULL); - - return ret; } static int sh_csi2_remove(struct platform_device *pdev) { - struct sh_csi2 *priv = platform_get_drvdata(pdev); + struct v4l2_subdev *subdev = platform_get_drvdata(pdev); + struct sh_csi2 *priv = container_of(subdev, struct sh_csi2, subdev); - v4l2_device_unregister_subdev(&priv->subdev); + v4l2_async_unregister_subdev(&priv->subdev); + v4l2_device_unregister_subdev(subdev); pm_runtime_disable(&pdev->dev); - platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c index 3a4efbdc7668..2dd0e5272941 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c @@ -21,21 +21,23 @@ #include <linux/i2c.h> #include <linux/init.h> #include <linux/list.h> -#include <linux/mutex.h> #include <linux/module.h> +#include <linux/mutex.h> #include <linux/platform_device.h> +#include <linux/pm_runtime.h> #include <linux/regulator/consumer.h> #include <linux/slab.h> -#include <linux/pm_runtime.h> #include <linux/vmalloc.h> #include <media/soc_camera.h> +#include <media/soc_mediabus.h> +#include <media/v4l2-async.h> +#include <media/v4l2-clk.h> #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-dev.h> #include <media/videobuf-core.h> #include <media/videobuf2-core.h> -#include <media/soc_mediabus.h> /* Default to VGA resolution */ #define DEFAULT_WIDTH 640 @@ -46,17 +48,39 @@ (icd)->vb_vidq.streaming : \ vb2_is_streaming(&(icd)->vb2_vidq)) +#define MAP_MAX_NUM 32 +static DECLARE_BITMAP(device_map, MAP_MAX_NUM); static LIST_HEAD(hosts); static LIST_HEAD(devices); -static DEFINE_MUTEX(list_lock); /* Protects the list of hosts */ +/* + * Protects lists and bitmaps of hosts and devices. + * Lock nesting: Ok to take ->host_lock under list_lock. + */ +static DEFINE_MUTEX(list_lock); + +struct soc_camera_async_client { + struct v4l2_async_subdev *sensor; + struct v4l2_async_notifier notifier; + struct platform_device *pdev; + struct list_head list; /* needed for clean up */ +}; + +static int soc_camera_video_start(struct soc_camera_device *icd); +static int video_dev_create(struct soc_camera_device *icd); -int soc_camera_power_on(struct device *dev, struct soc_camera_subdev_desc *ssdd) +int soc_camera_power_on(struct device *dev, struct soc_camera_subdev_desc *ssdd, + struct v4l2_clk *clk) { - int ret = regulator_bulk_enable(ssdd->num_regulators, + int ret = clk ? v4l2_clk_enable(clk) : 0; + if (ret < 0) { + dev_err(dev, "Cannot enable clock: %d\n", ret); + return ret; + } + ret = regulator_bulk_enable(ssdd->num_regulators, ssdd->regulators); if (ret < 0) { dev_err(dev, "Cannot enable regulators\n"); - return ret; + goto eregenable; } if (ssdd->power) { @@ -64,16 +88,25 @@ int soc_camera_power_on(struct device *dev, struct soc_camera_subdev_desc *ssdd) if (ret < 0) { dev_err(dev, "Platform failed to power-on the camera.\n"); - regulator_bulk_disable(ssdd->num_regulators, - ssdd->regulators); + goto epwron; } } + return 0; + +epwron: + regulator_bulk_disable(ssdd->num_regulators, + ssdd->regulators); +eregenable: + if (clk) + v4l2_clk_disable(clk); + return ret; } EXPORT_SYMBOL(soc_camera_power_on); -int soc_camera_power_off(struct device *dev, struct soc_camera_subdev_desc *ssdd) +int soc_camera_power_off(struct device *dev, struct soc_camera_subdev_desc *ssdd, + struct v4l2_clk *clk) { int ret = 0; int err; @@ -94,10 +127,21 @@ int soc_camera_power_off(struct device *dev, struct soc_camera_subdev_desc *ssdd ret = ret ? : err; } + if (clk) + v4l2_clk_disable(clk); + return ret; } EXPORT_SYMBOL(soc_camera_power_off); +int soc_camera_power_init(struct device *dev, struct soc_camera_subdev_desc *ssdd) +{ + + return devm_regulator_bulk_get(dev, ssdd->num_regulators, + ssdd->regulators); +} +EXPORT_SYMBOL(soc_camera_power_init); + static int __soc_camera_power_on(struct soc_camera_device *icd) { struct v4l2_subdev *sd = soc_camera_to_subdev(icd); @@ -235,7 +279,6 @@ static int soc_camera_enum_input(struct file *file, void *priv, /* default is camera */ inp->type = V4L2_INPUT_TYPE_CAMERA; - inp->std = V4L2_STD_UNKNOWN; strcpy(inp->name, "Camera"); return 0; @@ -505,6 +548,58 @@ static int soc_camera_set_fmt(struct soc_camera_device *icd, return ici->ops->set_bus_param(icd); } +static int soc_camera_add_device(struct soc_camera_device *icd) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + int ret; + + if (ici->icd) + return -EBUSY; + + if (!icd->clk) { + mutex_lock(&ici->clk_lock); + ret = ici->ops->clock_start(ici); + mutex_unlock(&ici->clk_lock); + if (ret < 0) + return ret; + } + + if (ici->ops->add) { + ret = ici->ops->add(icd); + if (ret < 0) + goto eadd; + } + + ici->icd = icd; + + return 0; + +eadd: + if (!icd->clk) { + mutex_lock(&ici->clk_lock); + ici->ops->clock_stop(ici); + mutex_unlock(&ici->clk_lock); + } + return ret; +} + +static void soc_camera_remove_device(struct soc_camera_device *icd) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + + if (WARN_ON(icd != ici->icd)) + return; + + if (ici->ops->remove) + ici->ops->remove(icd); + if (!icd->clk) { + mutex_lock(&ici->clk_lock); + ici->ops->clock_stop(ici); + mutex_unlock(&ici->clk_lock); + } + ici->icd = NULL; +} + static int soc_camera_open(struct file *file) { struct video_device *vdev = video_devdata(file); @@ -525,7 +620,7 @@ static int soc_camera_open(struct file *file) return -ENODEV; } - icd = dev_get_drvdata(vdev->parent); + icd = video_get_drvdata(vdev); ici = to_soc_camera_host(icd->parent); ret = try_module_get(ici->ops->owner) ? 0 : -ENODEV; @@ -568,7 +663,7 @@ static int soc_camera_open(struct file *file) if (sdesc->subdev_desc.reset) sdesc->subdev_desc.reset(icd->pdev); - ret = ici->ops->add(icd); + ret = soc_camera_add_device(icd); if (ret < 0) { dev_err(icd->pdev, "Couldn't activate the camera: %d\n", ret); goto eiciadd; @@ -610,8 +705,8 @@ static int soc_camera_open(struct file *file) return 0; /* - * First four errors are entered with the .host_lock held - * and use_count == 1 + * All errors are entered with the .host_lock held, first four also + * with use_count == 1 */ einitvb: esfmt: @@ -619,7 +714,7 @@ esfmt: eresume: __soc_camera_power_off(icd); epower: - ici->ops->remove(icd); + soc_camera_remove_device(icd); eiciadd: icd->use_count--; mutex_unlock(&ici->host_lock); @@ -645,7 +740,7 @@ static int soc_camera_close(struct file *file) vb2_queue_release(&icd->vb2_vidq); __soc_camera_power_off(icd); - ici->ops->remove(icd); + soc_camera_remove_device(icd); } if (icd->streamer == file) @@ -1036,76 +1131,225 @@ static int soc_camera_s_parm(struct file *file, void *fh, return -ENOIOCTLCMD; } -static int soc_camera_g_chip_ident(struct file *file, void *fh, - struct v4l2_dbg_chip_ident *id) +static int soc_camera_probe(struct soc_camera_host *ici, + struct soc_camera_device *icd); + +/* So far this function cannot fail */ +static void scan_add_host(struct soc_camera_host *ici) { - struct soc_camera_device *icd = file->private_data; - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct soc_camera_device *icd; + + mutex_lock(&list_lock); + + list_for_each_entry(icd, &devices, list) + if (icd->iface == ici->nr) { + struct soc_camera_desc *sdesc = to_soc_camera_desc(icd); + struct soc_camera_subdev_desc *ssdd = &sdesc->subdev_desc; + + /* The camera could have been already on, try to reset */ + if (ssdd->reset) + ssdd->reset(icd->pdev); - return v4l2_subdev_call(sd, core, g_chip_ident, id); + icd->parent = ici->v4l2_dev.dev; + + /* Ignore errors */ + soc_camera_probe(ici, icd); + } + + mutex_unlock(&list_lock); } -#ifdef CONFIG_VIDEO_ADV_DEBUG -static int soc_camera_g_register(struct file *file, void *fh, - struct v4l2_dbg_register *reg) +/* + * It is invalid to call v4l2_clk_enable() after a successful probing + * asynchronously outside of V4L2 operations, i.e. with .host_lock not held. + */ +static int soc_camera_clk_enable(struct v4l2_clk *clk) { - struct soc_camera_device *icd = file->private_data; - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct soc_camera_device *icd = clk->priv; + struct soc_camera_host *ici; + int ret; + + if (!icd || !icd->parent) + return -ENODEV; + + ici = to_soc_camera_host(icd->parent); + + if (!try_module_get(ici->ops->owner)) + return -ENODEV; - return v4l2_subdev_call(sd, core, g_register, reg); + /* + * If a different client is currently being probed, the host will tell + * you to go + */ + mutex_lock(&ici->clk_lock); + ret = ici->ops->clock_start(ici); + mutex_unlock(&ici->clk_lock); + return ret; } -static int soc_camera_s_register(struct file *file, void *fh, - const struct v4l2_dbg_register *reg) +static void soc_camera_clk_disable(struct v4l2_clk *clk) { - struct soc_camera_device *icd = file->private_data; - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct soc_camera_device *icd = clk->priv; + struct soc_camera_host *ici; + + if (!icd || !icd->parent) + return; + + ici = to_soc_camera_host(icd->parent); + + mutex_lock(&ici->clk_lock); + ici->ops->clock_stop(ici); + mutex_unlock(&ici->clk_lock); - return v4l2_subdev_call(sd, core, s_register, reg); + module_put(ici->ops->owner); } -#endif -static int soc_camera_probe(struct soc_camera_device *icd); +/* + * Eventually, it would be more logical to make the respective host the clock + * owner, but then we would have to copy this struct for each ici. Besides, it + * would introduce the circular dependency problem, unless we port all client + * drivers to release the clock, when not in use. + */ +static const struct v4l2_clk_ops soc_camera_clk_ops = { + .owner = THIS_MODULE, + .enable = soc_camera_clk_enable, + .disable = soc_camera_clk_disable, +}; -/* So far this function cannot fail */ -static void scan_add_host(struct soc_camera_host *ici) +static int soc_camera_dyn_pdev(struct soc_camera_desc *sdesc, + struct soc_camera_async_client *sasc) { - struct soc_camera_device *icd; + struct platform_device *pdev; + int ret, i; mutex_lock(&list_lock); + i = find_first_zero_bit(device_map, MAP_MAX_NUM); + if (i < MAP_MAX_NUM) + set_bit(i, device_map); + mutex_unlock(&list_lock); + if (i >= MAP_MAX_NUM) + return -ENOMEM; - list_for_each_entry(icd, &devices, list) { - if (icd->iface == ici->nr) { - icd->parent = ici->v4l2_dev.dev; - soc_camera_probe(icd); - } + pdev = platform_device_alloc("soc-camera-pdrv", i); + if (!pdev) + return -ENOMEM; + + ret = platform_device_add_data(pdev, sdesc, sizeof(*sdesc)); + if (ret < 0) { + platform_device_put(pdev); + return ret; } - mutex_unlock(&list_lock); + sasc->pdev = pdev; + + return 0; +} + +static struct soc_camera_device *soc_camera_add_pdev(struct soc_camera_async_client *sasc) +{ + struct platform_device *pdev = sasc->pdev; + int ret; + + ret = platform_device_add(pdev); + if (ret < 0 || !pdev->dev.driver) + return NULL; + + return platform_get_drvdata(pdev); +} + +/* Locking: called with .host_lock held */ +static int soc_camera_probe_finish(struct soc_camera_device *icd) +{ + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct v4l2_mbus_framefmt mf; + int ret; + + sd->grp_id = soc_camera_grp_id(icd); + v4l2_set_subdev_hostdata(sd, icd); + + ret = v4l2_ctrl_add_handler(&icd->ctrl_handler, sd->ctrl_handler, NULL); + if (ret < 0) + return ret; + + ret = soc_camera_add_device(icd); + if (ret < 0) { + dev_err(icd->pdev, "Couldn't activate the camera: %d\n", ret); + return ret; + } + + /* At this point client .probe() should have run already */ + ret = soc_camera_init_user_formats(icd); + if (ret < 0) + goto eusrfmt; + + icd->field = V4L2_FIELD_ANY; + + ret = soc_camera_video_start(icd); + if (ret < 0) + goto evidstart; + + /* Try to improve our guess of a reasonable window format */ + if (!v4l2_subdev_call(sd, video, g_mbus_fmt, &mf)) { + icd->user_width = mf.width; + icd->user_height = mf.height; + icd->colorspace = mf.colorspace; + icd->field = mf.field; + } + soc_camera_remove_device(icd); + + return 0; + +evidstart: + soc_camera_free_user_formats(icd); +eusrfmt: + soc_camera_remove_device(icd); + + return ret; } #ifdef CONFIG_I2C_BOARDINFO -static int soc_camera_init_i2c(struct soc_camera_device *icd, +static int soc_camera_i2c_init(struct soc_camera_device *icd, struct soc_camera_desc *sdesc) { struct i2c_client *client; - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + struct soc_camera_host *ici; struct soc_camera_host_desc *shd = &sdesc->host_desc; - struct i2c_adapter *adap = i2c_get_adapter(shd->i2c_adapter_id); + struct i2c_adapter *adap; struct v4l2_subdev *subdev; + char clk_name[V4L2_SUBDEV_NAME_SIZE]; + int ret; + /* First find out how we link the main client */ + if (icd->sasc) { + /* Async non-OF probing handled by the subdevice list */ + return -EPROBE_DEFER; + } + + ici = to_soc_camera_host(icd->parent); + adap = i2c_get_adapter(shd->i2c_adapter_id); if (!adap) { dev_err(icd->pdev, "Cannot get I2C adapter #%d. No driver?\n", shd->i2c_adapter_id); - goto ei2cga; + return -ENODEV; } shd->board_info->platform_data = &sdesc->subdev_desc; + snprintf(clk_name, sizeof(clk_name), "%d-%04x", + shd->i2c_adapter_id, shd->board_info->addr); + + icd->clk = v4l2_clk_register(&soc_camera_clk_ops, clk_name, "mclk", icd); + if (IS_ERR(icd->clk)) { + ret = PTR_ERR(icd->clk); + goto eclkreg; + } + subdev = v4l2_i2c_new_subdev_board(&ici->v4l2_dev, adap, shd->board_info, NULL); - if (!subdev) + if (!subdev) { + ret = -ENODEV; goto ei2cnd; + } client = v4l2_get_subdevdata(subdev); @@ -1114,39 +1358,203 @@ static int soc_camera_init_i2c(struct soc_camera_device *icd, return 0; ei2cnd: + v4l2_clk_unregister(icd->clk); +eclkreg: + icd->clk = NULL; i2c_put_adapter(adap); -ei2cga: - return -ENODEV; + return ret; } -static void soc_camera_free_i2c(struct soc_camera_device *icd) +static void soc_camera_i2c_free(struct soc_camera_device *icd) { struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); - struct i2c_adapter *adap = client->adapter; + struct i2c_adapter *adap; icd->control = NULL; + if (icd->sasc) + return; + + adap = client->adapter; v4l2_device_unregister_subdev(i2c_get_clientdata(client)); i2c_unregister_device(client); i2c_put_adapter(adap); + v4l2_clk_unregister(icd->clk); + icd->clk = NULL; +} + +/* + * V4L2 asynchronous notifier callbacks. They are all called under a v4l2-async + * internal global mutex, therefore cannot race against other asynchronous + * events. Until notifier->complete() (soc_camera_async_complete()) is called, + * the video device node is not registered and no V4L fops can occur. Unloading + * of the host driver also calls a v4l2-async function, so also there we're + * protected. + */ +static int soc_camera_async_bound(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *sd, + struct v4l2_async_subdev *asd) +{ + struct soc_camera_async_client *sasc = container_of(notifier, + struct soc_camera_async_client, notifier); + struct soc_camera_device *icd = platform_get_drvdata(sasc->pdev); + + if (asd == sasc->sensor && !WARN_ON(icd->control)) { + struct i2c_client *client = v4l2_get_subdevdata(sd); + + /* + * Only now we get subdevice-specific information like + * regulators, flags, callbacks, etc. + */ + if (client) { + struct soc_camera_desc *sdesc = to_soc_camera_desc(icd); + struct soc_camera_subdev_desc *ssdd = + soc_camera_i2c_to_desc(client); + if (ssdd) { + memcpy(&sdesc->subdev_desc, ssdd, + sizeof(sdesc->subdev_desc)); + if (ssdd->reset) + ssdd->reset(icd->pdev); + } + + icd->control = &client->dev; + } + } + + return 0; +} + +static void soc_camera_async_unbind(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *sd, + struct v4l2_async_subdev *asd) +{ + struct soc_camera_async_client *sasc = container_of(notifier, + struct soc_camera_async_client, notifier); + struct soc_camera_device *icd = platform_get_drvdata(sasc->pdev); + + if (icd->clk) { + v4l2_clk_unregister(icd->clk); + icd->clk = NULL; + } +} + +static int soc_camera_async_complete(struct v4l2_async_notifier *notifier) +{ + struct soc_camera_async_client *sasc = container_of(notifier, + struct soc_camera_async_client, notifier); + struct soc_camera_device *icd = platform_get_drvdata(sasc->pdev); + + if (to_soc_camera_control(icd)) { + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + int ret; + + mutex_lock(&list_lock); + ret = soc_camera_probe(ici, icd); + mutex_unlock(&list_lock); + if (ret < 0) + return ret; + } + + return 0; +} + +static int scan_async_group(struct soc_camera_host *ici, + struct v4l2_async_subdev **asd, unsigned int size) +{ + struct soc_camera_async_subdev *sasd; + struct soc_camera_async_client *sasc; + struct soc_camera_device *icd; + struct soc_camera_desc sdesc = {.host_desc.bus_id = ici->nr,}; + char clk_name[V4L2_SUBDEV_NAME_SIZE]; + int ret, i; + + /* First look for a sensor */ + for (i = 0; i < size; i++) { + sasd = container_of(asd[i], struct soc_camera_async_subdev, asd); + if (sasd->role == SOCAM_SUBDEV_DATA_SOURCE) + break; + } + + if (i == size || asd[i]->bus_type != V4L2_ASYNC_BUS_I2C) { + /* All useless */ + dev_err(ici->v4l2_dev.dev, "No I2C data source found!\n"); + return -ENODEV; + } + + /* Or shall this be managed by the soc-camera device? */ + sasc = devm_kzalloc(ici->v4l2_dev.dev, sizeof(*sasc), GFP_KERNEL); + if (!sasc) + return -ENOMEM; + + /* HACK: just need a != NULL */ + sdesc.host_desc.board_info = ERR_PTR(-ENODATA); + + ret = soc_camera_dyn_pdev(&sdesc, sasc); + if (ret < 0) + return ret; + + sasc->sensor = &sasd->asd; + + icd = soc_camera_add_pdev(sasc); + if (!icd) { + platform_device_put(sasc->pdev); + return -ENOMEM; + } + + sasc->notifier.subdev = asd; + sasc->notifier.num_subdevs = size; + sasc->notifier.bound = soc_camera_async_bound; + sasc->notifier.unbind = soc_camera_async_unbind; + sasc->notifier.complete = soc_camera_async_complete; + + icd->sasc = sasc; + icd->parent = ici->v4l2_dev.dev; + + snprintf(clk_name, sizeof(clk_name), "%d-%04x", + sasd->asd.match.i2c.adapter_id, sasd->asd.match.i2c.address); + + icd->clk = v4l2_clk_register(&soc_camera_clk_ops, clk_name, "mclk", icd); + if (IS_ERR(icd->clk)) { + ret = PTR_ERR(icd->clk); + goto eclkreg; + } + + ret = v4l2_async_notifier_register(&ici->v4l2_dev, &sasc->notifier); + if (!ret) + return 0; + + v4l2_clk_unregister(icd->clk); +eclkreg: + icd->clk = NULL; + platform_device_unregister(sasc->pdev); + dev_err(ici->v4l2_dev.dev, "group probe failed: %d\n", ret); + + return ret; +} + +static void scan_async_host(struct soc_camera_host *ici) +{ + struct v4l2_async_subdev **asd; + int j; + + for (j = 0, asd = ici->asd; ici->asd_sizes[j]; j++) { + scan_async_group(ici, asd, ici->asd_sizes[j]); + asd += ici->asd_sizes[j]; + } } #else -#define soc_camera_init_i2c(icd, sdesc) (-ENODEV) -#define soc_camera_free_i2c(icd) do {} while (0) +#define soc_camera_i2c_init(icd, sdesc) (-ENODEV) +#define soc_camera_i2c_free(icd) do {} while (0) +#define scan_async_host(ici) do {} while (0) #endif -static int soc_camera_video_start(struct soc_camera_device *icd); -static int video_dev_create(struct soc_camera_device *icd); /* Called during host-driver probe */ -static int soc_camera_probe(struct soc_camera_device *icd) +static int soc_camera_probe(struct soc_camera_host *ici, + struct soc_camera_device *icd) { - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct soc_camera_desc *sdesc = to_soc_camera_desc(icd); struct soc_camera_host_desc *shd = &sdesc->host_desc; - struct soc_camera_subdev_desc *ssdd = &sdesc->subdev_desc; struct device *control = NULL; - struct v4l2_subdev *sd; - struct v4l2_mbus_framefmt mf; int ret; dev_info(icd->pdev, "Probing %s\n", dev_name(icd->pdev)); @@ -1162,30 +1570,32 @@ static int soc_camera_probe(struct soc_camera_device *icd) if (ret < 0) return ret; - /* The camera could have been already on, try to reset */ - if (ssdd->reset) - ssdd->reset(icd->pdev); - - mutex_lock(&ici->host_lock); - ret = ici->ops->add(icd); - mutex_unlock(&ici->host_lock); - if (ret < 0) - goto eadd; - /* Must have icd->vdev before registering the device */ ret = video_dev_create(icd); if (ret < 0) goto evdc; + /* + * ..._video_start() will create a device node, video_register_device() + * itself is protected against concurrent open() calls, but we also have + * to protect our data also during client probing. + */ + /* Non-i2c cameras, e.g., soc_camera_platform, have no board_info */ if (shd->board_info) { - ret = soc_camera_init_i2c(icd, sdesc); - if (ret < 0) - goto eadddev; + ret = soc_camera_i2c_init(icd, sdesc); + if (ret < 0 && ret != -EPROBE_DEFER) + goto eadd; } else if (!shd->add_device || !shd->del_device) { ret = -EINVAL; - goto eadddev; + goto eadd; } else { + mutex_lock(&ici->clk_lock); + ret = ici->ops->clock_start(ici); + mutex_unlock(&ici->clk_lock); + if (ret < 0) + goto eadd; + if (shd->module_name) ret = request_module(shd->module_name); @@ -1206,81 +1616,49 @@ static int soc_camera_probe(struct soc_camera_device *icd) } } - sd = soc_camera_to_subdev(icd); - sd->grp_id = soc_camera_grp_id(icd); - v4l2_set_subdev_hostdata(sd, icd); - - ret = v4l2_ctrl_add_handler(&icd->ctrl_handler, sd->ctrl_handler, NULL); - if (ret < 0) - goto ectrl; - - /* At this point client .probe() should have run already */ - ret = soc_camera_init_user_formats(icd); - if (ret < 0) - goto eiufmt; - - icd->field = V4L2_FIELD_ANY; - - /* - * ..._video_start() will create a device node, video_register_device() - * itself is protected against concurrent open() calls, but we also have - * to protect our data. - */ mutex_lock(&ici->host_lock); - - ret = soc_camera_video_start(icd); - if (ret < 0) - goto evidstart; - - /* Try to improve our guess of a reasonable window format */ - if (!v4l2_subdev_call(sd, video, g_mbus_fmt, &mf)) { - icd->user_width = mf.width; - icd->user_height = mf.height; - icd->colorspace = mf.colorspace; - icd->field = mf.field; - } - - ici->ops->remove(icd); - + ret = soc_camera_probe_finish(icd); mutex_unlock(&ici->host_lock); + if (ret < 0) + goto efinish; return 0; -evidstart: - mutex_unlock(&ici->host_lock); - soc_camera_free_user_formats(icd); -eiufmt: -ectrl: +efinish: if (shd->board_info) { - soc_camera_free_i2c(icd); + soc_camera_i2c_free(icd); } else { shd->del_device(icd); module_put(control->driver->owner); - } enodrv: eadddev: + mutex_lock(&ici->clk_lock); + ici->ops->clock_stop(ici); + mutex_unlock(&ici->clk_lock); + } +eadd: video_device_release(icd->vdev); icd->vdev = NULL; + if (icd->vdev) { + video_device_release(icd->vdev); + icd->vdev = NULL; + } evdc: - mutex_lock(&ici->host_lock); - ici->ops->remove(icd); - mutex_unlock(&ici->host_lock); -eadd: v4l2_ctrl_handler_free(&icd->ctrl_handler); return ret; } /* * This is called on device_unregister, which only means we have to disconnect - * from the host, but not remove ourselves from the device list + * from the host, but not remove ourselves from the device list. With + * asynchronous client probing this can also be called without + * soc_camera_probe_finish() having run. Careful with clean up. */ static int soc_camera_remove(struct soc_camera_device *icd) { struct soc_camera_desc *sdesc = to_soc_camera_desc(icd); struct video_device *vdev = icd->vdev; - BUG_ON(!icd->parent); - v4l2_ctrl_handler_free(&icd->ctrl_handler); if (vdev) { video_unregister_device(vdev); @@ -1288,15 +1666,27 @@ static int soc_camera_remove(struct soc_camera_device *icd) } if (sdesc->host_desc.board_info) { - soc_camera_free_i2c(icd); + soc_camera_i2c_free(icd); } else { - struct device_driver *drv = to_soc_camera_control(icd)->driver; + struct device *dev = to_soc_camera_control(icd); + struct device_driver *drv = dev ? dev->driver : NULL; if (drv) { sdesc->host_desc.del_device(icd); module_put(drv->owner); } } - soc_camera_free_user_formats(icd); + + if (icd->num_user_formats) + soc_camera_free_user_formats(icd); + + if (icd->clk) { + /* For the synchronous case */ + v4l2_clk_unregister(icd->clk); + icd->clk = NULL; + } + + if (icd->sasc) + platform_device_unregister(icd->sasc->pdev); return 0; } @@ -1372,8 +1762,8 @@ int soc_camera_host_register(struct soc_camera_host *ici) ((!ici->ops->init_videobuf || !ici->ops->reqbufs) && !ici->ops->init_videobuf2) || - !ici->ops->add || - !ici->ops->remove || + !ici->ops->clock_start || + !ici->ops->clock_stop || !ici->ops->poll || !ici->v4l2_dev.dev) return -EINVAL; @@ -1407,7 +1797,18 @@ int soc_camera_host_register(struct soc_camera_host *ici) mutex_unlock(&list_lock); mutex_init(&ici->host_lock); - scan_add_host(ici); + mutex_init(&ici->clk_lock); + + if (ici->asd_sizes) + /* + * No OF, host with a list of subdevices. Don't try to mix + * modes by initialising some groups statically and some + * dynamically! + */ + scan_async_host(ici); + else + /* Legacy: static platform devices from board data */ + scan_add_host(ici); return 0; @@ -1420,13 +1821,30 @@ EXPORT_SYMBOL(soc_camera_host_register); /* Unregister all clients! */ void soc_camera_host_unregister(struct soc_camera_host *ici) { - struct soc_camera_device *icd; + struct soc_camera_device *icd, *tmp; + struct soc_camera_async_client *sasc; + LIST_HEAD(notifiers); mutex_lock(&list_lock); - list_del(&ici->list); list_for_each_entry(icd, &devices, list) - if (icd->iface == ici->nr && to_soc_camera_control(icd)) + if (icd->iface == ici->nr && icd->sasc) { + /* as long as we hold the device, sasc won't be freed */ + get_device(icd->pdev); + list_add(&icd->sasc->list, ¬ifiers); + } + mutex_unlock(&list_lock); + + list_for_each_entry(sasc, ¬ifiers, list) { + /* Must call unlocked to avoid AB-BA dead-lock */ + v4l2_async_notifier_unregister(&sasc->notifier); + put_device(&sasc->pdev->dev); + } + + mutex_lock(&list_lock); + + list_for_each_entry_safe(icd, tmp, &devices, list) + if (icd->iface == ici->nr) soc_camera_remove(icd); mutex_unlock(&list_lock); @@ -1441,6 +1859,7 @@ static int soc_camera_device_register(struct soc_camera_device *icd) struct soc_camera_device *ix; int num = -1, i; + mutex_lock(&list_lock); for (i = 0; i < 256 && num < 0; i++) { num = i; /* Check if this index is available on this interface */ @@ -1452,18 +1871,34 @@ static int soc_camera_device_register(struct soc_camera_device *icd) } } - if (num < 0) + if (num < 0) { /* * ok, we have 256 cameras on this host... * man, stay reasonable... */ + mutex_unlock(&list_lock); return -ENOMEM; + } icd->devnum = num; icd->use_count = 0; icd->host_priv = NULL; + /* + * Dynamically allocated devices set the bit earlier, but it doesn't hurt setting + * it again + */ + i = to_platform_device(icd->pdev)->id; + if (i < 0) + /* One static (legacy) soc-camera platform device */ + i = 0; + if (i >= MAP_MAX_NUM) { + mutex_unlock(&list_lock); + return -EBUSY; + } + set_bit(i, device_map); list_add_tail(&icd->list, &devices); + mutex_unlock(&list_lock); return 0; } @@ -1495,11 +1930,6 @@ static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = { .vidioc_s_selection = soc_camera_s_selection, .vidioc_g_parm = soc_camera_g_parm, .vidioc_s_parm = soc_camera_s_parm, - .vidioc_g_chip_ident = soc_camera_g_chip_ident, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = soc_camera_g_register, - .vidioc_s_register = soc_camera_s_register, -#endif }; static int video_dev_create(struct soc_camera_device *icd) @@ -1512,12 +1942,10 @@ static int video_dev_create(struct soc_camera_device *icd) strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name)); - vdev->parent = icd->pdev; - vdev->current_norm = V4L2_STD_UNKNOWN; + vdev->v4l2_dev = &ici->v4l2_dev; vdev->fops = &soc_camera_fops; vdev->ioctl_ops = &soc_camera_ioctl_ops; vdev->release = video_device_release; - vdev->tvnorms = V4L2_STD_UNKNOWN; vdev->ctrl_handler = &icd->ctrl_handler; vdev->lock = &ici->host_lock; @@ -1537,6 +1965,7 @@ static int soc_camera_video_start(struct soc_camera_device *icd) if (!icd->parent) return -ENODEV; + video_set_drvdata(icd->vdev, icd); ret = video_register_device(icd->vdev, VFL_TYPE_GRABBER, -1); if (ret < 0) { dev_err(icd->pdev, "video_register_device failed: %d\n", ret); @@ -1563,6 +1992,12 @@ static int soc_camera_pdrv_probe(struct platform_device *pdev) if (!icd) return -ENOMEM; + /* + * In the asynchronous case ssdd->num_regulators == 0 yet, so, the below + * regulator allocation is a dummy. They will be really requested later + * in soc_camera_async_bind(). Also note, that in that case regulators + * are attached to the I2C device and not to the camera platform device. + */ ret = devm_regulator_bulk_get(&pdev->dev, ssdd->num_regulators, ssdd->regulators); if (ret < 0) @@ -1587,11 +2022,25 @@ static int soc_camera_pdrv_probe(struct platform_device *pdev) static int soc_camera_pdrv_remove(struct platform_device *pdev) { struct soc_camera_device *icd = platform_get_drvdata(pdev); + int i; if (!icd) return -EINVAL; - list_del(&icd->list); + i = pdev->id; + if (i < 0) + i = 0; + + /* + * In synchronous mode with static platform devices this is called in a + * loop from drivers/base/dd.c::driver_detach(), no parallel execution, + * no need to lock. In asynchronous case the caller - + * soc_camera_host_unregister() - already holds the lock + */ + if (test_bit(i, device_map)) { + clear_bit(i, device_map); + list_del(&icd->list); + } return 0; } diff --git a/drivers/media/platform/soc_camera/soc_camera_platform.c b/drivers/media/platform/soc_camera/soc_camera_platform.c index 1b7a88ca195b..ceaddfb85e49 100644 --- a/drivers/media/platform/soc_camera/soc_camera_platform.c +++ b/drivers/media/platform/soc_camera/soc_camera_platform.c @@ -54,7 +54,7 @@ static int soc_camera_platform_s_power(struct v4l2_subdev *sd, int on) { struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd); - return soc_camera_set_power(p->icd->control, &p->icd->sdesc->subdev_desc, on); + return soc_camera_set_power(p->icd->control, &p->icd->sdesc->subdev_desc, NULL, on); } static struct v4l2_subdev_core_ops platform_subdev_core_ops = { @@ -137,7 +137,6 @@ static int soc_camera_platform_probe(struct platform_device *pdev) struct soc_camera_platform_priv *priv; struct soc_camera_platform_info *p = pdev->dev.platform_data; struct soc_camera_device *icd; - int ret; if (!p) return -EINVAL; @@ -165,15 +164,7 @@ static int soc_camera_platform_probe(struct platform_device *pdev) v4l2_set_subdevdata(&priv->subdev, p); strncpy(priv->subdev.name, dev_name(&pdev->dev), V4L2_SUBDEV_NAME_SIZE); - ret = v4l2_device_register_subdev(&ici->v4l2_dev, &priv->subdev); - if (ret) - goto evdrs; - - return ret; - -evdrs: - platform_set_drvdata(pdev, NULL); - return ret; + return v4l2_device_register_subdev(&ici->v4l2_dev, &priv->subdev); } static int soc_camera_platform_remove(struct platform_device *pdev) @@ -183,7 +174,6 @@ static int soc_camera_platform_remove(struct platform_device *pdev) p->icd->control = NULL; v4l2_device_unregister_subdev(&priv->subdev); - platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/media/platform/soc_camera/soc_scale_crop.c b/drivers/media/platform/soc_camera/soc_scale_crop.c new file mode 100644 index 000000000000..cbd3a34f4f3f --- /dev/null +++ b/drivers/media/platform/soc_camera/soc_scale_crop.c @@ -0,0 +1,402 @@ +/* + * soc-camera generic scaling-cropping manipulation functions + * + * Copyright (C) 2013 Guennadi Liakhovetski <g.liakhovetski@gmx.de> + * + * 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/device.h> +#include <linux/module.h> + +#include <media/soc_camera.h> +#include <media/v4l2-common.h> + +#include "soc_scale_crop.h" + +#ifdef DEBUG_GEOMETRY +#define dev_geo dev_info +#else +#define dev_geo dev_dbg +#endif + +/* Check if any dimension of r1 is smaller than respective one of r2 */ +static bool is_smaller(const struct v4l2_rect *r1, const struct v4l2_rect *r2) +{ + return r1->width < r2->width || r1->height < r2->height; +} + +/* Check if r1 fails to cover r2 */ +static bool is_inside(const struct v4l2_rect *r1, const struct v4l2_rect *r2) +{ + return r1->left > r2->left || r1->top > r2->top || + r1->left + r1->width < r2->left + r2->width || + r1->top + r1->height < r2->top + r2->height; +} + +/* Get and store current client crop */ +int soc_camera_client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect) +{ + struct v4l2_crop crop; + struct v4l2_cropcap cap; + int ret; + + crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + ret = v4l2_subdev_call(sd, video, g_crop, &crop); + if (!ret) { + *rect = crop.c; + return ret; + } + + /* Camera driver doesn't support .g_crop(), assume default rectangle */ + cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + ret = v4l2_subdev_call(sd, video, cropcap, &cap); + if (!ret) + *rect = cap.defrect; + + return ret; +} +EXPORT_SYMBOL(soc_camera_client_g_rect); + +/* Client crop has changed, update our sub-rectangle to remain within the area */ +static void update_subrect(struct v4l2_rect *rect, struct v4l2_rect *subrect) +{ + if (rect->width < subrect->width) + subrect->width = rect->width; + + if (rect->height < subrect->height) + subrect->height = rect->height; + + if (rect->left > subrect->left) + subrect->left = rect->left; + else if (rect->left + rect->width > + subrect->left + subrect->width) + subrect->left = rect->left + rect->width - + subrect->width; + + if (rect->top > subrect->top) + subrect->top = rect->top; + else if (rect->top + rect->height > + subrect->top + subrect->height) + subrect->top = rect->top + rect->height - + subrect->height; +} + +/* + * The common for both scaling and cropping iterative approach is: + * 1. try if the client can produce exactly what requested by the user + * 2. if (1) failed, try to double the client image until we get one big enough + * 3. if (2) failed, try to request the maximum image + */ +int soc_camera_client_s_crop(struct v4l2_subdev *sd, + struct v4l2_crop *crop, struct v4l2_crop *cam_crop, + struct v4l2_rect *target_rect, struct v4l2_rect *subrect) +{ + struct v4l2_rect *rect = &crop->c, *cam_rect = &cam_crop->c; + struct device *dev = sd->v4l2_dev->dev; + struct v4l2_cropcap cap; + int ret; + unsigned int width, height; + + v4l2_subdev_call(sd, video, s_crop, crop); + ret = soc_camera_client_g_rect(sd, cam_rect); + if (ret < 0) + return ret; + + /* + * Now cam_crop contains the current camera input rectangle, and it must + * be within camera cropcap bounds + */ + if (!memcmp(rect, cam_rect, sizeof(*rect))) { + /* Even if camera S_CROP failed, but camera rectangle matches */ + dev_dbg(dev, "Camera S_CROP successful for %dx%d@%d:%d\n", + rect->width, rect->height, rect->left, rect->top); + *target_rect = *cam_rect; + return 0; + } + + /* Try to fix cropping, that camera hasn't managed to set */ + dev_geo(dev, "Fix camera S_CROP for %dx%d@%d:%d to %dx%d@%d:%d\n", + cam_rect->width, cam_rect->height, + cam_rect->left, cam_rect->top, + rect->width, rect->height, rect->left, rect->top); + + /* We need sensor maximum rectangle */ + ret = v4l2_subdev_call(sd, video, cropcap, &cap); + if (ret < 0) + return ret; + + /* Put user requested rectangle within sensor bounds */ + soc_camera_limit_side(&rect->left, &rect->width, cap.bounds.left, 2, + cap.bounds.width); + soc_camera_limit_side(&rect->top, &rect->height, cap.bounds.top, 4, + cap.bounds.height); + + /* + * Popular special case - some cameras can only handle fixed sizes like + * QVGA, VGA,... Take care to avoid infinite loop. + */ + width = max(cam_rect->width, 2); + height = max(cam_rect->height, 2); + + /* + * Loop as long as sensor is not covering the requested rectangle and + * is still within its bounds + */ + while (!ret && (is_smaller(cam_rect, rect) || + is_inside(cam_rect, rect)) && + (cap.bounds.width > width || cap.bounds.height > height)) { + + width *= 2; + height *= 2; + + cam_rect->width = width; + cam_rect->height = height; + + /* + * We do not know what capabilities the camera has to set up + * left and top borders. We could try to be smarter in iterating + * them, e.g., if camera current left is to the right of the + * target left, set it to the middle point between the current + * left and minimum left. But that would add too much + * complexity: we would have to iterate each border separately. + * Instead we just drop to the left and top bounds. + */ + if (cam_rect->left > rect->left) + cam_rect->left = cap.bounds.left; + + if (cam_rect->left + cam_rect->width < rect->left + rect->width) + cam_rect->width = rect->left + rect->width - + cam_rect->left; + + if (cam_rect->top > rect->top) + cam_rect->top = cap.bounds.top; + + if (cam_rect->top + cam_rect->height < rect->top + rect->height) + cam_rect->height = rect->top + rect->height - + cam_rect->top; + + v4l2_subdev_call(sd, video, s_crop, cam_crop); + ret = soc_camera_client_g_rect(sd, cam_rect); + dev_geo(dev, "Camera S_CROP %d for %dx%d@%d:%d\n", ret, + cam_rect->width, cam_rect->height, + cam_rect->left, cam_rect->top); + } + + /* S_CROP must not modify the rectangle */ + if (is_smaller(cam_rect, rect) || is_inside(cam_rect, rect)) { + /* + * The camera failed to configure a suitable cropping, + * we cannot use the current rectangle, set to max + */ + *cam_rect = cap.bounds; + v4l2_subdev_call(sd, video, s_crop, cam_crop); + ret = soc_camera_client_g_rect(sd, cam_rect); + dev_geo(dev, "Camera S_CROP %d for max %dx%d@%d:%d\n", ret, + cam_rect->width, cam_rect->height, + cam_rect->left, cam_rect->top); + } + + if (!ret) { + *target_rect = *cam_rect; + update_subrect(target_rect, subrect); + } + + return ret; +} +EXPORT_SYMBOL(soc_camera_client_s_crop); + +/* Iterative s_mbus_fmt, also updates cached client crop on success */ +static int client_s_fmt(struct soc_camera_device *icd, + struct v4l2_rect *rect, struct v4l2_rect *subrect, + unsigned int max_width, unsigned int max_height, + struct v4l2_mbus_framefmt *mf, bool host_can_scale) +{ + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct device *dev = icd->parent; + unsigned int width = mf->width, height = mf->height, tmp_w, tmp_h; + struct v4l2_cropcap cap; + bool host_1to1; + int ret; + + ret = v4l2_device_call_until_err(sd->v4l2_dev, + soc_camera_grp_id(icd), video, + s_mbus_fmt, mf); + if (ret < 0) + return ret; + + dev_geo(dev, "camera scaled to %ux%u\n", mf->width, mf->height); + + if (width == mf->width && height == mf->height) { + /* Perfect! The client has done it all. */ + host_1to1 = true; + goto update_cache; + } + + host_1to1 = false; + if (!host_can_scale) + goto update_cache; + + cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + ret = v4l2_subdev_call(sd, video, cropcap, &cap); + if (ret < 0) + return ret; + + if (max_width > cap.bounds.width) + max_width = cap.bounds.width; + if (max_height > cap.bounds.height) + max_height = cap.bounds.height; + + /* Camera set a format, but geometry is not precise, try to improve */ + tmp_w = mf->width; + tmp_h = mf->height; + + /* width <= max_width && height <= max_height - guaranteed by try_fmt */ + while ((width > tmp_w || height > tmp_h) && + tmp_w < max_width && tmp_h < max_height) { + tmp_w = min(2 * tmp_w, max_width); + tmp_h = min(2 * tmp_h, max_height); + mf->width = tmp_w; + mf->height = tmp_h; + ret = v4l2_device_call_until_err(sd->v4l2_dev, + soc_camera_grp_id(icd), video, + s_mbus_fmt, mf); + dev_geo(dev, "Camera scaled to %ux%u\n", + mf->width, mf->height); + if (ret < 0) { + /* This shouldn't happen */ + dev_err(dev, "Client failed to set format: %d\n", ret); + return ret; + } + } + +update_cache: + /* Update cache */ + ret = soc_camera_client_g_rect(sd, rect); + if (ret < 0) + return ret; + + if (host_1to1) + *subrect = *rect; + else + update_subrect(rect, subrect); + + return 0; +} + +/** + * @icd - soc-camera device + * @rect - camera cropping window + * @subrect - part of rect, sent to the user + * @mf - in- / output camera output window + * @width - on input: max host input width + * on output: user width, mapped back to input + * @height - on input: max host input height + * on output: user height, mapped back to input + * @host_can_scale - host can scale this pixel format + * @shift - shift, used for scaling + */ +int soc_camera_client_scale(struct soc_camera_device *icd, + struct v4l2_rect *rect, struct v4l2_rect *subrect, + struct v4l2_mbus_framefmt *mf, + unsigned int *width, unsigned int *height, + bool host_can_scale, unsigned int shift) +{ + struct device *dev = icd->parent; + struct v4l2_mbus_framefmt mf_tmp = *mf; + unsigned int scale_h, scale_v; + int ret; + + /* + * 5. Apply iterative camera S_FMT for camera user window (also updates + * client crop cache and the imaginary sub-rectangle). + */ + ret = client_s_fmt(icd, rect, subrect, *width, *height, + &mf_tmp, host_can_scale); + if (ret < 0) + return ret; + + dev_geo(dev, "5: camera scaled to %ux%u\n", + mf_tmp.width, mf_tmp.height); + + /* 6. Retrieve camera output window (g_fmt) */ + + /* unneeded - it is already in "mf_tmp" */ + + /* 7. Calculate new client scales. */ + scale_h = soc_camera_calc_scale(rect->width, shift, mf_tmp.width); + scale_v = soc_camera_calc_scale(rect->height, shift, mf_tmp.height); + + mf->width = mf_tmp.width; + mf->height = mf_tmp.height; + mf->colorspace = mf_tmp.colorspace; + + /* + * 8. Calculate new host crop - apply camera scales to previously + * updated "effective" crop. + */ + *width = soc_camera_shift_scale(subrect->width, shift, scale_h); + *height = soc_camera_shift_scale(subrect->height, shift, scale_v); + + dev_geo(dev, "8: new client sub-window %ux%u\n", *width, *height); + + return 0; +} +EXPORT_SYMBOL(soc_camera_client_scale); + +/* + * Calculate real client output window by applying new scales to the current + * client crop. New scales are calculated from the requested output format and + * host crop, mapped backed onto the client input (subrect). + */ +void soc_camera_calc_client_output(struct soc_camera_device *icd, + struct v4l2_rect *rect, struct v4l2_rect *subrect, + const struct v4l2_pix_format *pix, struct v4l2_mbus_framefmt *mf, + unsigned int shift) +{ + struct device *dev = icd->parent; + unsigned int scale_v, scale_h; + + if (subrect->width == rect->width && + subrect->height == rect->height) { + /* No sub-cropping */ + mf->width = pix->width; + mf->height = pix->height; + return; + } + + /* 1.-2. Current camera scales and subwin - cached. */ + + dev_geo(dev, "2: subwin %ux%u@%u:%u\n", + subrect->width, subrect->height, + subrect->left, subrect->top); + + /* + * 3. Calculate new combined scales from input sub-window to requested + * user window. + */ + + /* + * TODO: CEU cannot scale images larger than VGA to smaller than SubQCIF + * (128x96) or larger than VGA. This and similar limitations have to be + * taken into account here. + */ + scale_h = soc_camera_calc_scale(subrect->width, shift, pix->width); + scale_v = soc_camera_calc_scale(subrect->height, shift, pix->height); + + dev_geo(dev, "3: scales %u:%u\n", scale_h, scale_v); + + /* + * 4. Calculate desired client output window by applying combined scales + * to client (real) input window. + */ + mf->width = soc_camera_shift_scale(rect->width, shift, scale_h); + mf->height = soc_camera_shift_scale(rect->height, shift, scale_v); +} +EXPORT_SYMBOL(soc_camera_calc_client_output); diff --git a/drivers/media/platform/soc_camera/soc_scale_crop.h b/drivers/media/platform/soc_camera/soc_scale_crop.h new file mode 100644 index 000000000000..184a30dff541 --- /dev/null +++ b/drivers/media/platform/soc_camera/soc_scale_crop.h @@ -0,0 +1,47 @@ +/* + * soc-camera generic scaling-cropping manipulation functions + * + * Copyright (C) 2013 Guennadi Liakhovetski <g.liakhovetski@gmx.de> + * + * 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 SOC_SCALE_CROP_H +#define SOC_SCALE_CROP_H + +#include <linux/kernel.h> + +struct soc_camera_device; + +struct v4l2_crop; +struct v4l2_mbus_framefmt; +struct v4l2_pix_format; +struct v4l2_rect; +struct v4l2_subdev; + +static inline unsigned int soc_camera_shift_scale(unsigned int size, + unsigned int shift, unsigned int scale) +{ + return DIV_ROUND_CLOSEST(size << shift, scale); +} + +#define soc_camera_calc_scale(in, shift, out) soc_camera_shift_scale(in, shift, out) + +int soc_camera_client_g_rect(struct v4l2_subdev *sd, struct v4l2_rect *rect); +int soc_camera_client_s_crop(struct v4l2_subdev *sd, + struct v4l2_crop *crop, struct v4l2_crop *cam_crop, + struct v4l2_rect *target_rect, struct v4l2_rect *subrect); +int soc_camera_client_scale(struct soc_camera_device *icd, + struct v4l2_rect *rect, struct v4l2_rect *subrect, + struct v4l2_mbus_framefmt *mf, + unsigned int *width, unsigned int *height, + bool host_can_scale, unsigned int shift); +void soc_camera_calc_client_output(struct soc_camera_device *icd, + struct v4l2_rect *rect, struct v4l2_rect *subrect, + const struct v4l2_pix_format *pix, struct v4l2_mbus_framefmt *mf, + unsigned int shift); + +#endif diff --git a/drivers/media/platform/timblogiw.c b/drivers/media/platform/timblogiw.c index a2f7bdd5104f..b557caf5b1a4 100644 --- a/drivers/media/platform/timblogiw.c +++ b/drivers/media/platform/timblogiw.c @@ -239,13 +239,12 @@ static int timblogiw_querycap(struct file *file, void *priv, struct video_device *vdev = video_devdata(file); dev_dbg(&vdev->dev, "%s: Entry\n", __func__); - memset(cap, 0, sizeof(*cap)); strncpy(cap->card, TIMBLOGIWIN_NAME, sizeof(cap->card)-1); strncpy(cap->driver, DRIVER_NAME, sizeof(cap->driver) - 1); - strlcpy(cap->bus_info, vdev->name, sizeof(cap->bus_info)); - cap->version = TIMBLOGIW_VERSION_CODE; - cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | + snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", vdev->name); + cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | V4L2_CAP_READWRITE; + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } @@ -834,11 +833,9 @@ static int timblogiw_probe(struct platform_device *pdev) goto err_request; } - return 0; err_request: - platform_set_drvdata(pdev, NULL); v4l2_device_unregister(&lw->v4l2_dev); err_register: kfree(lw); @@ -858,8 +855,6 @@ static int timblogiw_remove(struct platform_device *pdev) kfree(lw); - platform_set_drvdata(pdev, NULL); - return 0; } diff --git a/drivers/media/platform/via-camera.c b/drivers/media/platform/via-camera.c index a794cd6c4441..b4f9d03636e3 100644 --- a/drivers/media/platform/via-camera.c +++ b/drivers/media/platform/via-camera.c @@ -17,7 +17,6 @@ #include <linux/videodev2.h> #include <media/v4l2-device.h> #include <media/v4l2-ioctl.h> -#include <media/v4l2-chip-ident.h> #include <media/v4l2-ctrls.h> #include <media/ov7670.h> #include <media/videobuf-dma-sg.h> @@ -805,20 +804,6 @@ static const struct v4l2_file_operations viacam_fops = { * The long list of v4l2 ioctl ops */ -static int viacam_g_chip_ident(struct file *file, void *priv, - struct v4l2_dbg_chip_ident *ident) -{ - struct via_camera *cam = priv; - - ident->ident = V4L2_IDENT_NONE; - ident->revision = 0; - if (v4l2_chip_match_host(&ident->match)) { - ident->ident = V4L2_IDENT_VIA_VX855; - return 0; - } - return sensor_call(cam, core, g_chip_ident, ident); -} - /* * Only one input. */ @@ -852,6 +837,12 @@ static int viacam_s_std(struct file *filp, void *priv, v4l2_std_id std) return 0; } +static int viacam_g_std(struct file *filp, void *priv, v4l2_std_id *std) +{ + *std = V4L2_STD_NTSC_M; + return 0; +} + /* * Video format stuff. Here is our default format until * user space messes with things. @@ -1174,11 +1165,11 @@ static int viacam_enum_frameintervals(struct file *filp, void *priv, static const struct v4l2_ioctl_ops viacam_ioctl_ops = { - .vidioc_g_chip_ident = viacam_g_chip_ident, .vidioc_enum_input = viacam_enum_input, .vidioc_g_input = viacam_g_input, .vidioc_s_input = viacam_s_input, .vidioc_s_std = viacam_s_std, + .vidioc_g_std = viacam_g_std, .vidioc_enum_fmt_vid_cap = viacam_enum_fmt_vid_cap, .vidioc_try_fmt_vid_cap = viacam_try_fmt_vid_cap, .vidioc_g_fmt_vid_cap = viacam_g_fmt_vid_cap, @@ -1266,7 +1257,6 @@ static struct video_device viacam_v4l_template = { .name = "via-camera", .minor = -1, .tvnorms = V4L2_STD_NTSC_M, - .current_norm = V4L2_STD_NTSC_M, .fops = &viacam_fops, .ioctl_ops = &viacam_ioctl_ops, .release = video_device_release_empty, /* Check this */ diff --git a/drivers/media/radio/radio-keene.c b/drivers/media/radio/radio-keene.c index 4c9ae767fb31..21db23b196be 100644 --- a/drivers/media/radio/radio-keene.c +++ b/drivers/media/radio/radio-keene.c @@ -93,7 +93,7 @@ static int keene_cmd_main(struct keene_device *radio, unsigned freq, bool play) /* If bit 4 is set, then tune to the frequency. If bit 3 is set, then unmute; if bit 2 is set, then mute. If bit 1 is set, then enter idle mode; if bit 0 is set, - then enter transit mode. + then enter transmit mode. */ radio->buffer[5] = (radio->muted ? 4 : 8) | (play ? 1 : 2) | (freq ? 0x10 : 0); @@ -350,7 +350,6 @@ static int usb_keene_probe(struct usb_interface *intf, radio->pa = 118; radio->tx = 0x32; radio->stereo = true; - radio->curfreq = 95.16 * FREQ_MUL; if (hdl->error) { retval = hdl->error; @@ -383,6 +382,10 @@ static int usb_keene_probe(struct usb_interface *intf, video_set_drvdata(&radio->vdev, radio); set_bit(V4L2_FL_USE_FH_PRIO, &radio->vdev.flags); + /* at least 11ms is needed in order to settle hardware */ + msleep(20); + keene_cmd_main(radio, 95.16 * FREQ_MUL, false); + retval = video_register_device(&radio->vdev, VFL_TYPE_RADIO, -1); if (retval < 0) { dev_err(&intf->dev, "could not register video device\n"); diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c index adfcc61bdf0b..6f4318ff0db3 100644 --- a/drivers/media/radio/radio-sf16fmi.c +++ b/drivers/media/radio/radio-sf16fmi.c @@ -27,6 +27,8 @@ #include <linux/io.h> /* outb, outb_p */ #include <media/v4l2-device.h> #include <media/v4l2-ioctl.h> +#include <media/v4l2-ctrls.h> +#include <media/v4l2-event.h> #include "lm7000.h" MODULE_AUTHOR("Petr Vandrovec, vandrove@vc.cvut.cz and M. Kirkwood"); @@ -44,10 +46,11 @@ module_param(radio_nr, int, 0); struct fmi { struct v4l2_device v4l2_dev; + struct v4l2_ctrl_handler hdl; struct video_device vdev; int io; bool mute; - unsigned long curfreq; /* freq in kHz */ + u32 curfreq; /* freq in kHz */ struct mutex lock; }; @@ -55,8 +58,8 @@ static struct fmi fmi_card; static struct pnp_dev *dev; bool pnp_attached; -#define RSF16_MINFREQ (87 * 16000) -#define RSF16_MAXFREQ (108 * 16000) +#define RSF16_MINFREQ (87U * 16000) +#define RSF16_MAXFREQ (108U * 16000) #define FMI_BIT_TUN_CE (1 << 0) #define FMI_BIT_TUN_CLK (1 << 1) @@ -115,13 +118,22 @@ static inline int fmi_getsigstr(struct fmi *fmi) return (res & 2) ? 0 : 0xFFFF; } +static void fmi_set_freq(struct fmi *fmi) +{ + fmi->curfreq = clamp(fmi->curfreq, RSF16_MINFREQ, RSF16_MAXFREQ); + /* rounding in steps of 800 to match the freq + that will be used */ + lm7000_set_freq((fmi->curfreq / 800) * 800, fmi, fmi_set_pins); +} + 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", sizeof(v->bus_info)); - v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; + strlcpy(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; } @@ -157,12 +169,10 @@ static int vidioc_s_frequency(struct file *file, void *priv, if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) return -EINVAL; - if (f->frequency < RSF16_MINFREQ || - f->frequency > RSF16_MAXFREQ) - return -EINVAL; - /* rounding in steps of 800 to match the freq - that will be used */ - lm7000_set_freq((f->frequency / 800) * 800, fmi, fmi_set_pins); + + fmi->curfreq = f->frequency; + fmi_set_freq(fmi); + return 0; } @@ -178,74 +188,31 @@ static int vidioc_g_frequency(struct file *file, void *priv, return 0; } -static int vidioc_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *qc) +static int fmi_s_ctrl(struct v4l2_ctrl *ctrl) { - switch (qc->id) { - case V4L2_CID_AUDIO_MUTE: - return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); - } - return -EINVAL; -} - -static int vidioc_g_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct fmi *fmi = video_drvdata(file); + struct fmi *fmi = container_of(ctrl->handler, struct fmi, hdl); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: - ctrl->value = fmi->mute; - return 0; - } - return -EINVAL; -} - -static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct fmi *fmi = video_drvdata(file); - - switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - if (ctrl->value) + if (ctrl->val) fmi_mute(fmi); else fmi_unmute(fmi); - fmi->mute = ctrl->value; + fmi->mute = ctrl->val; return 0; } return -EINVAL; } -static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) -{ - *i = 0; - return 0; -} - -static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) -{ - return i ? -EINVAL : 0; -} - -static int vidioc_g_audio(struct file *file, void *priv, - struct v4l2_audio *a) -{ - a->index = 0; - strlcpy(a->name, "Radio", sizeof(a->name)); - a->capability = V4L2_AUDCAP_STEREO; - return 0; -} - -static int vidioc_s_audio(struct file *file, void *priv, - const struct v4l2_audio *a) -{ - return a->index ? -EINVAL : 0; -} +static const struct v4l2_ctrl_ops fmi_ctrl_ops = { + .s_ctrl = fmi_s_ctrl, +}; static const struct v4l2_file_operations fmi_fops = { .owner = THIS_MODULE, + .open = v4l2_fh_open, + .release = v4l2_fh_release, + .poll = v4l2_ctrl_poll, .unlocked_ioctl = video_ioctl2, }; @@ -253,15 +220,11 @@ static const struct v4l2_ioctl_ops fmi_ioctl_ops = { .vidioc_querycap = vidioc_querycap, .vidioc_g_tuner = vidioc_g_tuner, .vidioc_s_tuner = vidioc_s_tuner, - .vidioc_g_audio = vidioc_g_audio, - .vidioc_s_audio = vidioc_s_audio, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency, - .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_log_status = v4l2_ctrl_log_status, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, }; /* ladis: this is my card. does any other types exist? */ @@ -311,6 +274,7 @@ static int __init fmi_init(void) { struct fmi *fmi = &fmi_card; struct v4l2_device *v4l2_dev = &fmi->v4l2_dev; + struct v4l2_ctrl_handler *hdl = &fmi->hdl; int res, i; int probe_ports[] = { 0, 0x284, 0x384 }; @@ -363,19 +327,35 @@ static int __init fmi_init(void) return res; } + v4l2_ctrl_handler_init(hdl, 1); + v4l2_ctrl_new_std(hdl, &fmi_ctrl_ops, + V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1); + v4l2_dev->ctrl_handler = hdl; + if (hdl->error) { + res = hdl->error; + v4l2_err(v4l2_dev, "Could not register controls\n"); + v4l2_ctrl_handler_free(hdl); + v4l2_device_unregister(v4l2_dev); + return res; + } + strlcpy(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; fmi->vdev.release = video_device_release_empty; + set_bit(V4L2_FL_USE_FH_PRIO, &fmi->vdev.flags); video_set_drvdata(&fmi->vdev, fmi); mutex_init(&fmi->lock); - /* mute card - prevents noisy bootups */ - fmi_mute(fmi); + /* mute card and set default frequency */ + fmi->mute = 1; + fmi->curfreq = RSF16_MINFREQ; + fmi_set_freq(fmi); if (video_register_device(&fmi->vdev, VFL_TYPE_RADIO, radio_nr) < 0) { + v4l2_ctrl_handler_free(hdl); v4l2_device_unregister(v4l2_dev); release_region(fmi->io, 2); if (pnp_attached) @@ -391,6 +371,7 @@ static void __exit fmi_exit(void) { struct fmi *fmi = &fmi_card; + v4l2_ctrl_handler_free(&fmi->hdl); video_unregister_device(&fmi->vdev); v4l2_device_unregister(&fmi->v4l2_dev); release_region(fmi->io, 2); diff --git a/drivers/media/radio/radio-si476x.c b/drivers/media/radio/radio-si476x.c index 9dc8bafe6486..9c9084cb99f7 100644 --- a/drivers/media/radio/radio-si476x.c +++ b/drivers/media/radio/radio-si476x.c @@ -1018,16 +1018,6 @@ static int si476x_radio_s_ctrl(struct v4l2_ctrl *ctrl) return retval; } -static int si476x_radio_g_chip_ident(struct file *file, void *fh, - struct v4l2_dbg_chip_ident *chip) -{ - if (chip->match.type == V4L2_CHIP_MATCH_HOST && - v4l2_chip_match_host(&chip->match)) - return 0; - return -EINVAL; -} - - #ifdef CONFIG_VIDEO_ADV_DEBUG static int si476x_radio_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg) @@ -1203,7 +1193,6 @@ static const struct v4l2_ioctl_ops si4761_ioctl_ops = { .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, - .vidioc_g_chip_ident = si476x_radio_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = si476x_radio_g_register, .vidioc_s_register = si476x_radio_s_register, diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c index 38d563d62595..036e2f54f4db 100644 --- a/drivers/media/radio/radio-tea5764.c +++ b/drivers/media/radio/radio-tea5764.c @@ -39,6 +39,9 @@ #include <linux/i2c.h> /* I2C */ #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> +#include <media/v4l2-device.h> +#include <media/v4l2-ctrls.h> +#include <media/v4l2-event.h> #define DRIVER_VERSION "0.0.2" @@ -57,8 +60,8 @@ /* Frequency limits in MHz -- these are European values. For Japanese devices, that would be 76000 and 91000. */ -#define FREQ_MIN 87500 -#define FREQ_MAX 108000 +#define FREQ_MIN 87500U +#define FREQ_MAX 108000U #define FREQ_MUL 16 /* TEA5764 registers */ @@ -138,8 +141,10 @@ static int radio_nr = -1; static int use_xtal = RADIO_TEA5764_XTAL; struct tea5764_device { + struct v4l2_device v4l2_dev; + struct v4l2_ctrl_handler ctrl_handler; struct i2c_client *i2c_client; - struct video_device *videodev; + struct video_device vdev; struct tea5764_regs regs; struct mutex mutex; }; @@ -187,18 +192,6 @@ static int tea5764_i2c_write(struct tea5764_device *radio) return 0; } -/* V4L2 code related */ -static struct v4l2_queryctrl radio_qctrl[] = { - { - .id = V4L2_CID_AUDIO_MUTE, - .name = "Mute", - .minimum = 0, - .maximum = 1, - .default_value = 1, - .type = V4L2_CTRL_TYPE_BOOLEAN, - } -}; - static void tea5764_power_up(struct tea5764_device *radio) { struct tea5764_regs *r = &radio->regs; @@ -291,23 +284,19 @@ static void tea5764_mute(struct tea5764_device *radio, int on) tea5764_i2c_write(radio); } -static int tea5764_is_muted(struct tea5764_device *radio) -{ - return radio->regs.tnctrl & TEA5764_TNCTRL_MU; -} - /* V4L2 vidioc */ static int vidioc_querycap(struct file *file, void *priv, struct v4l2_capability *v) { struct tea5764_device *radio = video_drvdata(file); - struct video_device *dev = radio->videodev; + struct video_device *dev = &radio->vdev; strlcpy(v->driver, dev->dev.driver->name, sizeof(v->driver)); strlcpy(v->card, dev->name, sizeof(v->card)); snprintf(v->bus_info, sizeof(v->bus_info), "I2C:%s", dev_name(&dev->dev)); - v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; + v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO; + v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } @@ -320,8 +309,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, if (v->index > 0) return -EINVAL; - memset(v, 0, sizeof(*v)); - strcpy(v->name, "FM"); + strlcpy(v->name, "FM", sizeof(v->name)); v->type = V4L2_TUNER_RADIO; tea5764_i2c_read(radio); v->rangelow = FREQ_MIN * FREQ_MUL; @@ -354,19 +342,23 @@ static int vidioc_s_frequency(struct file *file, void *priv, const struct v4l2_frequency *f) { struct tea5764_device *radio = video_drvdata(file); + unsigned freq = f->frequency; if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO) return -EINVAL; - if (f->frequency == 0) { + if (freq == 0) { /* We special case this as a power down control. */ tea5764_power_down(radio); - } - if (f->frequency < (FREQ_MIN * FREQ_MUL)) - return -EINVAL; - if (f->frequency > (FREQ_MAX * FREQ_MUL)) + /* Yes, that's what is returned in this case. This + whole special case is non-compliant and should really + be replaced with something better, but changing this + might well break code that depends on this behavior. + So we keep it as-is. */ return -EINVAL; + } + clamp(freq, FREQ_MIN * FREQ_MUL, FREQ_MAX * FREQ_MUL); tea5764_power_up(radio); - tea5764_tune(radio, (f->frequency * 125) / 2); + tea5764_tune(radio, (freq * 125) / 2); return 0; } @@ -379,7 +371,6 @@ static int vidioc_g_frequency(struct file *file, void *priv, if (f->tuner != 0) return -EINVAL; tea5764_i2c_read(radio); - memset(f, 0, sizeof(*f)); f->type = V4L2_TUNER_RADIO; if (r->tnctrl & TEA5764_TNCTRL_PUPD0) f->frequency = (tea5764_get_freq(radio) * 2) / 125; @@ -389,83 +380,29 @@ static int vidioc_g_frequency(struct file *file, void *priv, return 0; } -static int vidioc_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *qc) +static int tea5764_s_ctrl(struct v4l2_ctrl *ctrl) { - int i; - - for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { - if (qc->id && qc->id == radio_qctrl[i].id) { - memcpy(qc, &(radio_qctrl[i]), sizeof(*qc)); - return 0; - } - } - return -EINVAL; -} - -static int vidioc_g_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct tea5764_device *radio = video_drvdata(file); - - switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - tea5764_i2c_read(radio); - ctrl->value = tea5764_is_muted(radio) ? 1 : 0; - return 0; - } - return -EINVAL; -} - -static int vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct tea5764_device *radio = video_drvdata(file); + struct tea5764_device *radio = + container_of(ctrl->handler, struct tea5764_device, ctrl_handler); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: - tea5764_mute(radio, ctrl->value); + tea5764_mute(radio, ctrl->val); return 0; } return -EINVAL; } -static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) -{ - *i = 0; - return 0; -} - -static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) -{ - if (i != 0) - return -EINVAL; - return 0; -} - -static int vidioc_g_audio(struct file *file, void *priv, - struct v4l2_audio *a) -{ - if (a->index > 1) - return -EINVAL; - - strcpy(a->name, "Radio"); - a->capability = V4L2_AUDCAP_STEREO; - return 0; -} - -static int vidioc_s_audio(struct file *file, void *priv, - const struct v4l2_audio *a) -{ - if (a->index != 0) - return -EINVAL; - - return 0; -} +static const struct v4l2_ctrl_ops tea5764_ctrl_ops = { + .s_ctrl = tea5764_s_ctrl, +}; /* File system interface */ static const struct v4l2_file_operations tea5764_fops = { .owner = THIS_MODULE, + .open = v4l2_fh_open, + .release = v4l2_fh_release, + .poll = v4l2_ctrl_poll, .unlocked_ioctl = video_ioctl2, }; @@ -473,15 +410,11 @@ static const struct v4l2_ioctl_ops tea5764_ioctl_ops = { .vidioc_querycap = vidioc_querycap, .vidioc_g_tuner = vidioc_g_tuner, .vidioc_s_tuner = vidioc_s_tuner, - .vidioc_g_audio = vidioc_g_audio, - .vidioc_s_audio = vidioc_s_audio, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency, - .vidioc_queryctrl = vidioc_queryctrl, - .vidioc_g_ctrl = vidioc_g_ctrl, - .vidioc_s_ctrl = vidioc_s_ctrl, + .vidioc_log_status = v4l2_ctrl_log_status, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, }; /* V4L2 interface */ @@ -489,7 +422,7 @@ static struct video_device tea5764_radio_template = { .name = "TEA5764 FM-Radio", .fops = &tea5764_fops, .ioctl_ops = &tea5764_ioctl_ops, - .release = video_device_release, + .release = video_device_release_empty, }; /* I2C probe: check if the device exists and register with v4l if it is */ @@ -497,6 +430,8 @@ static int tea5764_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct tea5764_device *radio; + struct v4l2_device *v4l2_dev; + struct v4l2_ctrl_handler *hdl; struct tea5764_regs *r; int ret; @@ -505,31 +440,45 @@ static int tea5764_i2c_probe(struct i2c_client *client, if (!radio) return -ENOMEM; + v4l2_dev = &radio->v4l2_dev; + ret = v4l2_device_register(&client->dev, v4l2_dev); + if (ret < 0) { + v4l2_err(v4l2_dev, "could not register v4l2_device\n"); + goto errfr; + } + + hdl = &radio->ctrl_handler; + v4l2_ctrl_handler_init(hdl, 1); + v4l2_ctrl_new_std(hdl, &tea5764_ctrl_ops, + V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1); + v4l2_dev->ctrl_handler = hdl; + if (hdl->error) { + ret = hdl->error; + v4l2_err(v4l2_dev, "Could not register controls\n"); + goto errunreg; + } + mutex_init(&radio->mutex); radio->i2c_client = client; ret = tea5764_i2c_read(radio); if (ret) - goto errfr; + goto errunreg; r = &radio->regs; PDEBUG("chipid = %04X, manid = %04X", r->chipid, r->manid); if (r->chipid != TEA5764_CHIPID || (r->manid & 0x0fff) != TEA5764_MANID) { PWARN("This chip is not a TEA5764!"); ret = -EINVAL; - goto errfr; + goto errunreg; } - radio->videodev = video_device_alloc(); - if (!(radio->videodev)) { - ret = -ENOMEM; - goto errfr; - } - memcpy(radio->videodev, &tea5764_radio_template, - sizeof(tea5764_radio_template)); + radio->vdev = tea5764_radio_template; i2c_set_clientdata(client, radio); - video_set_drvdata(radio->videodev, radio); - radio->videodev->lock = &radio->mutex; + video_set_drvdata(&radio->vdev, radio); + radio->vdev.lock = &radio->mutex; + radio->vdev.v4l2_dev = v4l2_dev; + set_bit(V4L2_FL_USE_FH_PRIO, &radio->vdev.flags); /* initialize and power off the chip */ tea5764_i2c_read(radio); @@ -537,16 +486,17 @@ static int tea5764_i2c_probe(struct i2c_client *client, tea5764_mute(radio, 1); tea5764_power_down(radio); - ret = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr); + ret = video_register_device(&radio->vdev, VFL_TYPE_RADIO, radio_nr); if (ret < 0) { PWARN("Could not register video device!"); - goto errrel; + goto errunreg; } PINFO("registered."); return 0; -errrel: - video_device_release(radio->videodev); +errunreg: + v4l2_ctrl_handler_free(hdl); + v4l2_device_unregister(v4l2_dev); errfr: kfree(radio); return ret; @@ -559,7 +509,9 @@ static int tea5764_i2c_remove(struct i2c_client *client) PDEBUG("remove"); if (radio) { tea5764_power_down(radio); - video_unregister_device(radio->videodev); + video_unregister_device(&radio->vdev); + v4l2_ctrl_handler_free(&radio->ctrl_handler); + v4l2_device_unregister(&radio->v4l2_dev); kfree(radio); } return 0; diff --git a/drivers/media/radio/radio-timb.c b/drivers/media/radio/radio-timb.c index bb7b143b65d1..0817964d9172 100644 --- a/drivers/media/radio/radio-timb.c +++ b/drivers/media/radio/radio-timb.c @@ -19,6 +19,8 @@ #include <linux/io.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-device.h> +#include <media/v4l2-ctrls.h> +#include <media/v4l2-event.h> #include <linux/platform_device.h> #include <linux/interrupt.h> #include <linux/slab.h> @@ -44,7 +46,8 @@ static int timbradio_vidioc_querycap(struct file *file, void *priv, strlcpy(v->driver, DRIVER_NAME, sizeof(v->driver)); strlcpy(v->card, "Timberdale Radio", sizeof(v->card)); snprintf(v->bus_info, sizeof(v->bus_info), "platform:"DRIVER_NAME); - v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; + v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO; + v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } @@ -62,34 +65,6 @@ static int timbradio_vidioc_s_tuner(struct file *file, void *priv, return v4l2_subdev_call(tr->sd_tuner, tuner, s_tuner, v); } -static int timbradio_vidioc_g_input(struct file *filp, void *priv, - unsigned int *i) -{ - *i = 0; - return 0; -} - -static int timbradio_vidioc_s_input(struct file *filp, void *priv, - unsigned int i) -{ - return i ? -EINVAL : 0; -} - -static int timbradio_vidioc_g_audio(struct file *file, void *priv, - struct v4l2_audio *a) -{ - a->index = 0; - strlcpy(a->name, "Radio", sizeof(a->name)); - a->capability = V4L2_AUDCAP_STEREO; - return 0; -} - -static int timbradio_vidioc_s_audio(struct file *file, void *priv, - const struct v4l2_audio *a) -{ - return a->index ? -EINVAL : 0; -} - static int timbradio_vidioc_s_frequency(struct file *file, void *priv, const struct v4l2_frequency *f) { @@ -104,44 +79,22 @@ static int timbradio_vidioc_g_frequency(struct file *file, void *priv, return v4l2_subdev_call(tr->sd_tuner, tuner, g_frequency, f); } -static int timbradio_vidioc_queryctrl(struct file *file, void *priv, - struct v4l2_queryctrl *qc) -{ - struct timbradio *tr = video_drvdata(file); - return v4l2_subdev_call(tr->sd_dsp, core, queryctrl, qc); -} - -static int timbradio_vidioc_g_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct timbradio *tr = video_drvdata(file); - return v4l2_subdev_call(tr->sd_dsp, core, g_ctrl, ctrl); -} - -static int timbradio_vidioc_s_ctrl(struct file *file, void *priv, - struct v4l2_control *ctrl) -{ - struct timbradio *tr = video_drvdata(file); - return v4l2_subdev_call(tr->sd_dsp, core, s_ctrl, ctrl); -} - static const struct v4l2_ioctl_ops timbradio_ioctl_ops = { .vidioc_querycap = timbradio_vidioc_querycap, .vidioc_g_tuner = timbradio_vidioc_g_tuner, .vidioc_s_tuner = timbradio_vidioc_s_tuner, .vidioc_g_frequency = timbradio_vidioc_g_frequency, .vidioc_s_frequency = timbradio_vidioc_s_frequency, - .vidioc_g_input = timbradio_vidioc_g_input, - .vidioc_s_input = timbradio_vidioc_s_input, - .vidioc_g_audio = timbradio_vidioc_g_audio, - .vidioc_s_audio = timbradio_vidioc_s_audio, - .vidioc_queryctrl = timbradio_vidioc_queryctrl, - .vidioc_g_ctrl = timbradio_vidioc_g_ctrl, - .vidioc_s_ctrl = timbradio_vidioc_s_ctrl + .vidioc_log_status = v4l2_ctrl_log_status, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, }; static const struct v4l2_file_operations timbradio_fops = { .owner = THIS_MODULE, + .open = v4l2_fh_open, + .release = v4l2_fh_release, + .poll = v4l2_ctrl_poll, .unlocked_ioctl = video_ioctl2, }; @@ -173,6 +126,7 @@ static int timbradio_probe(struct platform_device *pdev) tr->video_dev.release = video_device_release_empty; tr->video_dev.minor = -1; tr->video_dev.lock = &tr->lock; + set_bit(V4L2_FL_USE_FH_PRIO, &tr->video_dev.flags); strlcpy(tr->v4l2_dev.name, DRIVER_NAME, sizeof(tr->v4l2_dev.name)); err = v4l2_device_register(NULL, &tr->v4l2_dev); @@ -181,6 +135,15 @@ static int timbradio_probe(struct platform_device *pdev) tr->video_dev.v4l2_dev = &tr->v4l2_dev; + tr->sd_tuner = v4l2_i2c_new_subdev_board(&tr->v4l2_dev, + i2c_get_adapter(pdata->i2c_adapter), pdata->tuner, NULL); + tr->sd_dsp = v4l2_i2c_new_subdev_board(&tr->v4l2_dev, + i2c_get_adapter(pdata->i2c_adapter), pdata->dsp, NULL); + if (tr->sd_tuner == NULL || tr->sd_dsp == NULL) + goto err_video_req; + + tr->v4l2_dev.ctrl_handler = tr->sd_dsp->ctrl_handler; + err = video_register_device(&tr->video_dev, VFL_TYPE_RADIO, -1); if (err) { dev_err(&pdev->dev, "Error reg video\n"); @@ -193,7 +156,6 @@ static int timbradio_probe(struct platform_device *pdev) return 0; err_video_req: - video_device_release_empty(&tr->video_dev); v4l2_device_unregister(&tr->v4l2_dev); err: dev_err(&pdev->dev, "Failed to register: %d\n", err); @@ -206,10 +168,7 @@ static int timbradio_remove(struct platform_device *pdev) struct timbradio *tr = platform_get_drvdata(pdev); video_unregister_device(&tr->video_dev); - video_device_release_empty(&tr->video_dev); - v4l2_device_unregister(&tr->v4l2_dev); - return 0; } diff --git a/drivers/media/radio/saa7706h.c b/drivers/media/radio/saa7706h.c index 06c06cc9ff25..ec805b09c608 100644 --- a/drivers/media/radio/saa7706h.c +++ b/drivers/media/radio/saa7706h.c @@ -25,7 +25,7 @@ #include <linux/i2c.h> #include <linux/slab.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> +#include <media/v4l2-ctrls.h> #define DRIVER_NAME "saa7706h" @@ -127,6 +127,7 @@ struct saa7706h_state { struct v4l2_subdev sd; + struct v4l2_ctrl_handler hdl; unsigned muted; }; @@ -317,51 +318,32 @@ static int saa7706h_mute(struct v4l2_subdev *sd) return err; } -static int saa7706h_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) +static int saa7706h_s_ctrl(struct v4l2_ctrl *ctrl) { - switch (qc->id) { - case V4L2_CID_AUDIO_MUTE: - return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); - } - return -EINVAL; -} - -static int saa7706h_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) -{ - struct saa7706h_state *state = to_state(sd); + struct saa7706h_state *state = + container_of(ctrl->handler, struct saa7706h_state, hdl); switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: - ctrl->value = state->muted; - return 0; + if (ctrl->val) + return saa7706h_mute(&state->sd); + return saa7706h_unmute(&state->sd); } return -EINVAL; } -static int saa7706h_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) -{ - switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - if (ctrl->value) - return saa7706h_mute(sd); - return saa7706h_unmute(sd); - } - return -EINVAL; -} - -static int saa7706h_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7706H, 0); -} +static const struct v4l2_ctrl_ops saa7706h_ctrl_ops = { + .s_ctrl = saa7706h_s_ctrl, +}; static const struct v4l2_subdev_core_ops saa7706h_core_ops = { - .g_chip_ident = saa7706h_g_chip_ident, - .queryctrl = saa7706h_queryctrl, - .g_ctrl = saa7706h_g_ctrl, - .s_ctrl = saa7706h_s_ctrl, + .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, + .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, + .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, + .g_ctrl = v4l2_subdev_g_ctrl, + .s_ctrl = v4l2_subdev_s_ctrl, + .queryctrl = v4l2_subdev_queryctrl, + .querymenu = v4l2_subdev_querymenu, }; static const struct v4l2_subdev_ops saa7706h_ops = { @@ -393,13 +375,20 @@ static int saa7706h_probe(struct i2c_client *client, sd = &state->sd; v4l2_i2c_subdev_init(sd, client, &saa7706h_ops); + v4l2_ctrl_handler_init(&state->hdl, 4); + v4l2_ctrl_new_std(&state->hdl, &saa7706h_ctrl_ops, + V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1); + sd->ctrl_handler = &state->hdl; + err = state->hdl.error; + if (err) + goto err; + /* check the rom versions */ err = saa7706h_get_reg16(sd, SAA7706H_DSP1_ROM_VER); if (err < 0) goto err; if (err != SUPPORTED_DSP1_ROM_VER) v4l2_warn(sd, "Unknown DSP1 ROM code version: 0x%x\n", err); - state->muted = 1; /* startup in a muted state */ @@ -411,6 +400,7 @@ static int saa7706h_probe(struct i2c_client *client, err: v4l2_device_unregister_subdev(sd); + v4l2_ctrl_handler_free(&state->hdl); kfree(to_state(sd)); printk(KERN_ERR DRIVER_NAME ": Failed to probe: %d\n", err); @@ -421,9 +411,11 @@ err: static int saa7706h_remove(struct i2c_client *client) { struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct saa7706h_state *state = to_state(sd); saa7706h_mute(sd); v4l2_device_unregister_subdev(sd); + v4l2_ctrl_handler_free(&state->hdl); kfree(to_state(sd)); return 0; } diff --git a/drivers/media/radio/tef6862.c b/drivers/media/radio/tef6862.c index 82c6c9475d7c..06ac69245ca1 100644 --- a/drivers/media/radio/tef6862.c +++ b/drivers/media/radio/tef6862.c @@ -25,14 +25,13 @@ #include <linux/slab.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> #define DRIVER_NAME "tef6862" #define FREQ_MUL 16000 -#define TEF6862_LO_FREQ (875 * FREQ_MUL / 10) -#define TEF6862_HI_FREQ (108 * FREQ_MUL) +#define TEF6862_LO_FREQ (875U * FREQ_MUL / 10) +#define TEF6862_HI_FREQ (108U * FREQ_MUL) /* Write mode sub addresses */ #define WM_SUB_BANDWIDTH 0x0 @@ -105,6 +104,7 @@ static int tef6862_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequen { struct tef6862_state *state = to_state(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); + unsigned freq = f->frequency; u16 pll; u8 i2cmsg[3]; int err; @@ -112,7 +112,8 @@ static int tef6862_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequen if (f->tuner != 0) return -EINVAL; - pll = 1964 + ((f->frequency - TEF6862_LO_FREQ) * 20) / FREQ_MUL; + clamp(freq, TEF6862_LO_FREQ, TEF6862_HI_FREQ); + pll = 1964 + ((freq - TEF6862_LO_FREQ) * 20) / FREQ_MUL; i2cmsg[0] = (MODE_PRESET << MODE_SHIFT) | WM_SUB_PLLM; i2cmsg[1] = (pll >> 8) & 0xff; i2cmsg[2] = pll & 0xff; @@ -121,7 +122,7 @@ static int tef6862_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequen if (err != sizeof(i2cmsg)) return err < 0 ? err : -EIO; - state->freq = f->frequency; + state->freq = freq; return 0; } @@ -136,14 +137,6 @@ static int tef6862_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f) return 0; } -static int tef6862_g_chip_ident(struct v4l2_subdev *sd, - struct v4l2_dbg_chip_ident *chip) -{ - struct i2c_client *client = v4l2_get_subdevdata(sd); - - return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TEF6862, 0); -} - static const struct v4l2_subdev_tuner_ops tef6862_tuner_ops = { .g_tuner = tef6862_g_tuner, .s_tuner = tef6862_s_tuner, @@ -151,12 +144,7 @@ static const struct v4l2_subdev_tuner_ops tef6862_tuner_ops = { .g_frequency = tef6862_g_frequency, }; -static const struct v4l2_subdev_core_ops tef6862_core_ops = { - .g_chip_ident = tef6862_g_chip_ident, -}; - static const struct v4l2_subdev_ops tef6862_ops = { - .core = &tef6862_core_ops, .tuner = &tef6862_tuner_ops, }; diff --git a/drivers/media/radio/wl128x/fmdrv.h b/drivers/media/radio/wl128x/fmdrv.h index aac0f025f767..a587c9bac930 100644 --- a/drivers/media/radio/wl128x/fmdrv.h +++ b/drivers/media/radio/wl128x/fmdrv.h @@ -30,6 +30,7 @@ #include <linux/timer.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-common.h> +#include <media/v4l2-device.h> #include <media/v4l2-ctrls.h> #define FM_DRV_VERSION "0.1.1" @@ -202,6 +203,7 @@ struct fmtx_data { /* FM driver operation structure */ struct fmdev { struct video_device *radio_dev; /* V4L2 video device pointer */ + struct v4l2_device v4l2_dev; /* V4L2 top level struct */ struct snd_card *card; /* Card which holds FM mixer controls */ u16 asci_id; spinlock_t rds_buff_lock; /* To protect access to RDS buffer */ diff --git a/drivers/media/radio/wl128x/fmdrv_common.c b/drivers/media/radio/wl128x/fmdrv_common.c index a002234ed5de..253f307f0b37 100644 --- a/drivers/media/radio/wl128x/fmdrv_common.c +++ b/drivers/media/radio/wl128x/fmdrv_common.c @@ -715,7 +715,7 @@ static void fm_irq_handle_rdsdata_getcmd_resp(struct fmdev *fmdev) struct fm_rdsdata_format rds_fmt; struct fm_rds *rds = &fmdev->rx.rds; unsigned long group_idx, flags; - u8 *rds_data, meta_data, tmpbuf[3]; + u8 *rds_data, meta_data, tmpbuf[FM_RDS_BLK_SIZE]; u8 type, blk_idx; u16 cur_picode; u32 rds_len; @@ -1073,6 +1073,7 @@ int fmc_transfer_rds_from_internal_buff(struct fmdev *fmdev, struct file *file, u8 __user *buf, size_t count) { u32 block_count; + u8 tmpbuf[FM_RDS_BLK_SIZE]; unsigned long flags; int ret; @@ -1087,29 +1088,32 @@ int fmc_transfer_rds_from_internal_buff(struct fmdev *fmdev, struct file *file, } /* Calculate block count from byte count */ - count /= 3; + count /= FM_RDS_BLK_SIZE; block_count = 0; ret = 0; - spin_lock_irqsave(&fmdev->rds_buff_lock, flags); - while (block_count < count) { - if (fmdev->rx.rds.wr_idx == fmdev->rx.rds.rd_idx) - break; + spin_lock_irqsave(&fmdev->rds_buff_lock, flags); - if (copy_to_user(buf, &fmdev->rx.rds.buff[fmdev->rx.rds.rd_idx], - FM_RDS_BLK_SIZE)) + if (fmdev->rx.rds.wr_idx == fmdev->rx.rds.rd_idx) { + spin_unlock_irqrestore(&fmdev->rds_buff_lock, flags); break; - + } + memcpy(tmpbuf, &fmdev->rx.rds.buff[fmdev->rx.rds.rd_idx], + FM_RDS_BLK_SIZE); fmdev->rx.rds.rd_idx += FM_RDS_BLK_SIZE; if (fmdev->rx.rds.rd_idx >= fmdev->rx.rds.buf_size) fmdev->rx.rds.rd_idx = 0; + spin_unlock_irqrestore(&fmdev->rds_buff_lock, flags); + + if (copy_to_user(buf, tmpbuf, FM_RDS_BLK_SIZE)) + break; + block_count++; buf += FM_RDS_BLK_SIZE; ret += FM_RDS_BLK_SIZE; } - spin_unlock_irqrestore(&fmdev->rds_buff_lock, flags); return ret; } diff --git a/drivers/media/radio/wl128x/fmdrv_v4l2.c b/drivers/media/radio/wl128x/fmdrv_v4l2.c index 5dec323f4247..b55012c11842 100644 --- a/drivers/media/radio/wl128x/fmdrv_v4l2.c +++ b/drivers/media/radio/wl128x/fmdrv_v4l2.c @@ -533,6 +533,11 @@ 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)); + ret = v4l2_device_register(NULL, &fmdev->v4l2_dev); + if (ret < 0) + return ret; + /* Init mutex for core locking */ mutex_init(&fmdev->mutex); @@ -549,6 +554,7 @@ int fm_v4l2_init_video_device(struct fmdev *fmdev, int radio_nr) video_set_drvdata(gradio_dev, fmdev); gradio_dev->lock = &fmdev->mutex; + gradio_dev->v4l2_dev = &fmdev->v4l2_dev; /* Register with V4L2 subsystem as RADIO device */ if (video_register_device(gradio_dev, VFL_TYPE_RADIO, radio_nr)) { @@ -611,5 +617,7 @@ void *fm_v4l2_deinit_video_device(void) /* Unregister RADIO device from V4L2 subsystem */ video_unregister_device(gradio_dev); + v4l2_device_unregister(&fmdev->v4l2_dev); + return fmdev; } diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c index 8b82ae9bd686..07aacfa5903d 100644 --- a/drivers/media/rc/gpio-ir-recv.c +++ b/drivers/media/rc/gpio-ir-recv.c @@ -178,7 +178,6 @@ static int gpio_ir_recv_probe(struct platform_device *pdev) return 0; err_request_irq: - platform_set_drvdata(pdev, NULL); rc_unregister_device(rcdev); rcdev = NULL; err_register_rc_device: @@ -196,7 +195,6 @@ static int gpio_ir_recv_remove(struct platform_device *pdev) struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev); free_irq(gpio_to_irq(gpio_dev->gpio_nr), gpio_dev); - platform_set_drvdata(pdev, NULL); rc_unregister_device(gpio_dev->rcdev); gpio_free(gpio_dev->gpio_nr); kfree(gpio_dev); diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile index 5ab94ea4bc28..b1cde8c0422b 100644 --- a/drivers/media/rc/keymaps/Makefile +++ b/drivers/media/rc/keymaps/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ rc-budget-ci-old.o \ rc-cinergy-1400.o \ rc-cinergy.o \ + rc-delock-61959.o \ rc-dib0700-nec.o \ rc-dib0700-rc5.o \ rc-digitalnow-tinytwin.o \ diff --git a/drivers/media/rc/keymaps/rc-delock-61959.c b/drivers/media/rc/keymaps/rc-delock-61959.c new file mode 100644 index 000000000000..01bed864f09d --- /dev/null +++ b/drivers/media/rc/keymaps/rc-delock-61959.c @@ -0,0 +1,83 @@ +/* rc-delock-61959.c - Keytable for Delock + * + * Copyright (c) 2013 by Jakob Haufe <sur5r@sur5r.net> + * + * 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 <media/rc-map.h> +#include <linux/module.h> + +/* + * Keytable for remote provided with Delock 61959 + */ +static struct rc_map_table delock_61959[] = { + { 0x866b16, KEY_POWER2 }, /* Power */ + { 0x866b0c, KEY_POWER }, /* Shut Down */ + + { 0x866b00, KEY_1}, + { 0x866b01, KEY_2}, + { 0x866b02, KEY_3}, + { 0x866b03, KEY_4}, + { 0x866b04, KEY_5}, + { 0x866b05, KEY_6}, + { 0x866b06, KEY_7}, + { 0x866b07, KEY_8}, + { 0x866b08, KEY_9}, + { 0x866b14, KEY_0}, + + { 0x866b0a, KEY_ZOOM}, /* Full Screen */ + { 0x866b10, KEY_CAMERA}, /* Photo */ + { 0x866b0e, KEY_CHANNEL}, /* circular arrow / Recall */ + { 0x866b13, KEY_ESC}, /* Back */ + + { 0x866b20, KEY_UP}, + { 0x866b21, KEY_DOWN}, + { 0x866b42, KEY_LEFT}, + { 0x866b43, KEY_RIGHT}, + { 0x866b0b, KEY_OK}, + + { 0x866b11, KEY_CHANNELUP}, + { 0x866b1b, KEY_CHANNELDOWN}, + + { 0x866b12, KEY_VOLUMEUP}, + { 0x866b48, KEY_VOLUMEDOWN}, + { 0x866b44, KEY_MUTE}, + + { 0x866b1a, KEY_RECORD}, + { 0x866b41, KEY_PLAY}, + { 0x866b40, KEY_STOP}, + { 0x866b19, KEY_PAUSE}, + { 0x866b1c, KEY_FASTFORWARD}, /* >> / FWD */ + { 0x866b1e, KEY_REWIND}, /* << / REW */ + +}; + +static struct rc_map_list delock_61959_map = { + .map = { + .scan = delock_61959, + .size = ARRAY_SIZE(delock_61959), + .rc_type = RC_TYPE_NEC, + .name = RC_MAP_DELOCK_61959, + } +}; + +static int __init init_rc_map_delock_61959(void) +{ + return rc_map_register(&delock_61959_map); +} + +static void __exit exit_rc_map_delock_61959(void) +{ + rc_map_unregister(&delock_61959_map); +} + +module_init(init_rc_map_delock_61959) +module_exit(exit_rc_map_delock_61959) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jakob Haufe <sur5r@sur5r.net>"); +MODULE_DESCRIPTION("Delock 61959 remote keytable"); diff --git a/drivers/media/tuners/r820t.c b/drivers/media/tuners/r820t.c index 4835021aa3b6..1c23666468cf 100644 --- a/drivers/media/tuners/r820t.c +++ b/drivers/media/tuners/r820t.c @@ -364,8 +364,8 @@ static void shadow_store(struct r820t_priv *priv, u8 reg, const u8 *val, } if (len <= 0) return; - if (len > NUM_REGS) - len = NUM_REGS; + if (len > NUM_REGS - r) + len = NUM_REGS - r; tuner_dbg("%s: prev reg=%02x len=%d: %*ph\n", __func__, r + REG_SHADOW_START, len, len, val); @@ -1857,9 +1857,9 @@ static int r820t_imr(struct r820t_priv *priv, unsigned imr_mem, bool im_flag) int reg18, reg19, reg1f; if (priv->cfg->xtal > 24000000) - ring_ref = priv->cfg->xtal / 2; + ring_ref = priv->cfg->xtal / 2000; else - ring_ref = priv->cfg->xtal; + ring_ref = priv->cfg->xtal / 1000; n_ring = 15; for (n = 0; n < 16; n++) { @@ -2256,7 +2256,6 @@ static int r820t_release(struct dvb_frontend *fe) mutex_unlock(&r820t_list_mutex); - kfree(fe->tuner_priv); fe->tuner_priv = NULL; return 0; @@ -2311,8 +2310,6 @@ struct dvb_frontend *r820t_attach(struct dvb_frontend *fe, break; } - memcpy(&fe->ops.tuner_ops, &r820t_tuner_ops, sizeof(r820t_tuner_ops)); - if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); @@ -2327,15 +2324,14 @@ struct dvb_frontend *r820t_attach(struct dvb_frontend *fe, tuner_info("Rafael Micro r820t successfully identified\n"); - fe->tuner_priv = priv; - memcpy(&fe->ops.tuner_ops, &r820t_tuner_ops, - sizeof(struct dvb_tuner_ops)); - if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); mutex_unlock(&r820t_list_mutex); + memcpy(&fe->ops.tuner_ops, &r820t_tuner_ops, + sizeof(struct dvb_tuner_ops)); + return fe; err: if (fe->ops.i2c_gate_ctrl) diff --git a/drivers/media/usb/Kconfig b/drivers/media/usb/Kconfig index 0a7d520636a9..cfe8056b91aa 100644 --- a/drivers/media/usb/Kconfig +++ b/drivers/media/usb/Kconfig @@ -1,6 +1,7 @@ +if USB && MEDIA_SUPPORT + menuconfig MEDIA_USB_SUPPORT bool "Media USB Adapters" - depends on USB && MEDIA_SUPPORT help Enable media drivers for USB bus. If you have such devices, say Y. @@ -17,6 +18,7 @@ source "drivers/media/usb/zr364xx/Kconfig" source "drivers/media/usb/stkwebcam/Kconfig" source "drivers/media/usb/s2255/Kconfig" source "drivers/media/usb/sn9c102/Kconfig" +source "drivers/media/usb/usbtv/Kconfig" endif if MEDIA_ANALOG_TV_SUPPORT @@ -52,3 +54,4 @@ source "drivers/media/usb/em28xx/Kconfig" endif endif #MEDIA_USB_SUPPORT +endif #USB diff --git a/drivers/media/usb/Makefile b/drivers/media/usb/Makefile index 7f51d7e5f739..0935f47497a6 100644 --- a/drivers/media/usb/Makefile +++ b/drivers/media/usb/Makefile @@ -20,3 +20,4 @@ obj-$(CONFIG_VIDEO_STK1160) += stk1160/ obj-$(CONFIG_VIDEO_CX231XX) += cx231xx/ obj-$(CONFIG_VIDEO_TM6000) += tm6000/ obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ +obj-$(CONFIG_VIDEO_USBTV) += usbtv/ diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c index 75ac9947cdac..f6154546b5c0 100644 --- a/drivers/media/usb/au0828/au0828-video.c +++ b/drivers/media/usb/au0828/au0828-video.c @@ -36,7 +36,6 @@ #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-event.h> -#include <media/v4l2-chip-ident.h> #include <media/tuner.h> #include "au0828.h" #include "au0828-reg.h" @@ -1638,26 +1637,6 @@ static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv, return 0; } -static int vidioc_g_chip_ident(struct file *file, void *priv, - struct v4l2_dbg_chip_ident *chip) -{ - struct au0828_fh *fh = priv; - struct au0828_dev *dev = fh->dev; - chip->ident = V4L2_IDENT_NONE; - chip->revision = 0; - - if (v4l2_chip_match_host(&chip->match)) { - chip->ident = V4L2_IDENT_AU0828; - return 0; - } - - v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_chip_ident, chip); - if (chip->ident == V4L2_IDENT_NONE) - return -EINVAL; - - return 0; -} - static int vidioc_cropcap(struct file *file, void *priv, struct v4l2_cropcap *cc) { @@ -1779,16 +1758,8 @@ static int vidioc_g_register(struct file *file, void *priv, struct au0828_fh *fh = priv; struct au0828_dev *dev = fh->dev; - switch (reg->match.type) { - case V4L2_CHIP_MATCH_I2C_DRIVER: - v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg); - return 0; - default: - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; - } - reg->val = au0828_read(dev, reg->reg); + reg->size = 1; return 0; } @@ -1798,14 +1769,6 @@ static int vidioc_s_register(struct file *file, void *priv, struct au0828_fh *fh = priv; struct au0828_dev *dev = fh->dev; - switch (reg->match.type) { - case V4L2_CHIP_MATCH_I2C_DRIVER: - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg); - return 0; - default: - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; - } return au0828_writereg(dev, reg->reg, reg->val); } #endif @@ -1943,7 +1906,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_g_register = vidioc_g_register, .vidioc_s_register = vidioc_s_register, #endif - .vidioc_g_chip_ident = vidioc_g_chip_ident, .vidioc_log_status = vidioc_log_status, .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx231xx/cx231xx-417.c index f548db8043d4..2f63029e7a36 100644 --- a/drivers/media/usb/cx231xx/cx231xx-417.c +++ b/drivers/media/usb/cx231xx/cx231xx-417.c @@ -1840,7 +1840,6 @@ static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { .vidioc_streamon = vidioc_streamon, .vidioc_streamoff = vidioc_streamoff, .vidioc_log_status = vidioc_log_status, - .vidioc_g_chip_ident = cx231xx_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = cx231xx_g_register, .vidioc_s_register = cx231xx_s_register, diff --git a/drivers/media/usb/cx231xx/cx231xx-avcore.c b/drivers/media/usb/cx231xx/cx231xx-avcore.c index 235ba657d52e..89de00bf4f82 100644 --- a/drivers/media/usb/cx231xx/cx231xx-avcore.c +++ b/drivers/media/usb/cx231xx/cx231xx-avcore.c @@ -35,7 +35,6 @@ #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> -#include <media/v4l2-chip-ident.h> #include "cx231xx.h" #include "cx231xx-dif.h" diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c index 13249e5a7891..27948e1798eb 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c @@ -29,7 +29,6 @@ #include <media/tuner.h> #include <media/tveeprom.h> #include <media/v4l2-common.h> -#include <media/v4l2-chip-ident.h> #include <media/cx25840.h> #include "dvb-usb-ids.h" diff --git a/drivers/media/usb/cx231xx/cx231xx-vbi.c b/drivers/media/usb/cx231xx/cx231xx-vbi.c index 1340ff268817..c02794274f51 100644 --- a/drivers/media/usb/cx231xx/cx231xx-vbi.c +++ b/drivers/media/usb/cx231xx/cx231xx-vbi.c @@ -32,7 +32,6 @@ #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> -#include <media/v4l2-chip-ident.h> #include <media/msp3400.h> #include <media/tuner.h> diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c index cd221474e1b9..990626101718 100644 --- a/drivers/media/usb/cx231xx/cx231xx-video.c +++ b/drivers/media/usb/cx231xx/cx231xx-video.c @@ -36,7 +36,6 @@ #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-event.h> -#include <media/v4l2-chip-ident.h> #include <media/msp3400.h> #include <media/tuner.h> @@ -1228,179 +1227,93 @@ int cx231xx_s_frequency(struct file *file, void *priv, return rc; } -int cx231xx_g_chip_ident(struct file *file, void *fh, - struct v4l2_dbg_chip_ident *chip) +#ifdef CONFIG_VIDEO_ADV_DEBUG + +int cx231xx_g_chip_info(struct file *file, void *fh, + struct v4l2_dbg_chip_info *chip) { - chip->ident = V4L2_IDENT_NONE; - chip->revision = 0; - if (chip->match.type == V4L2_CHIP_MATCH_HOST) { - if (v4l2_chip_match_host(&chip->match)) - chip->ident = V4L2_IDENT_CX23100; + switch (chip->match.addr) { + case 0: /* Cx231xx - internal registers */ + return 0; + case 1: /* AFE - read byte */ + strlcpy(chip->name, "AFE (byte)", sizeof(chip->name)); + return 0; + case 2: /* Video Block - read byte */ + strlcpy(chip->name, "Video (byte)", sizeof(chip->name)); + return 0; + case 3: /* I2S block - read byte */ + strlcpy(chip->name, "I2S (byte)", sizeof(chip->name)); + return 0; + case 4: /* AFE - read dword */ + strlcpy(chip->name, "AFE (dword)", sizeof(chip->name)); + return 0; + case 5: /* Video Block - read dword */ + strlcpy(chip->name, "Video (dword)", sizeof(chip->name)); + return 0; + case 6: /* I2S Block - read dword */ + strlcpy(chip->name, "I2S (dword)", sizeof(chip->name)); return 0; } return -EINVAL; } -#ifdef CONFIG_VIDEO_ADV_DEBUG - -/* - -R, --list-registers=type=<host/i2cdrv/i2caddr>, - chip=<chip>[,min=<addr>,max=<addr>] - dump registers from <min> to <max> [VIDIOC_DBG_G_REGISTER] - -r, --set-register=type=<host/i2cdrv/i2caddr>, - chip=<chip>,reg=<addr>,val=<val> - set the register [VIDIOC_DBG_S_REGISTER] - - if type == host, then <chip> is the hosts chip ID (default 0) - if type == i2cdrv (default), then <chip> is the I2C driver name or ID - if type == i2caddr, then <chip> is the 7-bit I2C address -*/ - int cx231xx_g_register(struct file *file, void *priv, struct v4l2_dbg_register *reg) { struct cx231xx_fh *fh = priv; struct cx231xx *dev = fh->dev; - int ret = 0; + int ret; u8 value[4] = { 0, 0, 0, 0 }; u32 data = 0; - switch (reg->match.type) { - case V4L2_CHIP_MATCH_HOST: - switch (reg->match.addr) { - case 0: /* Cx231xx - internal registers */ - 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; - break; - case 1: /* AFE - read byte */ - ret = cx231xx_read_i2c_data(dev, AFE_DEVICE_ADDRESS, - (u16)reg->reg, 2, &data, 1); - reg->val = le32_to_cpu(data & 0xff); - break; - case 14: /* AFE - read dword */ - ret = cx231xx_read_i2c_data(dev, AFE_DEVICE_ADDRESS, - (u16)reg->reg, 2, &data, 4); - reg->val = le32_to_cpu(data); - break; - case 2: /* Video Block - read byte */ - ret = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS, - (u16)reg->reg, 2, &data, 1); - reg->val = le32_to_cpu(data & 0xff); - break; - case 24: /* Video Block - read dword */ - ret = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS, - (u16)reg->reg, 2, &data, 4); - reg->val = le32_to_cpu(data); - break; - case 3: /* I2S block - read byte */ - ret = cx231xx_read_i2c_data(dev, - I2S_BLK_DEVICE_ADDRESS, - (u16)reg->reg, 1, - &data, 1); - reg->val = le32_to_cpu(data & 0xff); - break; - case 34: /* I2S Block - read dword */ - ret = - cx231xx_read_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS, - (u16)reg->reg, 1, &data, 4); - reg->val = le32_to_cpu(data); - break; - } - return ret < 0 ? ret : 0; - - case V4L2_CHIP_MATCH_I2C_DRIVER: - call_all(dev, core, g_register, reg); - return 0; - case V4L2_CHIP_MATCH_I2C_ADDR:/*for register debug*/ - switch (reg->match.addr) { - case 0: /* Cx231xx - internal registers */ - 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; - - break; - case 0x600:/* AFE - read byte */ - ret = cx231xx_read_i2c_master(dev, AFE_DEVICE_ADDRESS, - (u16)reg->reg, 2, - &data, 1 , 0); - reg->val = le32_to_cpu(data & 0xff); - break; - - case 0x880:/* Video Block - read byte */ - if (reg->reg < 0x0b) { - ret = cx231xx_read_i2c_master(dev, - VID_BLK_I2C_ADDRESS, - (u16)reg->reg, 2, - &data, 1 , 0); - reg->val = le32_to_cpu(data & 0xff); - } else { - ret = cx231xx_read_i2c_master(dev, - VID_BLK_I2C_ADDRESS, - (u16)reg->reg, 2, - &data, 4 , 0); - reg->val = le32_to_cpu(data); - } - break; - case 0x980: - ret = cx231xx_read_i2c_master(dev, - I2S_BLK_DEVICE_ADDRESS, - (u16)reg->reg, 1, - &data, 1 , 0); - reg->val = le32_to_cpu(data & 0xff); - break; - case 0x400: - ret = - cx231xx_read_i2c_master(dev, 0x40, - (u16)reg->reg, 1, - &data, 1 , 0); - reg->val = le32_to_cpu(data & 0xff); - break; - case 0xc01: - ret = - cx231xx_read_i2c_master(dev, 0xc0, - (u16)reg->reg, 2, - &data, 38, 1); - reg->val = le32_to_cpu(data); - break; - case 0x022: - ret = - cx231xx_read_i2c_master(dev, 0x02, - (u16)reg->reg, 1, - &data, 1, 2); - reg->val = le32_to_cpu(data & 0xff); - break; - case 0x322: - ret = cx231xx_read_i2c_master(dev, - 0x32, - (u16)reg->reg, 1, - &data, 4 , 2); - reg->val = le32_to_cpu(data); - break; - case 0x342: - ret = cx231xx_read_i2c_master(dev, - 0x34, - (u16)reg->reg, 1, - &data, 4 , 2); - reg->val = le32_to_cpu(data); - break; - - default: - cx231xx_info("no match device address!!\n"); - break; - } - return ret < 0 ? ret : 0; - /*return -EINVAL;*/ + switch (reg->match.addr) { + case 0: /* Cx231xx - internal registers */ + 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; + reg->size = 4; + break; + case 1: /* AFE - read byte */ + ret = cx231xx_read_i2c_data(dev, AFE_DEVICE_ADDRESS, + (u16)reg->reg, 2, &data, 1); + reg->val = data; + reg->size = 1; + break; + case 2: /* Video Block - read byte */ + ret = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS, + (u16)reg->reg, 2, &data, 1); + reg->val = data; + reg->size = 1; + break; + case 3: /* I2S block - read byte */ + ret = cx231xx_read_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS, + (u16)reg->reg, 1, &data, 1); + reg->val = data; + reg->size = 1; + break; + case 4: /* AFE - read dword */ + ret = cx231xx_read_i2c_data(dev, AFE_DEVICE_ADDRESS, + (u16)reg->reg, 2, &data, 4); + reg->val = data; + reg->size = 4; + break; + case 5: /* Video Block - read dword */ + ret = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS, + (u16)reg->reg, 2, &data, 4); + reg->val = data; + reg->size = 4; + break; + case 6: /* I2S Block - read dword */ + ret = cx231xx_read_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS, + (u16)reg->reg, 1, &data, 4); + reg->val = data; + reg->size = 4; + break; default: - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; + return -EINVAL; } - - call_all(dev, core, g_register, reg); - - return ret; + return ret < 0 ? ret : 0; } int cx231xx_s_register(struct file *file, void *priv, @@ -1408,165 +1321,46 @@ int cx231xx_s_register(struct file *file, void *priv, { struct cx231xx_fh *fh = priv; struct cx231xx *dev = fh->dev; - int ret = 0; - __le64 buf; - u32 value; + int ret; u8 data[4] = { 0, 0, 0, 0 }; - buf = cpu_to_le64(reg->val); - - switch (reg->match.type) { - case V4L2_CHIP_MATCH_HOST: - { - value = (u32) buf & 0xffffffff; - - switch (reg->match.addr) { - case 0: /* cx231xx internal registers */ - data[0] = (u8) value; - data[1] = (u8) (value >> 8); - data[2] = (u8) (value >> 16); - data[3] = (u8) (value >> 24); - ret = cx231xx_write_ctrl_reg(dev, - VRT_SET_REGISTER, - (u16)reg->reg, data, - 4); - break; - case 1: /* AFE - read byte */ - ret = cx231xx_write_i2c_data(dev, - AFE_DEVICE_ADDRESS, - (u16)reg->reg, 2, - value, 1); - break; - case 14: /* AFE - read dword */ - ret = cx231xx_write_i2c_data(dev, - AFE_DEVICE_ADDRESS, - (u16)reg->reg, 2, - value, 4); - break; - case 2: /* Video Block - read byte */ - ret = - cx231xx_write_i2c_data(dev, - VID_BLK_I2C_ADDRESS, - (u16)reg->reg, 2, - value, 1); - break; - case 24: /* Video Block - read dword */ - ret = - cx231xx_write_i2c_data(dev, - VID_BLK_I2C_ADDRESS, - (u16)reg->reg, 2, - value, 4); - break; - case 3: /* I2S block - read byte */ - ret = - cx231xx_write_i2c_data(dev, - I2S_BLK_DEVICE_ADDRESS, - (u16)reg->reg, 1, - value, 1); - break; - case 34: /* I2S block - read dword */ - ret = - cx231xx_write_i2c_data(dev, - I2S_BLK_DEVICE_ADDRESS, - (u16)reg->reg, 1, - value, 4); - break; - } - } - return ret < 0 ? ret : 0; - case V4L2_CHIP_MATCH_I2C_ADDR: - { - value = (u32) buf & 0xffffffff; - - switch (reg->match.addr) { - case 0:/*cx231xx internal registers*/ - data[0] = (u8) value; - data[1] = (u8) (value >> 8); - data[2] = (u8) (value >> 16); - data[3] = (u8) (value >> 24); - ret = cx231xx_write_ctrl_reg(dev, - VRT_SET_REGISTER, - (u16)reg->reg, data, - 4); - break; - case 0x600:/* AFE - read byte */ - ret = cx231xx_write_i2c_master(dev, - AFE_DEVICE_ADDRESS, - (u16)reg->reg, 2, - value, 1 , 0); - break; - - case 0x880:/* Video Block - read byte */ - if (reg->reg < 0x0b) - cx231xx_write_i2c_master(dev, - VID_BLK_I2C_ADDRESS, - (u16)reg->reg, 2, - value, 1, 0); - else - cx231xx_write_i2c_master(dev, - VID_BLK_I2C_ADDRESS, - (u16)reg->reg, 2, - value, 4, 0); - break; - case 0x980: - ret = - cx231xx_write_i2c_master(dev, - I2S_BLK_DEVICE_ADDRESS, - (u16)reg->reg, 1, - value, 1, 0); - break; - case 0x400: - ret = - cx231xx_write_i2c_master(dev, - 0x40, - (u16)reg->reg, 1, - value, 1, 0); - break; - case 0xc01: - ret = - cx231xx_write_i2c_master(dev, - 0xc0, - (u16)reg->reg, 1, - value, 1, 1); - break; - - case 0x022: - ret = - cx231xx_write_i2c_master(dev, - 0x02, - (u16)reg->reg, 1, - value, 1, 2); - break; - case 0x322: - ret = - cx231xx_write_i2c_master(dev, - 0x32, - (u16)reg->reg, 1, - value, 4, 2); - break; - - case 0x342: - ret = - cx231xx_write_i2c_master(dev, - 0x34, - (u16)reg->reg, 1, - value, 4, 2); - break; - default: - cx231xx_info("no match device address, " - "the value is %x\n", reg->match.addr); - break; - - } - - } - default: + switch (reg->match.addr) { + case 0: /* cx231xx internal registers */ + data[0] = (u8) reg->val; + data[1] = (u8) (reg->val >> 8); + data[2] = (u8) (reg->val >> 16); + data[3] = (u8) (reg->val >> 24); + ret = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, + (u16)reg->reg, data, 4); + break; + case 1: /* AFE - write byte */ + ret = cx231xx_write_i2c_data(dev, AFE_DEVICE_ADDRESS, + (u16)reg->reg, 2, reg->val, 1); + break; + case 2: /* Video Block - write byte */ + ret = cx231xx_write_i2c_data(dev, VID_BLK_I2C_ADDRESS, + (u16)reg->reg, 2, reg->val, 1); + break; + case 3: /* I2S block - write byte */ + ret = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS, + (u16)reg->reg, 1, reg->val, 1); + break; + case 4: /* AFE - write dword */ + ret = cx231xx_write_i2c_data(dev, AFE_DEVICE_ADDRESS, + (u16)reg->reg, 2, reg->val, 4); + break; + case 5: /* Video Block - write dword */ + ret = cx231xx_write_i2c_data(dev, VID_BLK_I2C_ADDRESS, + (u16)reg->reg, 2, reg->val, 4); break; + case 6: /* I2S block - write dword */ + ret = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS, + (u16)reg->reg, 1, reg->val, 4); + break; + default: + return -EINVAL; } - - call_all(dev, core, s_register, reg); - - return ret; + return ret < 0 ? ret : 0; } #endif @@ -2208,8 +2002,8 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_s_tuner = cx231xx_s_tuner, .vidioc_g_frequency = cx231xx_g_frequency, .vidioc_s_frequency = cx231xx_s_frequency, - .vidioc_g_chip_ident = cx231xx_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_chip_info = cx231xx_g_chip_info, .vidioc_g_register = cx231xx_g_register, .vidioc_s_register = cx231xx_s_register, #endif @@ -2240,8 +2034,8 @@ static const struct v4l2_ioctl_ops radio_ioctl_ops = { .vidioc_s_tuner = radio_s_tuner, .vidioc_g_frequency = cx231xx_g_frequency, .vidioc_s_frequency = cx231xx_s_frequency, - .vidioc_g_chip_ident = cx231xx_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_chip_info = cx231xx_g_chip_info, .vidioc_g_register = cx231xx_g_register, .vidioc_s_register = cx231xx_s_register, #endif diff --git a/drivers/media/usb/cx231xx/cx231xx.h b/drivers/media/usb/cx231xx/cx231xx.h index 5ad9fd61d3c8..e812119ea7a8 100644 --- a/drivers/media/usb/cx231xx/cx231xx.h +++ b/drivers/media/usb/cx231xx/cx231xx.h @@ -945,7 +945,7 @@ int cx231xx_enum_input(struct file *file, void *priv, struct v4l2_input *i); int cx231xx_g_input(struct file *file, void *priv, unsigned int *i); int cx231xx_s_input(struct file *file, void *priv, unsigned int i); -int cx231xx_g_chip_ident(struct file *file, void *fh, struct v4l2_dbg_chip_ident *chip); +int cx231xx_g_chip_info(struct file *file, void *fh, struct v4l2_dbg_chip_info *chip); int cx231xx_g_register(struct file *file, void *priv, struct v4l2_dbg_register *reg); int cx231xx_s_register(struct file *file, void *priv, diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c index b638fc1cd574..1ea17dc2a76e 100644 --- a/drivers/media/usb/dvb-usb-v2/af9035.c +++ b/drivers/media/usb/dvb-usb-v2/af9035.c @@ -55,7 +55,7 @@ static int af9035_ctrl_msg(struct dvb_usb_device *d, struct usb_req *req) if (req->wlen > (BUF_LEN - REQ_HDR_LEN - CHECKSUM_LEN) || req->rlen > (BUF_LEN - ACK_HDR_LEN - CHECKSUM_LEN)) { dev_err(&d->udev->dev, "%s: too much data wlen=%d rlen=%d\n", - __func__, req->wlen, req->rlen); + KBUILD_MODNAME, req->wlen, req->rlen); ret = -EINVAL; goto exit; } @@ -91,9 +91,10 @@ static int af9035_ctrl_msg(struct dvb_usb_device *d, struct usb_req *req) checksum = af9035_checksum(state->buf, rlen - 2); tmp_checksum = (state->buf[rlen - 2] << 8) | state->buf[rlen - 1]; if (tmp_checksum != checksum) { - dev_err(&d->udev->dev, "%s: command=%02x checksum mismatch " \ - "(%04x != %04x)\n", KBUILD_MODNAME, req->cmd, - tmp_checksum, checksum); + dev_err(&d->udev->dev, + "%s: command=%02x checksum mismatch (%04x != %04x)\n", + KBUILD_MODNAME, req->cmd, tmp_checksum, + checksum); ret = -EIO; goto exit; } @@ -268,11 +269,29 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap, memcpy(&buf[5], msg[0].buf, msg[0].len); ret = af9035_ctrl_msg(d, &req); } + } else if (num == 1 && (msg[0].flags & I2C_M_RD)) { + if (msg[0].len > 40) { + /* TODO: correct limits > 40 */ + ret = -EOPNOTSUPP; + } else { + /* I2C */ + u8 buf[5]; + struct usb_req req = { CMD_I2C_RD, 0, sizeof(buf), + buf, msg[0].len, msg[0].buf }; + req.mbox |= ((msg[0].addr & 0x80) >> 3); + buf[0] = msg[0].len; + buf[1] = msg[0].addr << 1; + buf[2] = 0x00; /* reg addr len */ + buf[3] = 0x00; /* reg addr MSB */ + buf[4] = 0x00; /* reg addr LSB */ + ret = af9035_ctrl_msg(d, &req); + } } else { /* - * We support only two kind of I2C transactions: - * 1) 1 x read + 1 x write + * We support only three kind of I2C transactions: + * 1) 1 x read + 1 x write (repeated start) * 2) 1 x write + * 3) 1 x read */ ret = -EOPNOTSUPP; } @@ -317,8 +336,8 @@ static int af9035_identify_state(struct dvb_usb_device *d, const char **name) dev_info(&d->udev->dev, "%s: prechip_version=%02x chip_version=%02x chip_type=%04x\n", - __func__, state->prechip_version, state->chip_version, - state->chip_type); + KBUILD_MODNAME, state->prechip_version, + state->chip_version, state->chip_type); if (state->chip_type == 0x9135) { if (state->chip_version == 0x02) @@ -382,9 +401,10 @@ static int af9035_download_firmware_old(struct dvb_usb_device *d, hdr_checksum = fw->data[fw->size - i + 5] << 8; hdr_checksum |= fw->data[fw->size - i + 6] << 0; - dev_dbg(&d->udev->dev, "%s: core=%d addr=%04x data_len=%d " \ - "checksum=%04x\n", __func__, hdr_core, hdr_addr, - hdr_data_len, hdr_checksum); + dev_dbg(&d->udev->dev, + "%s: core=%d addr=%04x data_len=%d checksum=%04x\n", + __func__, hdr_core, hdr_addr, hdr_data_len, + hdr_checksum); if (((hdr_core != 1) && (hdr_core != 2)) || (hdr_data_len > i)) { @@ -489,7 +509,7 @@ static int af9035_download_firmware(struct dvb_usb_device *d, u8 rbuf[4]; u8 tmp; struct usb_req req = { 0, 0, 0, NULL, 0, NULL }; - struct usb_req req_fw_ver = { CMD_FW_QUERYINFO, 0, 1, wbuf, 4, rbuf } ; + struct usb_req req_fw_ver = { CMD_FW_QUERYINFO, 0, 1, wbuf, 4, rbuf }; dev_dbg(&d->udev->dev, "%s:\n", __func__); /* @@ -498,11 +518,11 @@ static int af9035_download_firmware(struct dvb_usb_device *d, * which is done by master demod. * Master feeds also clock and controls power via GPIO. */ - ret = af9035_rd_reg(d, state->eeprom_addr + EEPROM_DUAL_MODE, &tmp); + ret = af9035_rd_reg(d, state->eeprom_addr + EEPROM_TS_MODE, &tmp); if (ret < 0) goto err; - if (tmp) { + if (tmp == 1 || tmp == 3) { /* configure gpioh1, reset & power slave demod */ ret = af9035_wr_reg_mask(d, 0x00d8b0, 0x01, 0x01); if (ret < 0) @@ -620,13 +640,15 @@ static int af9035_read_config(struct dvb_usb_device *d) } /* check if there is dual tuners */ - ret = af9035_rd_reg(d, state->eeprom_addr + EEPROM_DUAL_MODE, &tmp); + ret = af9035_rd_reg(d, state->eeprom_addr + EEPROM_TS_MODE, &tmp); if (ret < 0) goto err; - state->dual_mode = tmp; - dev_dbg(&d->udev->dev, "%s: dual mode=%d\n", __func__, - state->dual_mode); + if (tmp == 1 || tmp == 3) + state->dual_mode = true; + + dev_dbg(&d->udev->dev, "%s: ts mode=%d dual mode=%d\n", __func__, + tmp, state->dual_mode); if (state->dual_mode) { /* read 2nd demodulator I2C address */ @@ -1200,9 +1222,9 @@ static int af9035_init(struct dvb_usb_device *d) { 0x80f9a4, 0x00, 0x01 }, }; - dev_dbg(&d->udev->dev, "%s: USB speed=%d frame_size=%04x " \ - "packet_size=%02x\n", __func__, - d->udev->speed, frame_size, packet_size); + dev_dbg(&d->udev->dev, + "%s: USB speed=%d frame_size=%04x packet_size=%02x\n", + __func__, d->udev->speed, frame_size, packet_size); /* init endpoints */ for (i = 0; i < ARRAY_SIZE(tab); i++) { @@ -1477,7 +1499,7 @@ static const struct usb_device_id af9035_id_table[] = { &af9035_props, "AVerMedia Twinstar (A825)", NULL) }, { DVB_USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3100MINI_PLUS, &af9035_props, "Asus U3100Mini Plus", NULL) }, - { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00aa, + { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00aa, &af9035_props, "TerraTec Cinergy T Stick (rev. 2)", NULL) }, /* IT9135 devices */ #if 0 diff --git a/drivers/media/usb/dvb-usb-v2/af9035.h b/drivers/media/usb/dvb-usb-v2/af9035.h index b5827ca3a01e..a1c68d829b8c 100644 --- a/drivers/media/usb/dvb-usb-v2/af9035.h +++ b/drivers/media/usb/dvb-usb-v2/af9035.h @@ -100,8 +100,13 @@ static const u32 clock_lut_it9135[] = { * eeprom is memory mapped as read only. Writing that memory mapped address * will not corrupt eeprom. * - * eeprom has value 0x00 single mode and 0x03 for dual mode as far as I have - * seen to this day. + * TS mode: + * 0 TS + * 1 DCA + PIP + * 3 PIP + * n DCA + * + * Values 0 and 3 are seen to this day. 0 for single TS and 3 for dual TS. */ #define EEPROM_BASE_AF9035 0x42fd @@ -109,7 +114,7 @@ static const u32 clock_lut_it9135[] = { #define EEPROM_SHIFT 0x10 #define EEPROM_IR_MODE 0x10 -#define EEPROM_DUAL_MODE 0x29 +#define EEPROM_TS_MODE 0x29 #define EEPROM_2ND_DEMOD_ADDR 0x2a #define EEPROM_IR_TYPE 0x2c #define EEPROM_1_IF_L 0x30 diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb.h b/drivers/media/usb/dvb-usb-v2/dvb_usb.h index 658c6d47fdff..399916bd588f 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb.h +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb.h @@ -140,7 +140,7 @@ struct dvb_usb_rc { int (*change_protocol)(struct rc_dev *dev, u64 *rc_type); int (*query) (struct dvb_usb_device *d); unsigned int interval; - const enum rc_driver_type driver_type; + enum rc_driver_type driver_type; bool bulk_mode; }; diff --git a/drivers/media/usb/dvb-usb-v2/it913x.c b/drivers/media/usb/dvb-usb-v2/it913x.c index e48cdeb9df41..1cb6899cf797 100644 --- a/drivers/media/usb/dvb-usb-v2/it913x.c +++ b/drivers/media/usb/dvb-usb-v2/it913x.c @@ -45,7 +45,7 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))."); static int dvb_usb_it913x_firmware; module_param_named(firmware, dvb_usb_it913x_firmware, int, 0644); -MODULE_PARM_DESC(firmware, "set firmware 0=auto"\ +MODULE_PARM_DESC(firmware, "set firmware 0=auto "\ "1=IT9137 2=IT9135 V1 3=IT9135 V2"); #define FW_IT9137 "dvb-usb-it9137-01.fw" #define FW_IT9135_V1 "dvb-usb-it9135-01.fw" @@ -796,6 +796,9 @@ static const struct usb_device_id it913x_id_table[] = { { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835B_4835, &it913x_properties, "Avermedia A835B(4835)", RC_MAP_IT913X_V2) }, + { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_CTVDIGDUAL_V2, + &it913x_properties, "Digital Dual TV Receiver CTVDIGDUAL_V2", + RC_MAP_IT913X_V1) }, {} /* Terminating entry */ }; diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c index ef4c65fcbb73..879c529640f7 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c @@ -31,8 +31,6 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))."); if (mxl111sf_tuner_debug) \ mxl_printk(KERN_DEBUG, fmt, ##arg) -#define err pr_err - /* ------------------------------------------------------------------------ */ struct mxl111sf_tuner_state { @@ -113,7 +111,7 @@ static struct mxl111sf_reg_ctrl_info *mxl111sf_calc_phy_tune_regs(u32 freq, filt_bw = 63; break; default: - err("%s: invalid bandwidth setting!", __func__); + pr_err("%s: invalid bandwidth setting!", __func__); return NULL; } @@ -304,12 +302,12 @@ static int mxl111sf_tuner_set_params(struct dvb_frontend *fe) bw = 8; break; default: - err("%s: bandwidth not set!", __func__); + pr_err("%s: bandwidth not set!", __func__); return -EINVAL; } break; default: - err("%s: modulation type not supported!", __func__); + pr_err("%s: modulation type not supported!", __func__); return -EINVAL; } ret = mxl1x1sf_tune_rf(fe, c->frequency, bw); diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c index efdcb15358f1..e97964ef7f56 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c @@ -52,12 +52,6 @@ MODULE_PARM_DESC(rfswitch, "force rf switch position (0=auto, 1=ext, 2=int)."); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); -#define deb_info pr_debug -#define deb_reg pr_debug -#define deb_adv pr_debug -#define err pr_err -#define info pr_info - int mxl111sf_ctrl_msg(struct dvb_usb_device *d, u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen) { @@ -65,7 +59,7 @@ int mxl111sf_ctrl_msg(struct dvb_usb_device *d, int ret; u8 sndbuf[1+wlen]; - deb_adv("%s(wlen = %d, rlen = %d)\n", __func__, wlen, rlen); + pr_debug("%s(wlen = %d, rlen = %d)\n", __func__, wlen, rlen); memset(sndbuf, 0, 1+wlen); @@ -98,12 +92,12 @@ int mxl111sf_read_reg(struct mxl111sf_state *state, u8 addr, u8 *data) if (buf[0] == addr) *data = buf[1]; else { - err("invalid response reading reg: 0x%02x != 0x%02x, 0x%02x", + pr_err("invalid response reading reg: 0x%02x != 0x%02x, 0x%02x", addr, buf[0], buf[1]); ret = -EINVAL; } - deb_reg("R: (0x%02x, 0x%02x)\n", addr, *data); + pr_debug("R: (0x%02x, 0x%02x)\n", addr, *data); fail: return ret; } @@ -113,11 +107,11 @@ int mxl111sf_write_reg(struct mxl111sf_state *state, u8 addr, u8 data) u8 buf[] = { addr, data }; int ret; - deb_reg("W: (0x%02x, 0x%02x)\n", addr, data); + pr_debug("W: (0x%02x, 0x%02x)\n", addr, data); ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_WRITE, buf, 2, NULL, 0); if (mxl_fail(ret)) - err("error writing reg: 0x%02x, val: 0x%02x", addr, data); + pr_err("error writing reg: 0x%02x, val: 0x%02x", addr, data); return ret; } @@ -134,7 +128,7 @@ int mxl111sf_write_reg_mask(struct mxl111sf_state *state, #if 1 /* dont know why this usually errors out on the first try */ if (mxl_fail(ret)) - err("error writing addr: 0x%02x, mask: 0x%02x, " + pr_err("error writing addr: 0x%02x, mask: 0x%02x, " "data: 0x%02x, retrying...", addr, mask, data); ret = mxl111sf_read_reg(state, addr, &val); @@ -167,7 +161,7 @@ int mxl111sf_ctrl_program_regs(struct mxl111sf_state *state, ctrl_reg_info[i].mask, ctrl_reg_info[i].data); if (mxl_fail(ret)) { - err("failed on reg #%d (0x%02x)", i, + pr_err("failed on reg #%d (0x%02x)", i, ctrl_reg_info[i].addr); break; } @@ -225,7 +219,7 @@ static int mxl1x1sf_get_chip_info(struct mxl111sf_state *state) mxl_rev = "UNKNOWN REVISION"; break; } - info("%s detected, %s (0x%x)", mxl_chip, mxl_rev, ver); + pr_info("%s detected, %s (0x%x)", mxl_chip, mxl_rev, ver); fail: return ret; } @@ -239,7 +233,7 @@ fail: " on first probe attempt"); \ ___ret = mxl1x1sf_get_chip_info(state); \ if (mxl_fail(___ret)) \ - err("failed to get chip info during probe"); \ + pr_err("failed to get chip info during probe"); \ else \ mxl_debug("probe needed a retry " \ "in order to succeed."); \ @@ -270,14 +264,14 @@ static int mxl111sf_adap_fe_init(struct dvb_frontend *fe) goto fail; } - deb_info("%s()\n", __func__); + pr_debug("%s()\n", __func__); mutex_lock(&state->fe_lock); state->alt_mode = adap_state->alt_mode; if (usb_set_interface(d->udev, 0, state->alt_mode) < 0) - err("set interface failed"); + pr_err("set interface failed"); err = mxl1x1sf_soft_reset(state); mxl_fail(err); @@ -326,7 +320,7 @@ static int mxl111sf_adap_fe_sleep(struct dvb_frontend *fe) goto fail; } - deb_info("%s()\n", __func__); + pr_debug("%s()\n", __func__); err = (adap_state->fe_sleep) ? adap_state->fe_sleep(fe) : 0; @@ -344,7 +338,7 @@ static int mxl111sf_ep6_streaming_ctrl(struct dvb_frontend *fe, int onoff) struct mxl111sf_adap_state *adap_state = &state->adap_state[fe->id]; int ret = 0; - deb_info("%s(%d)\n", __func__, onoff); + pr_debug("%s(%d)\n", __func__, onoff); if (onoff) { ret = mxl111sf_enable_usb_output(state); @@ -368,7 +362,7 @@ static int mxl111sf_ep5_streaming_ctrl(struct dvb_frontend *fe, int onoff) struct mxl111sf_state *state = fe_to_priv(fe); int ret = 0; - deb_info("%s(%d)\n", __func__, onoff); + pr_debug("%s(%d)\n", __func__, onoff); if (onoff) { ret = mxl111sf_enable_usb_output(state); @@ -394,7 +388,7 @@ static int mxl111sf_ep4_streaming_ctrl(struct dvb_frontend *fe, int onoff) struct mxl111sf_state *state = fe_to_priv(fe); int ret = 0; - deb_info("%s(%d)\n", __func__, onoff); + pr_debug("%s(%d)\n", __func__, onoff); if (onoff) { ret = mxl111sf_enable_usb_output(state); @@ -424,7 +418,7 @@ static int mxl111sf_lgdt3305_frontend_attach(struct dvb_usb_adapter *adap, u8 fe struct mxl111sf_adap_state *adap_state = &state->adap_state[fe_id]; int ret; - deb_adv("%s()\n", __func__); + pr_debug("%s()\n", __func__); /* save a pointer to the dvb_usb_device in device state */ state->d = d; @@ -432,7 +426,7 @@ static int mxl111sf_lgdt3305_frontend_attach(struct dvb_usb_adapter *adap, u8 fe state->alt_mode = adap_state->alt_mode; if (usb_set_interface(d->udev, 0, state->alt_mode) < 0) - err("set interface failed"); + pr_err("set interface failed"); state->gpio_mode = MXL111SF_GPIO_MOD_ATSC; adap_state->gpio_mode = state->gpio_mode; @@ -495,7 +489,7 @@ static int mxl111sf_lg2160_frontend_attach(struct dvb_usb_adapter *adap, u8 fe_i struct mxl111sf_adap_state *adap_state = &state->adap_state[fe_id]; int ret; - deb_adv("%s()\n", __func__); + pr_debug("%s()\n", __func__); /* save a pointer to the dvb_usb_device in device state */ state->d = d; @@ -503,7 +497,7 @@ static int mxl111sf_lg2160_frontend_attach(struct dvb_usb_adapter *adap, u8 fe_i state->alt_mode = adap_state->alt_mode; if (usb_set_interface(d->udev, 0, state->alt_mode) < 0) - err("set interface failed"); + pr_err("set interface failed"); state->gpio_mode = MXL111SF_GPIO_MOD_MH; adap_state->gpio_mode = state->gpio_mode; @@ -580,7 +574,7 @@ static int mxl111sf_lg2161_frontend_attach(struct dvb_usb_adapter *adap, u8 fe_i struct mxl111sf_adap_state *adap_state = &state->adap_state[fe_id]; int ret; - deb_adv("%s()\n", __func__); + pr_debug("%s()\n", __func__); /* save a pointer to the dvb_usb_device in device state */ state->d = d; @@ -588,7 +582,7 @@ static int mxl111sf_lg2161_frontend_attach(struct dvb_usb_adapter *adap, u8 fe_i state->alt_mode = adap_state->alt_mode; if (usb_set_interface(d->udev, 0, state->alt_mode) < 0) - err("set interface failed"); + pr_err("set interface failed"); state->gpio_mode = MXL111SF_GPIO_MOD_MH; adap_state->gpio_mode = state->gpio_mode; @@ -667,7 +661,7 @@ static int mxl111sf_lg2161_ep6_frontend_attach(struct dvb_usb_adapter *adap, u8 struct mxl111sf_adap_state *adap_state = &state->adap_state[fe_id]; int ret; - deb_adv("%s()\n", __func__); + pr_debug("%s()\n", __func__); /* save a pointer to the dvb_usb_device in device state */ state->d = d; @@ -675,7 +669,7 @@ static int mxl111sf_lg2161_ep6_frontend_attach(struct dvb_usb_adapter *adap, u8 state->alt_mode = adap_state->alt_mode; if (usb_set_interface(d->udev, 0, state->alt_mode) < 0) - err("set interface failed"); + pr_err("set interface failed"); state->gpio_mode = MXL111SF_GPIO_MOD_MH; adap_state->gpio_mode = state->gpio_mode; @@ -742,7 +736,7 @@ static int mxl111sf_attach_demod(struct dvb_usb_adapter *adap, u8 fe_id) struct mxl111sf_adap_state *adap_state = &state->adap_state[fe_id]; int ret; - deb_adv("%s()\n", __func__); + pr_debug("%s()\n", __func__); /* save a pointer to the dvb_usb_device in device state */ state->d = d; @@ -750,7 +744,7 @@ static int mxl111sf_attach_demod(struct dvb_usb_adapter *adap, u8 fe_id) state->alt_mode = adap_state->alt_mode; if (usb_set_interface(d->udev, 0, state->alt_mode) < 0) - err("set interface failed"); + pr_err("set interface failed"); state->gpio_mode = MXL111SF_GPIO_MOD_DVBT; adap_state->gpio_mode = state->gpio_mode; @@ -802,7 +796,7 @@ static inline int mxl111sf_set_ant_path(struct mxl111sf_state *state, } #define DbgAntHunt(x, pwr0, pwr1, pwr2, pwr3) \ - err("%s(%d) FINAL input set to %s rxPwr:%d|%d|%d|%d\n", \ + pr_err("%s(%d) FINAL input set to %s rxPwr:%d|%d|%d|%d\n", \ __func__, __LINE__, \ (ANT_PATH_EXTERNAL == x) ? "EXTERNAL" : "INTERNAL", \ pwr0, pwr1, pwr2, pwr3) @@ -868,7 +862,7 @@ static int mxl111sf_attach_tuner(struct dvb_usb_adapter *adap) struct mxl111sf_state *state = adap_to_priv(adap); int i; - deb_adv("%s()\n", __func__); + pr_debug("%s()\n", __func__); for (i = 0; i < state->num_frontends; i++) { if (dvb_attach(mxl111sf_tuner_attach, adap->fe[i], state, @@ -902,7 +896,7 @@ static int mxl111sf_init(struct dvb_usb_device *d) ret = get_chip_info(state); if (mxl_fail(ret)) - err("failed to get chip info during probe"); + pr_err("failed to get chip info during probe"); mutex_init(&state->fe_lock); @@ -950,7 +944,7 @@ static int mxl111sf_frontend_attach_mh(struct dvb_usb_adapter *adap) static int mxl111sf_frontend_attach_atsc_mh(struct dvb_usb_adapter *adap) { int ret; - deb_info("%s\n", __func__); + pr_debug("%s\n", __func__); ret = mxl111sf_lgdt3305_frontend_attach(adap, 0); if (ret < 0) @@ -970,7 +964,7 @@ static int mxl111sf_frontend_attach_atsc_mh(struct dvb_usb_adapter *adap) static int mxl111sf_frontend_attach_mercury(struct dvb_usb_adapter *adap) { int ret; - deb_info("%s\n", __func__); + pr_debug("%s\n", __func__); ret = mxl111sf_lgdt3305_frontend_attach(adap, 0); if (ret < 0) @@ -990,7 +984,7 @@ static int mxl111sf_frontend_attach_mercury(struct dvb_usb_adapter *adap) static int mxl111sf_frontend_attach_mercury_mh(struct dvb_usb_adapter *adap) { int ret; - deb_info("%s\n", __func__); + pr_debug("%s\n", __func__); ret = mxl111sf_attach_demod(adap, 0); if (ret < 0) @@ -1006,7 +1000,7 @@ static int mxl111sf_frontend_attach_mercury_mh(struct dvb_usb_adapter *adap) static void mxl111sf_stream_config_bulk(struct usb_data_stream_properties *stream, u8 endpoint) { - deb_info("%s: endpoint=%d size=8192\n", __func__, endpoint); + pr_debug("%s: endpoint=%d size=8192\n", __func__, endpoint); stream->type = USB_BULK; stream->count = 5; stream->endpoint = endpoint; @@ -1016,7 +1010,7 @@ static void mxl111sf_stream_config_bulk(struct usb_data_stream_properties *strea static void mxl111sf_stream_config_isoc(struct usb_data_stream_properties *stream, u8 endpoint, int framesperurb, int framesize) { - deb_info("%s: endpoint=%d size=%d\n", __func__, endpoint, + pr_debug("%s: endpoint=%d size=%d\n", __func__, endpoint, framesperurb * framesize); stream->type = USB_ISOC; stream->count = 5; @@ -1035,7 +1029,7 @@ static void mxl111sf_stream_config_isoc(struct usb_data_stream_properties *strea static int mxl111sf_get_stream_config_dvbt(struct dvb_frontend *fe, u8 *ts_type, struct usb_data_stream_properties *stream) { - deb_info("%s: fe=%d\n", __func__, fe->id); + pr_debug("%s: fe=%d\n", __func__, fe->id); *ts_type = DVB_USB_FE_TS_TYPE_188; if (dvb_usb_mxl111sf_isoc) @@ -1076,7 +1070,7 @@ static struct dvb_usb_device_properties mxl111sf_props_dvbt = { static int mxl111sf_get_stream_config_atsc(struct dvb_frontend *fe, u8 *ts_type, struct usb_data_stream_properties *stream) { - deb_info("%s: fe=%d\n", __func__, fe->id); + pr_debug("%s: fe=%d\n", __func__, fe->id); *ts_type = DVB_USB_FE_TS_TYPE_188; if (dvb_usb_mxl111sf_isoc) @@ -1117,7 +1111,7 @@ static struct dvb_usb_device_properties mxl111sf_props_atsc = { static int mxl111sf_get_stream_config_mh(struct dvb_frontend *fe, u8 *ts_type, struct usb_data_stream_properties *stream) { - deb_info("%s: fe=%d\n", __func__, fe->id); + pr_debug("%s: fe=%d\n", __func__, fe->id); *ts_type = DVB_USB_FE_TS_TYPE_RAW; if (dvb_usb_mxl111sf_isoc) @@ -1158,7 +1152,7 @@ static struct dvb_usb_device_properties mxl111sf_props_mh = { static int mxl111sf_get_stream_config_atsc_mh(struct dvb_frontend *fe, u8 *ts_type, struct usb_data_stream_properties *stream) { - deb_info("%s: fe=%d\n", __func__, fe->id); + pr_debug("%s: fe=%d\n", __func__, fe->id); if (fe->id == 0) { *ts_type = DVB_USB_FE_TS_TYPE_188; @@ -1184,7 +1178,7 @@ static int mxl111sf_get_stream_config_atsc_mh(struct dvb_frontend *fe, static int mxl111sf_streaming_ctrl_atsc_mh(struct dvb_frontend *fe, int onoff) { - deb_info("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff); + pr_debug("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff); if (fe->id == 0) return mxl111sf_ep6_streaming_ctrl(fe, onoff); @@ -1228,7 +1222,7 @@ static struct dvb_usb_device_properties mxl111sf_props_atsc_mh = { static int mxl111sf_get_stream_config_mercury(struct dvb_frontend *fe, u8 *ts_type, struct usb_data_stream_properties *stream) { - deb_info("%s: fe=%d\n", __func__, fe->id); + pr_debug("%s: fe=%d\n", __func__, fe->id); if (fe->id == 0) { *ts_type = DVB_USB_FE_TS_TYPE_188; @@ -1260,7 +1254,7 @@ static int mxl111sf_get_stream_config_mercury(struct dvb_frontend *fe, static int mxl111sf_streaming_ctrl_mercury(struct dvb_frontend *fe, int onoff) { - deb_info("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff); + pr_debug("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff); if (fe->id == 0) return mxl111sf_ep6_streaming_ctrl(fe, onoff); @@ -1306,7 +1300,7 @@ static struct dvb_usb_device_properties mxl111sf_props_mercury = { static int mxl111sf_get_stream_config_mercury_mh(struct dvb_frontend *fe, u8 *ts_type, struct usb_data_stream_properties *stream) { - deb_info("%s: fe=%d\n", __func__, fe->id); + pr_debug("%s: fe=%d\n", __func__, fe->id); if (fe->id == 0) { *ts_type = DVB_USB_FE_TS_TYPE_188; @@ -1332,7 +1326,7 @@ static int mxl111sf_get_stream_config_mercury_mh(struct dvb_frontend *fe, static int mxl111sf_streaming_ctrl_mercury_mh(struct dvb_frontend *fe, int onoff) { - deb_info("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff); + pr_debug("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff); if (fe->id == 0) return mxl111sf_ep4_streaming_ctrl(fe, onoff); diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index 2cc8ec70e3b6..c0cd0848631b 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -1041,67 +1041,34 @@ err: static int rtl2832u_power_ctrl(struct dvb_usb_device *d, int onoff) { int ret; - u8 val; dev_dbg(&d->udev->dev, "%s: onoff=%d\n", __func__, onoff); if (onoff) { - /* set output values */ - ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &val); + /* GPIO3=1, GPIO4=0 */ + ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x08, 0x18); if (ret) goto err; - val |= 0x08; - val &= 0xef; - - ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, val); + /* suspend? */ + ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL1, 0x00, 0x10); if (ret) goto err; - /* demod_ctl_1 */ - ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL1, &val); + /* enable PLL */ + ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, 0x80, 0x80); if (ret) goto err; - val &= 0xef; - - ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL1, val); - if (ret) - goto err; - - /* demod control */ - /* PLL enable */ - ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val); - if (ret) - goto err; - - /* bit 7 to 1 */ - val |= 0x80; - - ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val); - if (ret) - goto err; - - ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val); - if (ret) - goto err; - - val |= 0x20; - - ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val); + /* disable reset */ + ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, 0x20, 0x20); if (ret) goto err; mdelay(5); - /*enable ADC_Q and ADC_I */ - ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val); - if (ret) - goto err; - - val |= 0x48; - - ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val); + /* enable ADC */ + ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, 0x48, 0x48); if (ret) goto err; @@ -1114,36 +1081,18 @@ static int rtl2832u_power_ctrl(struct dvb_usb_device *d, int onoff) if (ret) goto err; } else { - /* demod_ctl_1 */ - ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL1, &val); - if (ret) - goto err; - - val |= 0x0c; - - ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL1, val); - if (ret) - goto err; - - /* set output values */ - ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &val); - if (ret) - goto err; - - val |= 0x10; - - ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, val); + /* GPIO4=1 */ + ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x10, 0x10); if (ret) goto err; - /* demod control */ - ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val); + /* disable ADC */ + ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, 0x00, 0x48); if (ret) goto err; - val &= 0x37; - - ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val); + /* disable PLL */ + ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, 0x00, 0x80); if (ret) goto err; @@ -1242,42 +1191,47 @@ static int rtl2831u_get_rc_config(struct dvb_usb_device *d, return 0; } -#else - #define rtl2831u_get_rc_config NULL -#endif -#if IS_ENABLED(CONFIG_RC_CORE) static int rtl2832u_rc_query(struct dvb_usb_device *d) { - int ret, i; + int ret, i, len; struct rtl28xxu_priv *priv = d->priv; + struct ir_raw_event ev; u8 buf[128]; - int len; - struct rtl28xxu_reg_val rc_nec_tab[] = { - { IR_RX_CTRL, 0x20 }, - { IR_RX_BUF_CTRL, 0x80 }, - { IR_RX_IF, 0xff }, - { IR_RX_IE, 0xff }, - { IR_MAX_DURATION0, 0xd0 }, - { IR_MAX_DURATION1, 0x07 }, - { IR_IDLE_LEN0, 0xc0 }, - { IR_IDLE_LEN1, 0x00 }, - { IR_GLITCH_LEN, 0x03 }, - { IR_RX_CLK, 0x09 }, - { IR_RX_CFG, 0x1c }, - { IR_MAX_H_TOL_LEN, 0x1e }, - { IR_MAX_L_TOL_LEN, 0x1e }, - { IR_RX_CTRL, 0x80 }, + static const struct rtl28xxu_reg_val_mask refresh_tab[] = { + {IR_RX_IF, 0x03, 0xff}, + {IR_RX_BUF_CTRL, 0x80, 0xff}, + {IR_RX_CTRL, 0x80, 0xff}, }; /* init remote controller */ if (!priv->rc_active) { - for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) { - ret = rtl28xx_wr_reg(d, rc_nec_tab[i].reg, - rc_nec_tab[i].val); + static const struct rtl28xxu_reg_val_mask init_tab[] = { + {SYS_DEMOD_CTL1, 0x00, 0x04}, + {SYS_DEMOD_CTL1, 0x00, 0x08}, + {USB_CTRL, 0x20, 0x20}, + {SYS_GPIO_DIR, 0x00, 0x08}, + {SYS_GPIO_OUT_EN, 0x08, 0x08}, + {SYS_GPIO_OUT_VAL, 0x08, 0x08}, + {IR_MAX_DURATION0, 0xd0, 0xff}, + {IR_MAX_DURATION1, 0x07, 0xff}, + {IR_IDLE_LEN0, 0xc0, 0xff}, + {IR_IDLE_LEN1, 0x00, 0xff}, + {IR_GLITCH_LEN, 0x03, 0xff}, + {IR_RX_CLK, 0x09, 0xff}, + {IR_RX_CFG, 0x1c, 0xff}, + {IR_MAX_H_TOL_LEN, 0x1e, 0xff}, + {IR_MAX_L_TOL_LEN, 0x1e, 0xff}, + {IR_RX_CTRL, 0x80, 0xff}, + }; + + for (i = 0; i < ARRAY_SIZE(init_tab); i++) { + ret = rtl28xx_wr_reg_mask(d, init_tab[i].reg, + init_tab[i].val, init_tab[i].mask); if (ret) goto err; } + priv->rc_active = true; } @@ -1293,14 +1247,32 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d) goto err; len = buf[0]; + + /* read raw code from hw */ ret = rtl2831_rd_regs(d, IR_RX_BUF, buf, len); + if (ret) + goto err; - /* TODO: pass raw IR to Kernel IR decoder */ + /* let hw receive new code */ + for (i = 0; i < ARRAY_SIZE(refresh_tab); i++) { + ret = rtl28xx_wr_reg_mask(d, refresh_tab[i].reg, + refresh_tab[i].val, refresh_tab[i].mask); + if (ret) + goto err; + } - ret = rtl28xx_wr_reg(d, IR_RX_IF, 0x03); - ret = rtl28xx_wr_reg(d, IR_RX_BUF_CTRL, 0x80); - ret = rtl28xx_wr_reg(d, IR_RX_CTRL, 0x80); + /* 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); + ir_raw_event_store_with_filter(d->rc_dev, &ev); + } + + /* 'flush' ir_raw_event_store_with_filter() */ + ir_raw_event_set_idle(d->rc_dev, true); + ir_raw_event_handle(d->rc_dev); exit: return ret; err: @@ -1311,15 +1283,19 @@ err: static int rtl2832u_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) { - rc->map_name = RC_MAP_EMPTY; - rc->allowed_protos = RC_BIT_NEC; + /* load empty to enable rc */ + if (!rc->map_name) + rc->map_name = RC_MAP_EMPTY; + rc->allowed_protos = RC_BIT_ALL; + rc->driver_type = RC_DRIVER_IR_RAW; rc->query = rtl2832u_rc_query; rc->interval = 400; return 0; } #else - #define rtl2832u_get_rc_config NULL +#define rtl2831u_get_rc_config NULL +#define rtl2832u_get_rc_config NULL #endif static const struct dvb_usb_device_properties rtl2831u_props = { @@ -1379,7 +1355,7 @@ static const struct usb_device_id rtl28xxu_id_table[] = { { DVB_USB_DEVICE(USB_VID_REALTEK, 0x2838, &rtl2832u_props, "Realtek RTL2832U reference design", NULL) }, { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_BLACK_REV1, - &rtl2832u_props, "TerraTec Cinergy T Stick Black", NULL) }, + &rtl2832u_props, "TerraTec Cinergy T Stick Black", RC_MAP_TERRATEC_SLIM) }, { DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_DELOCK_USB2_DVBT, &rtl2832u_props, "G-Tek Electronics Group Lifeview LV5TDLX DVB-T", NULL) }, { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_NOXON_DAB_STICK, @@ -1403,11 +1379,15 @@ static const struct usb_device_id rtl28xxu_id_table[] = { { DVB_USB_DEVICE(USB_VID_KWORLD_2, 0xd393, &rtl2832u_props, "GIGABYTE U7300", NULL) }, { DVB_USB_DEVICE(USB_VID_DEXATEK, 0x1104, - &rtl2832u_props, "Digivox Micro Hd", NULL) }, + &rtl2832u_props, "MSI DIGIVOX Micro HD", NULL) }, { DVB_USB_DEVICE(USB_VID_COMPRO, 0x0620, &rtl2832u_props, "Compro VideoMate U620F", NULL) }, { DVB_USB_DEVICE(USB_VID_KWORLD_2, 0xd394, &rtl2832u_props, "MaxMedia HU394-T", NULL) }, + { DVB_USB_DEVICE(USB_VID_LEADTEK, 0x6a03, + &rtl2832u_props, "Leadtek WinFast DTV Dongle mini", NULL) }, + { DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_CPYTO_REDI_PC50A, + &rtl2832u_props, "Crypto ReDi PC 50 A", NULL) }, { } }; MODULE_DEVICE_TABLE(usb, rtl28xxu_id_table); diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h index 533a33127289..729b3540c2f9 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h @@ -97,6 +97,12 @@ struct rtl28xxu_reg_val { u8 val; }; +struct rtl28xxu_reg_val_mask { + u16 reg; + u8 val; + u8 mask; +}; + /* * memory map * diff --git a/drivers/media/usb/dvb-usb/az6027.c b/drivers/media/usb/dvb-usb/az6027.c index 91e0119e8a87..ea2d5ee86576 100644 --- a/drivers/media/usb/dvb-usb/az6027.c +++ b/drivers/media/usb/dvb-usb/az6027.c @@ -264,7 +264,7 @@ struct stb0899_config az6027_stb0899_config = { .demod_address = 0xd0, /* 0x68, 0xd0 >> 1 */ .xtal_freq = 27000000, - .inversion = IQ_SWAP_ON, /* 1 */ + .inversion = IQ_SWAP_ON, .lo_clk = 76500000, .hi_clk = 99000000, diff --git a/drivers/media/usb/dvb-usb/pctv452e.c b/drivers/media/usb/dvb-usb/pctv452e.c index d1ddfa13de86..449a99605a87 100644 --- a/drivers/media/usb/dvb-usb/pctv452e.c +++ b/drivers/media/usb/dvb-usb/pctv452e.c @@ -828,7 +828,7 @@ static struct stb0899_config stb0899_config = { .block_sync_mode = STB0899_SYNC_FORCED, /* ? */ .xtal_freq = 27000000, /* Assume Hz ? */ - .inversion = IQ_SWAP_ON, /* ? */ + .inversion = IQ_SWAP_ON, .lo_clk = 76500000, .hi_clk = 99000000, diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index 83bfbe4c980f..dc65742c4bbc 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -37,7 +37,6 @@ #include <media/i2c-addr.h> #include <media/tveeprom.h> #include <media/v4l2-common.h> -#include <media/v4l2-chip-ident.h> #include "em28xx.h" @@ -83,26 +82,26 @@ static void em28xx_pre_card_setup(struct em28xx *dev); /* Reset for the most [analog] boards */ static struct em28xx_reg_seq default_analog[] = { - {EM28XX_R08_GPIO, 0x6d, ~EM_GPIO_4, 10}, + {EM2820_R08_GPIO_CTRL, 0x6d, ~EM_GPIO_4, 10}, { -1, -1, -1, -1}, }; /* Reset for the most [digital] boards */ static struct em28xx_reg_seq default_digital[] = { - {EM28XX_R08_GPIO, 0x6e, ~EM_GPIO_4, 10}, + {EM2820_R08_GPIO_CTRL, 0x6e, ~EM_GPIO_4, 10}, { -1, -1, -1, -1}, }; /* Board Hauppauge WinTV HVR 900 analog */ static struct em28xx_reg_seq hauppauge_wintv_hvr_900_analog[] = { - {EM28XX_R08_GPIO, 0x2d, ~EM_GPIO_4, 10}, + {EM2820_R08_GPIO_CTRL, 0x2d, ~EM_GPIO_4, 10}, {0x05, 0xff, 0x10, 10}, { -1, -1, -1, -1}, }; /* Board Hauppauge WinTV HVR 900 digital */ static struct em28xx_reg_seq hauppauge_wintv_hvr_900_digital[] = { - {EM28XX_R08_GPIO, 0x2e, ~EM_GPIO_4, 10}, + {EM2820_R08_GPIO_CTRL, 0x2e, ~EM_GPIO_4, 10}, {EM2880_R04_GPO, 0x04, 0x0f, 10}, {EM2880_R04_GPO, 0x0c, 0x0f, 10}, { -1, -1, -1, -1}, @@ -110,14 +109,14 @@ static struct em28xx_reg_seq hauppauge_wintv_hvr_900_digital[] = { /* Board Hauppauge WinTV HVR 900 (R2) digital */ static struct em28xx_reg_seq hauppauge_wintv_hvr_900R2_digital[] = { - {EM28XX_R08_GPIO, 0x2e, ~EM_GPIO_4, 10}, + {EM2820_R08_GPIO_CTRL, 0x2e, ~EM_GPIO_4, 10}, {EM2880_R04_GPO, 0x0c, 0x0f, 10}, { -1, -1, -1, -1}, }; /* Boards - EM2880 MSI DIGIVOX AD and EM2880_BOARD_MSI_DIGIVOX_AD_II */ static struct em28xx_reg_seq em2880_msi_digivox_ad_analog[] = { - {EM28XX_R08_GPIO, 0x69, ~EM_GPIO_4, 10}, + {EM2820_R08_GPIO_CTRL, 0x69, ~EM_GPIO_4, 10}, { -1, -1, -1, -1}, }; @@ -128,11 +127,11 @@ static struct em28xx_reg_seq em2880_msi_digivox_ad_analog[] = { /* Board - EM2882 Kworld 315U digital */ static struct em28xx_reg_seq em2882_kworld_315u_digital[] = { - {EM28XX_R08_GPIO, 0xff, 0xff, 10}, - {EM28XX_R08_GPIO, 0xfe, 0xff, 10}, + {EM2820_R08_GPIO_CTRL, 0xff, 0xff, 10}, + {EM2820_R08_GPIO_CTRL, 0xfe, 0xff, 10}, {EM2880_R04_GPO, 0x04, 0xff, 10}, {EM2880_R04_GPO, 0x0c, 0xff, 10}, - {EM28XX_R08_GPIO, 0x7e, 0xff, 10}, + {EM2820_R08_GPIO_CTRL, 0x7e, 0xff, 10}, { -1, -1, -1, -1}, }; @@ -145,13 +144,13 @@ static struct em28xx_reg_seq em2882_kworld_315u_tuner_gpio[] = { }; static struct em28xx_reg_seq kworld_330u_analog[] = { - {EM28XX_R08_GPIO, 0x6d, ~EM_GPIO_4, 10}, + {EM2820_R08_GPIO_CTRL, 0x6d, ~EM_GPIO_4, 10}, {EM2880_R04_GPO, 0x00, 0xff, 10}, { -1, -1, -1, -1}, }; static struct em28xx_reg_seq kworld_330u_digital[] = { - {EM28XX_R08_GPIO, 0x6e, ~EM_GPIO_4, 10}, + {EM2820_R08_GPIO_CTRL, 0x6e, ~EM_GPIO_4, 10}, {EM2880_R04_GPO, 0x08, 0xff, 10}, { -1, -1, -1, -1}, }; @@ -163,12 +162,12 @@ static struct em28xx_reg_seq kworld_330u_digital[] = { GOP3 - s5h1409 reset */ static struct em28xx_reg_seq evga_indtube_analog[] = { - {EM28XX_R08_GPIO, 0x79, 0xff, 60}, + {EM2820_R08_GPIO_CTRL, 0x79, 0xff, 60}, { -1, -1, -1, -1}, }; static struct em28xx_reg_seq evga_indtube_digital[] = { - {EM28XX_R08_GPIO, 0x7a, 0xff, 1}, + {EM2820_R08_GPIO_CTRL, 0x7a, 0xff, 1}, {EM2880_R04_GPO, 0x04, 0xff, 10}, {EM2880_R04_GPO, 0x0c, 0xff, 1}, { -1, -1, -1, -1}, @@ -186,31 +185,31 @@ static struct em28xx_reg_seq evga_indtube_digital[] = { * EM_GPIO_7 - currently unknown */ static struct em28xx_reg_seq kworld_a340_digital[] = { - {EM28XX_R08_GPIO, 0x6d, ~EM_GPIO_4, 10}, + {EM2820_R08_GPIO_CTRL, 0x6d, ~EM_GPIO_4, 10}, { -1, -1, -1, -1}, }; /* Pinnacle Hybrid Pro eb1a:2881 */ static struct em28xx_reg_seq pinnacle_hybrid_pro_analog[] = { - {EM28XX_R08_GPIO, 0xfd, ~EM_GPIO_4, 10}, + {EM2820_R08_GPIO_CTRL, 0xfd, ~EM_GPIO_4, 10}, { -1, -1, -1, -1}, }; static struct em28xx_reg_seq pinnacle_hybrid_pro_digital[] = { - {EM28XX_R08_GPIO, 0x6e, ~EM_GPIO_4, 10}, + {EM2820_R08_GPIO_CTRL, 0x6e, ~EM_GPIO_4, 10}, {EM2880_R04_GPO, 0x04, 0xff, 100},/* zl10353 reset */ {EM2880_R04_GPO, 0x0c, 0xff, 1}, { -1, -1, -1, -1}, }; static struct em28xx_reg_seq terratec_cinergy_USB_XS_FR_analog[] = { - {EM28XX_R08_GPIO, 0x6d, ~EM_GPIO_4, 10}, + {EM2820_R08_GPIO_CTRL, 0x6d, ~EM_GPIO_4, 10}, {EM2880_R04_GPO, 0x00, 0xff, 10}, { -1, -1, -1, -1}, }; static struct em28xx_reg_seq terratec_cinergy_USB_XS_FR_digital[] = { - {EM28XX_R08_GPIO, 0x6e, ~EM_GPIO_4, 10}, + {EM2820_R08_GPIO_CTRL, 0x6e, ~EM_GPIO_4, 10}, {EM2880_R04_GPO, 0x08, 0xff, 10}, { -1, -1, -1, -1}, }; @@ -219,66 +218,66 @@ static struct em28xx_reg_seq terratec_cinergy_USB_XS_FR_digital[] = { GPIO4 - CU1216L NIM Other GPIOs seems to be don't care. */ static struct em28xx_reg_seq reddo_dvb_c_usb_box[] = { - {EM28XX_R08_GPIO, 0xfe, 0xff, 10}, - {EM28XX_R08_GPIO, 0xde, 0xff, 10}, - {EM28XX_R08_GPIO, 0xfe, 0xff, 10}, - {EM28XX_R08_GPIO, 0xff, 0xff, 10}, - {EM28XX_R08_GPIO, 0x7f, 0xff, 10}, - {EM28XX_R08_GPIO, 0x6f, 0xff, 10}, - {EM28XX_R08_GPIO, 0xff, 0xff, 10}, + {EM2820_R08_GPIO_CTRL, 0xfe, 0xff, 10}, + {EM2820_R08_GPIO_CTRL, 0xde, 0xff, 10}, + {EM2820_R08_GPIO_CTRL, 0xfe, 0xff, 10}, + {EM2820_R08_GPIO_CTRL, 0xff, 0xff, 10}, + {EM2820_R08_GPIO_CTRL, 0x7f, 0xff, 10}, + {EM2820_R08_GPIO_CTRL, 0x6f, 0xff, 10}, + {EM2820_R08_GPIO_CTRL, 0xff, 0xff, 10}, {-1, -1, -1, -1}, }; /* Callback for the most boards */ static struct em28xx_reg_seq default_tuner_gpio[] = { - {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10}, - {EM28XX_R08_GPIO, 0, EM_GPIO_4, 10}, - {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10}, + {EM2820_R08_GPIO_CTRL, EM_GPIO_4, EM_GPIO_4, 10}, + {EM2820_R08_GPIO_CTRL, 0, EM_GPIO_4, 10}, + {EM2820_R08_GPIO_CTRL, EM_GPIO_4, EM_GPIO_4, 10}, { -1, -1, -1, -1}, }; /* Mute/unmute */ static struct em28xx_reg_seq compro_unmute_tv_gpio[] = { - {EM28XX_R08_GPIO, 5, 7, 10}, + {EM2820_R08_GPIO_CTRL, 5, 7, 10}, { -1, -1, -1, -1}, }; static struct em28xx_reg_seq compro_unmute_svid_gpio[] = { - {EM28XX_R08_GPIO, 4, 7, 10}, + {EM2820_R08_GPIO_CTRL, 4, 7, 10}, { -1, -1, -1, -1}, }; static struct em28xx_reg_seq compro_mute_gpio[] = { - {EM28XX_R08_GPIO, 6, 7, 10}, + {EM2820_R08_GPIO_CTRL, 6, 7, 10}, { -1, -1, -1, -1}, }; /* Terratec AV350 */ static struct em28xx_reg_seq terratec_av350_mute_gpio[] = { - {EM28XX_R08_GPIO, 0xff, 0x7f, 10}, + {EM2820_R08_GPIO_CTRL, 0xff, 0x7f, 10}, { -1, -1, -1, -1}, }; static struct em28xx_reg_seq terratec_av350_unmute_gpio[] = { - {EM28XX_R08_GPIO, 0xff, 0xff, 10}, + {EM2820_R08_GPIO_CTRL, 0xff, 0xff, 10}, { -1, -1, -1, -1}, }; static struct em28xx_reg_seq silvercrest_reg_seq[] = { - {EM28XX_R08_GPIO, 0xff, 0xff, 10}, - {EM28XX_R08_GPIO, 0x01, 0xf7, 10}, + {EM2820_R08_GPIO_CTRL, 0xff, 0xff, 10}, + {EM2820_R08_GPIO_CTRL, 0x01, 0xf7, 10}, { -1, -1, -1, -1}, }; static struct em28xx_reg_seq vc211a_enable[] = { - {EM28XX_R08_GPIO, 0xff, 0x07, 10}, - {EM28XX_R08_GPIO, 0xff, 0x0f, 10}, - {EM28XX_R08_GPIO, 0xff, 0x0b, 10}, + {EM2820_R08_GPIO_CTRL, 0xff, 0x07, 10}, + {EM2820_R08_GPIO_CTRL, 0xff, 0x0f, 10}, + {EM2820_R08_GPIO_CTRL, 0xff, 0x0b, 10}, { -1, -1, -1, -1}, }; static struct em28xx_reg_seq dikom_dk300_digital[] = { - {EM28XX_R08_GPIO, 0x6e, ~EM_GPIO_4, 10}, + {EM2820_R08_GPIO_CTRL, 0x6e, ~EM_GPIO_4, 10}, {EM2880_R04_GPO, 0x08, 0xff, 10}, { -1, -1, -1, -1}, }; @@ -286,14 +285,14 @@ static struct em28xx_reg_seq dikom_dk300_digital[] = { /* Reset for the most [digital] boards */ static struct em28xx_reg_seq leadership_digital[] = { - {EM2874_R80_GPIO, 0x70, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0x70, 0xff, 10}, { -1, -1, -1, -1}, }; static struct em28xx_reg_seq leadership_reset[] = { - {EM2874_R80_GPIO, 0xf0, 0xff, 10}, - {EM2874_R80_GPIO, 0xb0, 0xff, 10}, - {EM2874_R80_GPIO, 0xf0, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0xf0, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0xb0, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0xf0, 0xff, 10}, { -1, -1, -1, -1}, }; @@ -302,25 +301,25 @@ static struct em28xx_reg_seq leadership_reset[] = { * GPIO_7 - LED */ static struct em28xx_reg_seq pctv_290e[] = { - {EM2874_R80_GPIO, 0x00, 0xff, 80}, - {EM2874_R80_GPIO, 0x40, 0xff, 80}, /* GPIO_6 = 1 */ - {EM2874_R80_GPIO, 0xc0, 0xff, 80}, /* GPIO_7 = 1 */ + {EM2874_R80_GPIO_P0_CTRL, 0x00, 0xff, 80}, + {EM2874_R80_GPIO_P0_CTRL, 0x40, 0xff, 80}, /* GPIO_6 = 1 */ + {EM2874_R80_GPIO_P0_CTRL, 0xc0, 0xff, 80}, /* GPIO_7 = 1 */ {-1, -1, -1, -1}, }; #if 0 static struct em28xx_reg_seq terratec_h5_gpio[] = { - {EM28XX_R08_GPIO, 0xff, 0xff, 10}, - {EM2874_R80_GPIO, 0xf6, 0xff, 100}, - {EM2874_R80_GPIO, 0xf2, 0xff, 50}, - {EM2874_R80_GPIO, 0xf6, 0xff, 50}, + {EM2820_R08_GPIO_CTRL, 0xff, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0xf2, 0xff, 50}, + {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 50}, { -1, -1, -1, -1}, }; static struct em28xx_reg_seq terratec_h5_digital[] = { - {EM2874_R80_GPIO, 0xf6, 0xff, 10}, - {EM2874_R80_GPIO, 0xe6, 0xff, 100}, - {EM2874_R80_GPIO, 0xa6, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0xe6, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0xa6, 0xff, 10}, { -1, -1, -1, -1}, }; #endif @@ -336,51 +335,52 @@ static struct em28xx_reg_seq terratec_h5_digital[] = { * GPIO_7 - LED (green LED) */ static struct em28xx_reg_seq pctv_460e[] = { - {EM2874_R80_GPIO, 0x01, 0xff, 50}, + {EM2874_R80_GPIO_P0_CTRL, 0x01, 0xff, 50}, {0x0d, 0xff, 0xff, 50}, - {EM2874_R80_GPIO, 0x41, 0xff, 50}, /* GPIO_6=1 */ + {EM2874_R80_GPIO_P0_CTRL, 0x41, 0xff, 50}, /* GPIO_6=1 */ {0x0d, 0x42, 0xff, 50}, - {EM2874_R80_GPIO, 0x61, 0xff, 50}, /* GPIO_5=1 */ + {EM2874_R80_GPIO_P0_CTRL, 0x61, 0xff, 50}, /* GPIO_5=1 */ { -1, -1, -1, -1}, }; static struct em28xx_reg_seq c3tech_digital_duo_digital[] = { - {EM2874_R80_GPIO, 0xff, 0xff, 10}, - {EM2874_R80_GPIO, 0xfd, 0xff, 10}, /* xc5000 reset */ - {EM2874_R80_GPIO, 0xf9, 0xff, 35}, - {EM2874_R80_GPIO, 0xfd, 0xff, 10}, - {EM2874_R80_GPIO, 0xff, 0xff, 10}, - {EM2874_R80_GPIO, 0xfe, 0xff, 10}, - {EM2874_R80_GPIO, 0xbe, 0xff, 10}, - {EM2874_R80_GPIO, 0xfe, 0xff, 20}, + {EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0xfd, 0xff, 10}, /* xc5000 reset */ + {EM2874_R80_GPIO_P0_CTRL, 0xf9, 0xff, 35}, + {EM2874_R80_GPIO_P0_CTRL, 0xfd, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0xfe, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0xbe, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0xfe, 0xff, 20}, { -1, -1, -1, -1}, }; #if 0 static struct em28xx_reg_seq hauppauge_930c_gpio[] = { - {EM2874_R80_GPIO, 0x6f, 0xff, 10}, - {EM2874_R80_GPIO, 0x4f, 0xff, 10}, /* xc5000 reset */ - {EM2874_R80_GPIO, 0x6f, 0xff, 10}, - {EM2874_R80_GPIO, 0x4f, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0x6f, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0x4f, 0xff, 10}, /* xc5000 reset */ + {EM2874_R80_GPIO_P0_CTRL, 0x6f, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0x4f, 0xff, 10}, { -1, -1, -1, -1}, }; static struct em28xx_reg_seq hauppauge_930c_digital[] = { - {EM2874_R80_GPIO, 0xf6, 0xff, 10}, - {EM2874_R80_GPIO, 0xe6, 0xff, 100}, - {EM2874_R80_GPIO, 0xa6, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0xe6, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0xa6, 0xff, 10}, { -1, -1, -1, -1}, }; #endif /* 1b80:e425 MaxMedia UB425-TC + * 1b80:e1cc Delock 61959 * GPIO_6 - demod reset, 0=active * GPIO_7 - LED, 0=active */ static struct em28xx_reg_seq maxmedia_ub425_tc[] = { - {EM2874_R80_GPIO, 0x83, 0xff, 100}, - {EM2874_R80_GPIO, 0xc3, 0xff, 100}, /* GPIO_6 = 1 */ - {EM2874_R80_GPIO, 0x43, 0xff, 000}, /* GPIO_7 = 0 */ + {EM2874_R80_GPIO_P0_CTRL, 0x83, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0xc3, 0xff, 100}, /* GPIO_6 = 1 */ + {EM2874_R80_GPIO_P0_CTRL, 0x43, 0xff, 000}, /* GPIO_7 = 0 */ {-1, -1, -1, -1}, }; @@ -391,9 +391,9 @@ static struct em28xx_reg_seq maxmedia_ub425_tc[] = { * GPIO_7: LED, 1=active */ static struct em28xx_reg_seq pctv_510e[] = { - {EM2874_R80_GPIO, 0x10, 0xff, 100}, - {EM2874_R80_GPIO, 0x14, 0xff, 100}, /* GPIO_2 = 1 */ - {EM2874_R80_GPIO, 0x54, 0xff, 050}, /* GPIO_6 = 1 */ + {EM2874_R80_GPIO_P0_CTRL, 0x10, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0x14, 0xff, 100}, /* GPIO_2 = 1 */ + {EM2874_R80_GPIO_P0_CTRL, 0x54, 0xff, 050}, /* GPIO_6 = 1 */ { -1, -1, -1, -1}, }; @@ -404,10 +404,10 @@ static struct em28xx_reg_seq pctv_510e[] = { * GPIO_7: LED, 1=active */ static struct em28xx_reg_seq pctv_520e[] = { - {EM2874_R80_GPIO, 0x10, 0xff, 100}, - {EM2874_R80_GPIO, 0x14, 0xff, 100}, /* GPIO_2 = 1 */ - {EM2874_R80_GPIO, 0x54, 0xff, 050}, /* GPIO_6 = 1 */ - {EM2874_R80_GPIO, 0xd4, 0xff, 000}, /* GPIO_7 = 1 */ + {EM2874_R80_GPIO_P0_CTRL, 0x10, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0x14, 0xff, 100}, /* GPIO_2 = 1 */ + {EM2874_R80_GPIO_P0_CTRL, 0x54, 0xff, 050}, /* GPIO_6 = 1 */ + {EM2874_R80_GPIO_P0_CTRL, 0xd4, 0xff, 000}, /* GPIO_7 = 1 */ { -1, -1, -1, -1}, }; @@ -2017,6 +2017,19 @@ struct em28xx_board em28xx_boards[] = { .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_400_KHZ, }, + /* 1b80:e1cc Delock 61959 + * Empia EM2874B + Micronas DRX 3913KA2 + NXP TDA18271HDC2 + * mostly the same as MaxMedia UB-425-TC but different remote */ + [EM2874_BOARD_DELOCK_61959] = { + .name = "Delock 61959", + .tuner_type = TUNER_ABSENT, + .tuner_gpio = maxmedia_ub425_tc, + .has_dvb = 1, + .ir_codes = RC_MAP_DELOCK_61959, + .def_i2c_bus = 1, + .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | + EM28XX_I2C_FREQ_400_KHZ, + }, }; const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); @@ -2178,6 +2191,8 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM2884_BOARD_PCTV_510E }, { USB_DEVICE(0x2013, 0x0251), .driver_info = EM2884_BOARD_PCTV_520E }, + { USB_DEVICE(0x1b80, 0xe1cc), + .driver_info = EM2874_BOARD_DELOCK_61959 }, { }, }; MODULE_DEVICE_TABLE(usb, em28xx_id_table); @@ -2284,9 +2299,9 @@ static void em28xx_pre_card_setup(struct em28xx *dev) break; case EM2861_BOARD_KWORLD_PVRTV_300U: case EM2880_BOARD_KWORLD_DVB_305U: - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0x6d); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0x6d); msleep(10); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0x7d); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0x7d); msleep(10); break; case EM2870_BOARD_COMPRO_VIDEOMATE: @@ -2296,45 +2311,45 @@ static void em28xx_pre_card_setup(struct em28xx *dev) msleep(10); em28xx_write_reg(dev, EM2880_R04_GPO, 0x01); msleep(10); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xfd); mdelay(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfc); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xfc); mdelay(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xdc); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xdc); mdelay(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfc); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xfc); mdelay(70); break; case EM2870_BOARD_TERRATEC_XS_MT2060: /* this device needs some gpio writes to get the DVB-T demod work */ - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xfe); mdelay(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xde); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xde); mdelay(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xfe); mdelay(70); break; case EM2870_BOARD_PINNACLE_PCTV_DVB: /* this device needs some gpio writes to get the DVB-T demod work */ - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xfe); mdelay(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xde); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xde); mdelay(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xfe); mdelay(70); break; case EM2820_BOARD_GADMEI_UTV310: case EM2820_BOARD_MSI_VOX_USB_2: /* enables audio for that devices */ - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xfd); break; case EM2882_BOARD_KWORLD_ATSC_315U: - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xff); msleep(10); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xfe); msleep(10); em28xx_write_reg(dev, EM2880_R04_GPO, 0x00); msleep(10); @@ -2360,13 +2375,13 @@ static void em28xx_pre_card_setup(struct em28xx *dev) break; case EM2820_BOARD_IODATA_GVMVP_SZ: - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xff); msleep(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf7); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xf7); msleep(10); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xfe); msleep(70); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xfd); msleep(70); break; } @@ -2653,7 +2668,7 @@ static void em28xx_card_setup(struct em28xx *dev) dev->tuner_type = tv.tuner_type; - if (tv.audio_processor == V4L2_IDENT_MSPX4XX) { + if (tv.audio_processor == TVEEPROM_AUDPROC_MSP) { dev->i2s_speed = 2048000; dev->board.has_msp34xx = 1; } @@ -2662,12 +2677,12 @@ static void em28xx_card_setup(struct em28xx *dev) case EM2882_BOARD_KWORLD_ATSC_315U: em28xx_write_reg(dev, 0x0d, 0x42); msleep(10); - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xfd); msleep(10); break; case EM2820_BOARD_KWORLD_PVRTV2800RF: /* GPIO enables sound on KWORLD PVR TV 2800RF */ - em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf9); + em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xf9); break; case EM2820_BOARD_UNKNOWN: case EM2800_BOARD_UNKNOWN: @@ -2881,10 +2896,6 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, em28xx_set_model(dev); - /* Set the default GPO/GPIO for legacy devices */ - dev->reg_gpo_num = EM2880_R04_GPO; - dev->reg_gpio_num = EM28XX_R08_GPIO; - dev->wait_after_write = 5; /* Based on the Chip ID, set the device configuration */ @@ -2932,13 +2943,11 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, break; case CHIP_ID_EM2874: chip_name = "em2874"; - dev->reg_gpio_num = EM2874_R80_GPIO; dev->wait_after_write = 0; dev->eeprom_addrwidth_16bit = 1; break; case CHIP_ID_EM28174: chip_name = "em28174"; - dev->reg_gpio_num = EM2874_R80_GPIO; dev->wait_after_write = 0; dev->eeprom_addrwidth_16bit = 1; break; @@ -2948,7 +2957,6 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, break; case CHIP_ID_EM2884: chip_name = "em2884"; - dev->reg_gpio_num = EM2874_R80_GPIO; dev->wait_after_write = 0; dev->eeprom_addrwidth_16bit = 1; break; @@ -2977,11 +2985,6 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, return 0; } - /* Prepopulate cached GPO register content */ - retval = em28xx_read_reg(dev, dev->reg_gpo_num); - if (retval >= 0) - dev->reg_gpo = retval; - em28xx_pre_card_setup(dev); if (!dev->board.is_em2800) { @@ -3071,7 +3074,7 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, if (dev->board.has_msp34xx) { /* Send a reset to other chips via gpio */ - retval = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf7); + retval = em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xf7); if (retval < 0) { em28xx_errdev("%s: em28xx_write_reg - " "msp34xx(1) failed! error [%d]\n", @@ -3080,7 +3083,7 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, } msleep(3); - retval = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff); + retval = em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xff); if (retval < 0) { em28xx_errdev("%s: em28xx_write_reg - " "msp34xx(2) failed! error [%d]\n", diff --git a/drivers/media/usb/em28xx/em28xx-core.c b/drivers/media/usb/em28xx/em28xx-core.c index a802128ce9c5..fc157af5234a 100644 --- a/drivers/media/usb/em28xx/em28xx-core.c +++ b/drivers/media/usb/em28xx/em28xx-core.c @@ -193,23 +193,7 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len) { - int rc; - - rc = em28xx_write_regs_req(dev, USB_REQ_GET_STATUS, reg, buf, len); - - /* Stores GPO/GPIO values at the cache, if changed - Only write values should be stored, since input on a GPIO - register will return the input bits. - Not sure what happens on reading GPO register. - */ - if (rc >= 0) { - if (reg == dev->reg_gpo_num) - dev->reg_gpo = buf[0]; - else if (reg == dev->reg_gpio_num) - dev->reg_gpio = buf[0]; - } - - return rc; + return em28xx_write_regs_req(dev, USB_REQ_GET_STATUS, reg, buf, len); } EXPORT_SYMBOL_GPL(em28xx_write_regs); @@ -231,14 +215,7 @@ int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val, int oldval; u8 newval; - /* Uses cache for gpo/gpio registers */ - if (reg == dev->reg_gpo_num) - oldval = dev->reg_gpo; - else if (reg == dev->reg_gpio_num) - oldval = dev->reg_gpio; - else - oldval = em28xx_read_reg(dev, reg); - + oldval = em28xx_read_reg(dev, reg); if (oldval < 0) return oldval; diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index b22f8fed8127..bb1e8dca80cd 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -421,23 +421,23 @@ static void hauppauge_hvr930c_init(struct em28xx *dev) int i; struct em28xx_reg_seq hauppauge_hvr930c_init[] = { - {EM2874_R80_GPIO, 0xff, 0xff, 0x65}, - {EM2874_R80_GPIO, 0xfb, 0xff, 0x32}, - {EM2874_R80_GPIO, 0xff, 0xff, 0xb8}, + {EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 0x65}, + {EM2874_R80_GPIO_P0_CTRL, 0xfb, 0xff, 0x32}, + {EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 0xb8}, { -1, -1, -1, -1}, }; struct em28xx_reg_seq hauppauge_hvr930c_end[] = { - {EM2874_R80_GPIO, 0xef, 0xff, 0x01}, - {EM2874_R80_GPIO, 0xaf, 0xff, 0x65}, - {EM2874_R80_GPIO, 0xef, 0xff, 0x76}, - {EM2874_R80_GPIO, 0xef, 0xff, 0x01}, - {EM2874_R80_GPIO, 0xcf, 0xff, 0x0b}, - {EM2874_R80_GPIO, 0xef, 0xff, 0x40}, - - {EM2874_R80_GPIO, 0xcf, 0xff, 0x65}, - {EM2874_R80_GPIO, 0xef, 0xff, 0x65}, - {EM2874_R80_GPIO, 0xcf, 0xff, 0x0b}, - {EM2874_R80_GPIO, 0xef, 0xff, 0x65}, + {EM2874_R80_GPIO_P0_CTRL, 0xef, 0xff, 0x01}, + {EM2874_R80_GPIO_P0_CTRL, 0xaf, 0xff, 0x65}, + {EM2874_R80_GPIO_P0_CTRL, 0xef, 0xff, 0x76}, + {EM2874_R80_GPIO_P0_CTRL, 0xef, 0xff, 0x01}, + {EM2874_R80_GPIO_P0_CTRL, 0xcf, 0xff, 0x0b}, + {EM2874_R80_GPIO_P0_CTRL, 0xef, 0xff, 0x40}, + + {EM2874_R80_GPIO_P0_CTRL, 0xcf, 0xff, 0x65}, + {EM2874_R80_GPIO_P0_CTRL, 0xef, 0xff, 0x65}, + {EM2874_R80_GPIO_P0_CTRL, 0xcf, 0xff, 0x0b}, + {EM2874_R80_GPIO_P0_CTRL, 0xef, 0xff, 0x65}, { -1, -1, -1, -1}, }; @@ -487,16 +487,16 @@ static void terratec_h5_init(struct em28xx *dev) { int i; struct em28xx_reg_seq terratec_h5_init[] = { - {EM28XX_R08_GPIO, 0xff, 0xff, 10}, - {EM2874_R80_GPIO, 0xf6, 0xff, 100}, - {EM2874_R80_GPIO, 0xf2, 0xff, 50}, - {EM2874_R80_GPIO, 0xf6, 0xff, 100}, + {EM2820_R08_GPIO_CTRL, 0xff, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0xf2, 0xff, 50}, + {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 100}, { -1, -1, -1, -1}, }; struct em28xx_reg_seq terratec_h5_end[] = { - {EM2874_R80_GPIO, 0xe6, 0xff, 100}, - {EM2874_R80_GPIO, 0xa6, 0xff, 50}, - {EM2874_R80_GPIO, 0xe6, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0xe6, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0xa6, 0xff, 50}, + {EM2874_R80_GPIO_P0_CTRL, 0xe6, 0xff, 100}, { -1, -1, -1, -1}, }; struct { @@ -543,15 +543,15 @@ static void terratec_htc_stick_init(struct em28xx *dev) * 0xb6: unknown (does not affect DVB-T). */ struct em28xx_reg_seq terratec_htc_stick_init[] = { - {EM28XX_R08_GPIO, 0xff, 0xff, 10}, - {EM2874_R80_GPIO, 0xf6, 0xff, 100}, - {EM2874_R80_GPIO, 0xe6, 0xff, 50}, - {EM2874_R80_GPIO, 0xf6, 0xff, 100}, + {EM2820_R08_GPIO_CTRL, 0xff, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0xe6, 0xff, 50}, + {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 100}, { -1, -1, -1, -1}, }; struct em28xx_reg_seq terratec_htc_stick_end[] = { - {EM2874_R80_GPIO, 0xb6, 0xff, 100}, - {EM2874_R80_GPIO, 0xf6, 0xff, 50}, + {EM2874_R80_GPIO_P0_CTRL, 0xb6, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0xf6, 0xff, 50}, { -1, -1, -1, -1}, }; @@ -590,16 +590,16 @@ static void terratec_htc_usb_xs_init(struct em28xx *dev) int i; struct em28xx_reg_seq terratec_htc_usb_xs_init[] = { - {EM28XX_R08_GPIO, 0xff, 0xff, 10}, - {EM2874_R80_GPIO, 0xb2, 0xff, 100}, - {EM2874_R80_GPIO, 0xb2, 0xff, 50}, - {EM2874_R80_GPIO, 0xb6, 0xff, 100}, + {EM2820_R08_GPIO_CTRL, 0xff, 0xff, 10}, + {EM2874_R80_GPIO_P0_CTRL, 0xb2, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0xb2, 0xff, 50}, + {EM2874_R80_GPIO_P0_CTRL, 0xb6, 0xff, 100}, { -1, -1, -1, -1}, }; struct em28xx_reg_seq terratec_htc_usb_xs_end[] = { - {EM2874_R80_GPIO, 0xa6, 0xff, 100}, - {EM2874_R80_GPIO, 0xa6, 0xff, 50}, - {EM2874_R80_GPIO, 0xe6, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0xa6, 0xff, 100}, + {EM2874_R80_GPIO_P0_CTRL, 0xa6, 0xff, 50}, + {EM2874_R80_GPIO_P0_CTRL, 0xe6, 0xff, 100}, { -1, -1, -1, -1}, }; @@ -1216,6 +1216,7 @@ static int em28xx_dvb_init(struct em28xx *dev) dvb_attach(a8293_attach, dvb->fe[0], &dev->i2c_adap[dev->def_i2c_bus], &em28xx_a8293_config); break; + case EM2874_BOARD_DELOCK_61959: case EM2874_BOARD_MAXMEDIA_UB425_TC: /* attach demodulator */ dvb->fe[0] = dvb_attach(drxk_attach, &maxmedia_ub425_tc_drxk, @@ -1235,8 +1236,8 @@ static int em28xx_dvb_init(struct em28xx *dev) } /* TODO: we need drx-3913k firmware in order to support DVB-T */ - em28xx_info("MaxMedia UB425-TC: only DVB-C supported by that " \ - "driver version\n"); + em28xx_info("MaxMedia UB425-TC/Delock 61959: only DVB-C " \ + "supported by that driver version\n"); break; case EM2884_BOARD_PCTV_510E: diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c index 466b19d0d767..ea181e4b68c5 100644 --- a/drivers/media/usb/em28xx/em28xx-input.c +++ b/drivers/media/usb/em28xx/em28xx-input.c @@ -32,7 +32,6 @@ #define EM28XX_SNAPSHOT_KEY KEY_CAMERA #define EM28XX_SBUTTON_QUERY_INTERVAL 500 -#define EM28XX_R0C_USBSUSP_SNAPSHOT 0x20 static unsigned int ir_debug; module_param(ir_debug, int, 0644); diff --git a/drivers/media/usb/em28xx/em28xx-reg.h b/drivers/media/usb/em28xx/em28xx-reg.h index 622871db04aa..0e0477847965 100644 --- a/drivers/media/usb/em28xx/em28xx-reg.h +++ b/drivers/media/usb/em28xx/em28xx-reg.h @@ -49,8 +49,9 @@ /* GPIO/GPO registers */ -#define EM2880_R04_GPO 0x04 /* em2880-em2883 only */ -#define EM28XX_R08_GPIO 0x08 /* em2820 or upper */ +#define EM2880_R04_GPO 0x04 /* em2880-em2883 only */ +#define EM2820_R08_GPIO_CTRL 0x08 /* em2820-em2873/83 only */ +#define EM2820_R09_GPIO_STATE 0x09 /* em2820-em2873/83 only */ #define EM28XX_R06_I2C_CLK 0x06 @@ -67,7 +68,8 @@ #define EM28XX_R0A_CHIPID 0x0a -#define EM28XX_R0C_USBSUSP 0x0c /* */ +#define EM28XX_R0C_USBSUSP 0x0c +#define EM28XX_R0C_USBSUSP_SNAPSHOT 0x20 /* 1=button pressed, needs reset */ #define EM28XX_R0E_AUDIOSRC 0x0e #define EM28XX_R0F_XCLK 0x0f @@ -193,7 +195,20 @@ #define EM2874_R50_IR_CONFIG 0x50 #define EM2874_R51_IR 0x51 #define EM2874_R5F_TS_ENABLE 0x5f -#define EM2874_R80_GPIO 0x80 + +/* em2874/174/84, em25xx, em276x/7x/8x GPIO registers */ +/* + * NOTE: not all ports are bonded out; + * Some ports are multiplexed with special function I/O + */ +#define EM2874_R80_GPIO_P0_CTRL 0x80 +#define EM2874_R81_GPIO_P1_CTRL 0x81 +#define EM2874_R82_GPIO_P2_CTRL 0x82 +#define EM2874_R83_GPIO_P3_CTRL 0x83 +#define EM2874_R84_GPIO_P0_STATE 0x84 +#define EM2874_R85_GPIO_P1_STATE 0x85 +#define EM2874_R86_GPIO_P2_STATE 0x86 +#define EM2874_R87_GPIO_P3_STATE 0x87 /* em2874 IR config register (0x50) */ #define EM2874_IR_NEC 0x00 diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 32d60e5546bc..1a577ed8ea0c 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -41,7 +41,6 @@ #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-event.h> -#include <media/v4l2-chip-ident.h> #include <media/msp3400.h> #include <media/tuner.h> @@ -1309,28 +1308,6 @@ static int vidioc_s_frequency(struct file *file, void *priv, return 0; } -static int vidioc_g_chip_ident(struct file *file, void *priv, - struct v4l2_dbg_chip_ident *chip) -{ - struct em28xx_fh *fh = priv; - struct em28xx *dev = fh->dev; - - chip->ident = V4L2_IDENT_NONE; - chip->revision = 0; - if (chip->match.type == V4L2_CHIP_MATCH_BRIDGE) { - if (chip->match.addr > 1) - return -EINVAL; - return 0; - } - if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER && - chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR) - return -EINVAL; - - v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_chip_ident, chip); - - return 0; -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int vidioc_g_chip_info(struct file *file, void *priv, struct v4l2_dbg_chip_info *chip) @@ -1366,14 +1343,9 @@ static int vidioc_g_register(struct file *file, void *priv, struct em28xx *dev = fh->dev; int ret; - switch (reg->match.type) { - case V4L2_CHIP_MATCH_BRIDGE: - if (reg->match.addr > 1) - return -EINVAL; - if (!reg->match.addr) - break; - /* fall-through */ - case V4L2_CHIP_MATCH_AC97: + if (reg->match.addr > 1) + return -EINVAL; + if (reg->match.addr) { ret = em28xx_read_ac97(dev, reg->reg); if (ret < 0) return ret; @@ -1381,15 +1353,6 @@ static int vidioc_g_register(struct file *file, void *priv, reg->val = ret; reg->size = 1; return 0; - case V4L2_CHIP_MATCH_I2C_DRIVER: - v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg); - return 0; - case V4L2_CHIP_MATCH_I2C_ADDR: - /* TODO: is this correct? */ - v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg); - return 0; - default: - return -EINVAL; } /* Match host */ @@ -1421,25 +1384,10 @@ static int vidioc_s_register(struct file *file, void *priv, struct em28xx *dev = fh->dev; __le16 buf; - switch (reg->match.type) { - case V4L2_CHIP_MATCH_BRIDGE: - if (reg->match.addr > 1) - return -EINVAL; - if (!reg->match.addr) - break; - /* fall-through */ - case V4L2_CHIP_MATCH_AC97: - return em28xx_write_ac97(dev, reg->reg, reg->val); - case V4L2_CHIP_MATCH_I2C_DRIVER: - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg); - return 0; - case V4L2_CHIP_MATCH_I2C_ADDR: - /* TODO: is this correct? */ - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg); - return 0; - default: + if (reg->match.addr > 1) return -EINVAL; - } + if (reg->match.addr) + return em28xx_write_ac97(dev, reg->reg, reg->val); /* Match host */ buf = cpu_to_le16(reg->val); @@ -1795,7 +1743,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_s_frequency = vidioc_s_frequency, .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, - .vidioc_g_chip_ident = vidioc_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_chip_info = vidioc_g_chip_info, .vidioc_g_register = vidioc_g_register, @@ -1826,7 +1773,6 @@ static const struct v4l2_ioctl_ops radio_ioctl_ops = { .vidioc_s_frequency = vidioc_s_frequency, .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, - .vidioc_g_chip_ident = vidioc_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_chip_info = vidioc_g_chip_info, .vidioc_g_register = vidioc_g_register, diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h index a9323b63d8e5..205e9038b1c0 100644 --- a/drivers/media/usb/em28xx/em28xx.h +++ b/drivers/media/usb/em28xx/em28xx.h @@ -130,6 +130,7 @@ #define EM2884_BOARD_PCTV_520E 86 #define EM2884_BOARD_TERRATEC_HTC_USB_XS 87 #define EM2884_BOARD_C3TECH_DIGITAL_DUO 88 +#define EM2874_BOARD_DELOCK_61959 89 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 @@ -636,12 +637,6 @@ struct em28xx { enum em28xx_mode mode; - /* register numbers for GPO/GPIO registers */ - u16 reg_gpo_num, reg_gpio_num; - - /* Caches GPO and GPIO registers */ - unsigned char reg_gpo, reg_gpio; - /* Snapshot button */ char snapshot_button_path[30]; /* path of the input dev */ struct input_dev *sbutton_input_dev; diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c index 5995ec4de6bc..b7ae8721b847 100644 --- a/drivers/media/usb/gspca/gspca.c +++ b/drivers/media/usb/gspca/gspca.c @@ -1029,33 +1029,35 @@ static int gspca_get_mode(struct gspca_dev *gspca_dev, } #ifdef CONFIG_VIDEO_ADV_DEBUG -static int vidioc_g_register(struct file *file, void *priv, - struct v4l2_dbg_register *reg) +static int vidioc_g_chip_info(struct file *file, void *priv, + struct v4l2_dbg_chip_info *chip) { struct gspca_dev *gspca_dev = video_drvdata(file); gspca_dev->usb_err = 0; - return gspca_dev->sd_desc->get_register(gspca_dev, reg); + if (gspca_dev->sd_desc->get_chip_info) + return gspca_dev->sd_desc->get_chip_info(gspca_dev, chip); + return chip->match.addr ? -EINVAL : 0; } -static int vidioc_s_register(struct file *file, void *priv, - const struct v4l2_dbg_register *reg) +static int vidioc_g_register(struct file *file, void *priv, + struct v4l2_dbg_register *reg) { struct gspca_dev *gspca_dev = video_drvdata(file); gspca_dev->usb_err = 0; - return gspca_dev->sd_desc->set_register(gspca_dev, reg); + return gspca_dev->sd_desc->get_register(gspca_dev, reg); } -#endif -static int vidioc_g_chip_ident(struct file *file, void *priv, - struct v4l2_dbg_chip_ident *chip) +static int vidioc_s_register(struct file *file, void *priv, + const struct v4l2_dbg_register *reg) { struct gspca_dev *gspca_dev = video_drvdata(file); gspca_dev->usb_err = 0; - return gspca_dev->sd_desc->get_chip_ident(gspca_dev, chip); + return gspca_dev->sd_desc->set_register(gspca_dev, reg); } +#endif static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *fmtdesc) @@ -1974,10 +1976,10 @@ static const struct v4l2_ioctl_ops dev_ioctl_ops = { .vidioc_enum_framesizes = vidioc_enum_framesizes, .vidioc_enum_frameintervals = vidioc_enum_frameintervals, #ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_chip_info = vidioc_g_chip_info, .vidioc_g_register = vidioc_g_register, .vidioc_s_register = vidioc_s_register, #endif - .vidioc_g_chip_ident = vidioc_g_chip_ident, .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, }; @@ -2086,14 +2088,10 @@ int gspca_dev_probe2(struct usb_interface *intf, v4l2_disable_ioctl_locking(&gspca_dev->vdev, VIDIOC_DQBUF); v4l2_disable_ioctl_locking(&gspca_dev->vdev, VIDIOC_QBUF); v4l2_disable_ioctl_locking(&gspca_dev->vdev, VIDIOC_QUERYBUF); - if (!gspca_dev->sd_desc->get_chip_ident) - v4l2_disable_ioctl(&gspca_dev->vdev, VIDIOC_DBG_G_CHIP_IDENT); #ifdef CONFIG_VIDEO_ADV_DEBUG - if (!gspca_dev->sd_desc->get_chip_ident || - !gspca_dev->sd_desc->get_register) + if (!gspca_dev->sd_desc->get_register) v4l2_disable_ioctl(&gspca_dev->vdev, VIDIOC_DBG_G_REGISTER); - if (!gspca_dev->sd_desc->get_chip_ident || - !gspca_dev->sd_desc->set_register) + if (!gspca_dev->sd_desc->set_register) v4l2_disable_ioctl(&gspca_dev->vdev, VIDIOC_DBG_S_REGISTER); #endif if (!gspca_dev->sd_desc->get_jcomp) diff --git a/drivers/media/usb/gspca/gspca.h b/drivers/media/usb/gspca/gspca.h index ef8efeb80070..ac0b11f46f50 100644 --- a/drivers/media/usb/gspca/gspca.h +++ b/drivers/media/usb/gspca/gspca.h @@ -78,8 +78,8 @@ typedef int (*cam_get_reg_op) (struct gspca_dev *, struct v4l2_dbg_register *); typedef int (*cam_set_reg_op) (struct gspca_dev *, const struct v4l2_dbg_register *); -typedef int (*cam_ident_op) (struct gspca_dev *, - struct v4l2_dbg_chip_ident *); +typedef int (*cam_chip_info_op) (struct gspca_dev *, + struct v4l2_dbg_chip_info *); typedef void (*cam_streamparm_op) (struct gspca_dev *, struct v4l2_streamparm *); typedef void (*cam_pkt_op) (struct gspca_dev *gspca_dev, @@ -112,8 +112,8 @@ struct sd_desc { #ifdef CONFIG_VIDEO_ADV_DEBUG cam_set_reg_op set_register; cam_get_reg_op get_register; + cam_chip_info_op get_chip_info; #endif - cam_ident_op get_chip_ident; #if IS_ENABLED(CONFIG_INPUT) cam_int_pkt_op int_pkt_scan; /* other_input makes the gspca core create gspca_dev->input even when diff --git a/drivers/media/usb/gspca/pac7302.c b/drivers/media/usb/gspca/pac7302.c index 6008c8d546a3..a91509643563 100644 --- a/drivers/media/usb/gspca/pac7302.c +++ b/drivers/media/usb/gspca/pac7302.c @@ -93,7 +93,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/input.h> -#include <media/v4l2-chip-ident.h> #include "gspca.h" /* Include pac common sof detection functions */ #include "pac_common.h" @@ -849,8 +848,7 @@ static int sd_dbg_s_register(struct gspca_dev *gspca_dev, * reg->reg: bit0..15: reserved for register index (wIndex is 16bit * long on the USB bus) */ - if (reg->match.type == V4L2_CHIP_MATCH_HOST && - reg->match.addr == 0 && + if (reg->match.addr == 0 && (reg->reg < 0x000000ff) && (reg->val <= 0x000000ff) ) { @@ -871,20 +869,6 @@ static int sd_dbg_s_register(struct gspca_dev *gspca_dev, } return gspca_dev->usb_err; } - -static int sd_chip_ident(struct gspca_dev *gspca_dev, - struct v4l2_dbg_chip_ident *chip) -{ - int ret = -EINVAL; - - if (chip->match.type == V4L2_CHIP_MATCH_HOST && - chip->match.addr == 0) { - chip->revision = 0; - chip->ident = V4L2_IDENT_UNKNOWN; - ret = 0; - } - return ret; -} #endif #if IS_ENABLED(CONFIG_INPUT) @@ -931,7 +915,6 @@ static const struct sd_desc sd_desc = { .dq_callback = do_autogain, #ifdef CONFIG_VIDEO_ADV_DEBUG .set_register = sd_dbg_s_register, - .get_chip_ident = sd_chip_ident, #endif #if IS_ENABLED(CONFIG_INPUT) .int_pkt_scan = sd_int_pkt_scan, diff --git a/drivers/media/usb/gspca/sn9c20x.c b/drivers/media/usb/gspca/sn9c20x.c index ead9a1f58513..f4453d52801b 100644 --- a/drivers/media/usb/gspca/sn9c20x.c +++ b/drivers/media/usb/gspca/sn9c20x.c @@ -27,7 +27,6 @@ #include "gspca.h" #include "jpeg.h" -#include <media/v4l2-chip-ident.h> #include <linux/dmi.h> MODULE_AUTHOR("Brian Johnson <brijohn@gmail.com>, " @@ -582,22 +581,6 @@ static const s16 hsv_blue_y[] = { 4, 2, 0, -1, -3, -5, -7, -9, -11 }; -static const u16 i2c_ident[] = { - V4L2_IDENT_OV9650, - V4L2_IDENT_OV9655, - V4L2_IDENT_SOI968, - V4L2_IDENT_OV7660, - V4L2_IDENT_OV7670, - V4L2_IDENT_MT9V011, - V4L2_IDENT_MT9V111, - V4L2_IDENT_MT9V112, - V4L2_IDENT_MT9M001C12ST, - V4L2_IDENT_MT9M111, - V4L2_IDENT_MT9M112, - V4L2_IDENT_HV7131R, -[SENSOR_MT9VPRB] = V4L2_IDENT_UNKNOWN, -}; - static const u16 bridge_init[][2] = { {0x1000, 0x78}, {0x1001, 0x40}, {0x1002, 0x1c}, {0x1020, 0x80}, {0x1061, 0x01}, {0x1067, 0x40}, @@ -1574,21 +1557,19 @@ static int sd_dbg_g_register(struct gspca_dev *gspca_dev, { struct sd *sd = (struct sd *) gspca_dev; - switch (reg->match.type) { - case V4L2_CHIP_MATCH_HOST: - if (reg->match.addr != 0) - return -EINVAL; + reg->size = 1; + switch (reg->match.addr) { + case 0: if (reg->reg < 0x1000 || reg->reg > 0x11ff) return -EINVAL; reg_r(gspca_dev, reg->reg, 1); reg->val = gspca_dev->usb_buf[0]; return gspca_dev->usb_err; - case V4L2_CHIP_MATCH_I2C_ADDR: - if (reg->match.addr != sd->i2c_addr) - return -EINVAL; + case 1: if (sd->sensor >= SENSOR_MT9V011 && sd->sensor <= SENSOR_MT9M112) { i2c_r2(gspca_dev, reg->reg, (u16 *) ®->val); + reg->size = 2; } else { i2c_r1(gspca_dev, reg->reg, (u8 *) ®->val); } @@ -1602,17 +1583,13 @@ static int sd_dbg_s_register(struct gspca_dev *gspca_dev, { struct sd *sd = (struct sd *) gspca_dev; - switch (reg->match.type) { - case V4L2_CHIP_MATCH_HOST: - if (reg->match.addr != 0) - return -EINVAL; + switch (reg->match.addr) { + case 0: if (reg->reg < 0x1000 || reg->reg > 0x11ff) return -EINVAL; reg_w1(gspca_dev, reg->reg, reg->val); return gspca_dev->usb_err; - case V4L2_CHIP_MATCH_I2C_ADDR: - if (reg->match.addr != sd->i2c_addr) - return -EINVAL; + case 1: if (sd->sensor >= SENSOR_MT9V011 && sd->sensor <= SENSOR_MT9M112) { i2c_w2(gspca_dev, reg->reg, reg->val); @@ -1623,29 +1600,17 @@ static int sd_dbg_s_register(struct gspca_dev *gspca_dev, } return -EINVAL; } -#endif -static int sd_chip_ident(struct gspca_dev *gspca_dev, - struct v4l2_dbg_chip_ident *chip) +static int sd_chip_info(struct gspca_dev *gspca_dev, + struct v4l2_dbg_chip_info *chip) { - struct sd *sd = (struct sd *) gspca_dev; - - switch (chip->match.type) { - case V4L2_CHIP_MATCH_HOST: - if (chip->match.addr != 0) - return -EINVAL; - chip->revision = 0; - chip->ident = V4L2_IDENT_SN9C20X; - return 0; - case V4L2_CHIP_MATCH_I2C_ADDR: - if (chip->match.addr != sd->i2c_addr) - return -EINVAL; - chip->revision = 0; - chip->ident = i2c_ident[sd->sensor]; - return 0; - } - return -EINVAL; + if (chip->match.addr > 1) + return -EINVAL; + if (chip->match.addr == 1) + strlcpy(chip->name, "sensor", sizeof(chip->name)); + return 0; } +#endif static int sd_config(struct gspca_dev *gspca_dev, const struct usb_device_id *id) @@ -2356,8 +2321,8 @@ static const struct sd_desc sd_desc = { #ifdef CONFIG_VIDEO_ADV_DEBUG .set_register = sd_dbg_s_register, .get_register = sd_dbg_g_register, + .get_chip_info = sd_chip_info, #endif - .get_chip_ident = sd_chip_ident, }; #define SN9C20X(sensor, i2c_addr, flags) \ diff --git a/drivers/media/usb/hdpvr/Kconfig b/drivers/media/usb/hdpvr/Kconfig index de247f3c7d05..d73d9a1952b4 100644 --- a/drivers/media/usb/hdpvr/Kconfig +++ b/drivers/media/usb/hdpvr/Kconfig @@ -1,7 +1,7 @@ config VIDEO_HDPVR tristate "Hauppauge HD PVR support" - depends on VIDEO_DEV + depends on VIDEO_DEV && VIDEO_V4L2 ---help--- This is a video4linux driver for Hauppauge's HD PVR USB device. diff --git a/drivers/media/usb/hdpvr/hdpvr-control.c b/drivers/media/usb/hdpvr/hdpvr-control.c index ae8f229d1141..6053661dc04b 100644 --- a/drivers/media/usb/hdpvr/hdpvr-control.c +++ b/drivers/media/usb/hdpvr/hdpvr-control.c @@ -45,20 +45,11 @@ int hdpvr_config_call(struct hdpvr_device *dev, uint value, u8 valbuf) return ret < 0 ? ret : 0; } -struct hdpvr_video_info *get_video_info(struct hdpvr_device *dev) +int get_video_info(struct hdpvr_device *dev, struct hdpvr_video_info *vidinf) { - struct hdpvr_video_info *vidinf = NULL; -#ifdef HDPVR_DEBUG - char print_buf[15]; -#endif int ret; - vidinf = kzalloc(sizeof(struct hdpvr_video_info), GFP_KERNEL); - if (!vidinf) { - v4l2_err(&dev->v4l2_dev, "out of memory\n"); - goto err; - } - + vidinf->valid = false; mutex_lock(&dev->usbc_mutex); ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), @@ -66,14 +57,10 @@ struct hdpvr_video_info *get_video_info(struct hdpvr_device *dev) 0x1400, 0x0003, dev->usbc_buf, 5, 1000); - if (ret == 5) { - vidinf->width = dev->usbc_buf[1] << 8 | dev->usbc_buf[0]; - vidinf->height = dev->usbc_buf[3] << 8 | dev->usbc_buf[2]; - vidinf->fps = dev->usbc_buf[4]; - } #ifdef HDPVR_DEBUG if (hdpvr_debug & MSG_INFO) { + char print_buf[15]; hex_dump_to_buffer(dev->usbc_buf, 5, 16, 1, print_buf, sizeof(print_buf), 0); v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, @@ -82,12 +69,15 @@ struct hdpvr_video_info *get_video_info(struct hdpvr_device *dev) #endif mutex_unlock(&dev->usbc_mutex); - if (!vidinf->width || !vidinf->height || !vidinf->fps) { - kfree(vidinf); - vidinf = NULL; - } -err: - return vidinf; + if (ret < 0) + return ret; + + vidinf->width = dev->usbc_buf[1] << 8 | dev->usbc_buf[0]; + vidinf->height = dev->usbc_buf[3] << 8 | dev->usbc_buf[2]; + vidinf->fps = dev->usbc_buf[4]; + vidinf->valid = vidinf->width && vidinf->height && vidinf->fps; + + return 0; } int get_input_lines_info(struct hdpvr_device *dev) diff --git a/drivers/media/usb/hdpvr/hdpvr-core.c b/drivers/media/usb/hdpvr/hdpvr-core.c index 8247c19d6260..cb694055ba7d 100644 --- a/drivers/media/usb/hdpvr/hdpvr-core.c +++ b/drivers/media/usb/hdpvr/hdpvr-core.c @@ -220,7 +220,6 @@ static int hdpvr_device_init(struct hdpvr_device *dev) { int ret; u8 *buf; - struct hdpvr_video_info *vidinf; if (device_authorization(dev)) return -EACCES; @@ -242,13 +241,6 @@ static int hdpvr_device_init(struct hdpvr_device *dev) "control request returned %d\n", ret); mutex_unlock(&dev->usbc_mutex); - vidinf = get_video_info(dev); - if (!vidinf) - v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, - "no valid video signal or device init failed\n"); - else - kfree(vidinf); - /* enable fan and bling leds */ mutex_lock(&dev->usbc_mutex); buf[0] = 0x1; diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c index 774ba0e820be..4f8567aa99d8 100644 --- a/drivers/media/usb/hdpvr/hdpvr-video.c +++ b/drivers/media/usb/hdpvr/hdpvr-video.c @@ -277,44 +277,50 @@ error: static int hdpvr_start_streaming(struct hdpvr_device *dev) { int ret; - struct hdpvr_video_info *vidinf; + struct hdpvr_video_info vidinf; if (dev->status == STATUS_STREAMING) return 0; - else if (dev->status != STATUS_IDLE) + if (dev->status != STATUS_IDLE) return -EAGAIN; - vidinf = get_video_info(dev); + ret = get_video_info(dev, &vidinf); + if (ret < 0) + return ret; - if (vidinf) { - v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, - "video signal: %dx%d@%dhz\n", vidinf->width, - vidinf->height, vidinf->fps); - kfree(vidinf); - - /* start streaming 2 request */ - ret = usb_control_msg(dev->udev, - usb_sndctrlpipe(dev->udev, 0), - 0xb8, 0x38, 0x1, 0, NULL, 0, 8000); - v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, - "encoder start control request returned %d\n", ret); + if (!vidinf.valid) { + msleep(250); + v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, + "no video signal at input %d\n", dev->options.video_input); + return -EAGAIN; + } - hdpvr_config_call(dev, CTRL_START_STREAMING_VALUE, 0x00); + v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, + "video signal: %dx%d@%dhz\n", vidinf.width, + vidinf.height, vidinf.fps); - dev->status = STATUS_STREAMING; + /* start streaming 2 request */ + ret = usb_control_msg(dev->udev, + usb_sndctrlpipe(dev->udev, 0), + 0xb8, 0x38, 0x1, 0, NULL, 0, 8000); + v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, + "encoder start control request returned %d\n", ret); + if (ret < 0) + return ret; - INIT_WORK(&dev->worker, hdpvr_transmit_buffers); - queue_work(dev->workqueue, &dev->worker); + ret = hdpvr_config_call(dev, CTRL_START_STREAMING_VALUE, 0x00); + if (ret) + return ret; - v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, - "streaming started\n"); + dev->status = STATUS_STREAMING; - return 0; - } - msleep(250); - v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, - "no video signal at input %d\n", dev->options.video_input); - return -EAGAIN; + INIT_WORK(&dev->worker, hdpvr_transmit_buffers); + queue_work(dev->workqueue, &dev->worker); + + v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, + "streaming started\n"); + + return 0; } @@ -606,22 +612,20 @@ static int vidioc_g_std(struct file *file, void *_fh, static int vidioc_querystd(struct file *file, void *_fh, v4l2_std_id *a) { struct hdpvr_device *dev = video_drvdata(file); - struct hdpvr_video_info *vid_info; + struct hdpvr_video_info vid_info; struct hdpvr_fh *fh = _fh; + int ret; - *a = V4L2_STD_ALL; + *a = V4L2_STD_UNKNOWN; if (dev->options.video_input == HDPVR_COMPONENT) return fh->legacy_mode ? 0 : -ENODATA; - vid_info = get_video_info(dev); - if (vid_info == NULL) - return 0; - if (vid_info->width == 720 && - (vid_info->height == 480 || vid_info->height == 576)) { - *a = (vid_info->height == 480) ? + ret = get_video_info(dev, &vid_info); + if (vid_info.valid && vid_info.width == 720 && + (vid_info.height == 480 || vid_info.height == 576)) { + *a = (vid_info.height == 480) ? V4L2_STD_525_60 : V4L2_STD_625_50; } - kfree(vid_info); - return 0; + return ret; } static int vidioc_s_dv_timings(struct file *file, void *_fh, @@ -665,7 +669,7 @@ static int vidioc_query_dv_timings(struct file *file, void *_fh, { struct hdpvr_device *dev = video_drvdata(file); struct hdpvr_fh *fh = _fh; - struct hdpvr_video_info *vid_info; + struct hdpvr_video_info vid_info; bool interlaced; int ret = 0; int i; @@ -673,10 +677,12 @@ static int vidioc_query_dv_timings(struct file *file, void *_fh, fh->legacy_mode = false; if (dev->options.video_input) return -ENODATA; - vid_info = get_video_info(dev); - if (vid_info == NULL) + ret = get_video_info(dev, &vid_info); + if (ret) + return ret; + if (!vid_info.valid) return -ENOLCK; - interlaced = vid_info->fps <= 30; + interlaced = vid_info.fps <= 30; for (i = 0; i < ARRAY_SIZE(hdpvr_dv_timings); i++) { const struct v4l2_bt_timings *bt = &hdpvr_dv_timings[i].bt; unsigned hsize; @@ -688,17 +694,17 @@ static int vidioc_query_dv_timings(struct file *file, void *_fh, bt->il_vfrontporch + bt->il_vsync + bt->il_vbackporch + bt->height; fps = (unsigned)bt->pixelclock / (hsize * vsize); - if (bt->width != vid_info->width || - bt->height != vid_info->height || + if (bt->width != vid_info.width || + bt->height != vid_info.height || bt->interlaced != interlaced || - (fps != vid_info->fps && fps + 1 != vid_info->fps)) + (fps != vid_info.fps && fps + 1 != vid_info.fps)) continue; *timings = hdpvr_dv_timings[i]; break; } if (i == ARRAY_SIZE(hdpvr_dv_timings)) ret = -ERANGE; - kfree(vid_info); + return ret; } @@ -988,6 +994,7 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *_fh, { struct hdpvr_device *dev = video_drvdata(file); struct hdpvr_fh *fh = _fh; + int ret; /* * The original driver would always returns the current detected @@ -1000,14 +1007,15 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *_fh, * last set format. */ if (fh->legacy_mode) { - struct hdpvr_video_info *vid_info; + struct hdpvr_video_info vid_info; - vid_info = get_video_info(dev); - if (!vid_info) + ret = get_video_info(dev, &vid_info); + if (ret < 0) + return ret; + if (!vid_info.valid) return -EFAULT; - f->fmt.pix.width = vid_info->width; - f->fmt.pix.height = vid_info->height; - kfree(vid_info); + f->fmt.pix.width = vid_info.width; + f->fmt.pix.height = vid_info.height; } else { f->fmt.pix.width = dev->width; f->fmt.pix.height = dev->height; diff --git a/drivers/media/usb/hdpvr/hdpvr.h b/drivers/media/usb/hdpvr/hdpvr.h index 1478f3d57630..dc685d44cb3e 100644 --- a/drivers/media/usb/hdpvr/hdpvr.h +++ b/drivers/media/usb/hdpvr/hdpvr.h @@ -154,6 +154,7 @@ struct hdpvr_video_info { u16 width; u16 height; u8 fps; + bool valid; }; enum { @@ -303,7 +304,7 @@ int hdpvr_set_audio(struct hdpvr_device *dev, u8 input, int hdpvr_config_call(struct hdpvr_device *dev, uint value, unsigned char valbuf); -struct hdpvr_video_info *get_video_info(struct hdpvr_device *dev); +int get_video_info(struct hdpvr_device *dev, struct hdpvr_video_info *vid_info); /* :0 s b8 81 1800 0003 0003 3 < */ /* :0 0 3 = 0301ff */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c index e11267f35d87..c4d51d78f837 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c @@ -2704,6 +2704,10 @@ static void pvr2_hdw_remove_usb_stuff(struct pvr2_hdw *hdw) pvr2_hdw_render_useless(hdw); } +void pvr2_hdw_set_v4l2_dev(struct pvr2_hdw *hdw, struct video_device *vdev) +{ + vdev->v4l2_dev = &hdw->v4l2_dev; +} /* Destroy hardware interaction structure */ void pvr2_hdw_destroy(struct pvr2_hdw *hdw) @@ -5162,41 +5166,3 @@ static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw) } while(0); LOCK_GIVE(hdw->ctl_lock); return result; } - - -int pvr2_hdw_register_access(struct pvr2_hdw *hdw, - const struct v4l2_dbg_match *match, u64 reg_id, - int setFl, u64 *val_ptr) -{ -#ifdef CONFIG_VIDEO_ADV_DEBUG - struct v4l2_dbg_register req; - int stat = 0; - int okFl = 0; - - if (!capable(CAP_SYS_ADMIN)) return -EPERM; - - req.match = *match; - req.reg = reg_id; - if (setFl) req.val = *val_ptr; - /* It would be nice to know if a sub-device answered the request */ - v4l2_device_call_all(&hdw->v4l2_dev, 0, core, g_register, &req); - if (!setFl) *val_ptr = req.val; - if (okFl) { - return stat; - } - return -EINVAL; -#else - return -ENOSYS; -#endif -} - - -/* - Stuff for Emacs to see, in order to encourage consistent editing style: - *** Local Variables: *** - *** mode: c *** - *** fill-column: 75 *** - *** tab-width: 8 *** - *** c-basic-offset: 8 *** - *** End: *** - */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.h b/drivers/media/usb/pvrusb2/pvrusb2-hdw.h index 91bae930cd79..41847076f51a 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.h @@ -22,6 +22,7 @@ #include <linux/usb.h> #include <linux/videodev2.h> +#include <media/v4l2-dev.h> #include "pvrusb2-io.h" #include "pvrusb2-ctrl.h" @@ -138,6 +139,9 @@ const char *pvr2_hdw_get_device_identifier(struct pvr2_hdw *); /* Called when hardware has been unplugged */ void pvr2_hdw_disconnect(struct pvr2_hdw *); +/* Sets v4l2_dev of a video_device struct */ +void pvr2_hdw_set_v4l2_dev(struct pvr2_hdw *, struct video_device *); + /* Get the number of defined controls */ unsigned int pvr2_hdw_get_ctrl_count(struct pvr2_hdw *); @@ -234,15 +238,6 @@ int pvr2_hdw_v4l_get_minor_number(struct pvr2_hdw *,enum pvr2_v4l_type index); void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *, enum pvr2_v4l_type index,int); -/* Direct read/write access to chip's registers: - match - specify criteria to identify target chip (this is a v4l dbg struct) - reg_id - register number to access - setFl - true to set the register, false to read it - val_ptr - storage location for source / result. */ -int pvr2_hdw_register_access(struct pvr2_hdw *, - const struct v4l2_dbg_match *match, u64 reg_id, - int setFl, u64 *val_ptr); - /* The following entry points are all lower level things you normally don't want to worry about. */ diff --git a/drivers/media/usb/pvrusb2/pvrusb2-io.c b/drivers/media/usb/pvrusb2/pvrusb2-io.c index 20b6ae0bb40d..1e354747de3f 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-io.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-io.c @@ -354,9 +354,9 @@ static int pvr2_stream_buffer_count(struct pvr2_stream *sp,unsigned int cnt) if (scnt < sp->buffer_slot_count) { struct pvr2_buffer **nb = NULL; if (scnt) { - nb = kmalloc(scnt * sizeof(*nb),GFP_KERNEL); + nb = kmemdup(sp->buffers, scnt * sizeof(*nb), + GFP_KERNEL); if (!nb) return -ENOMEM; - memcpy(nb,sp->buffers,scnt * sizeof(*nb)); } kfree(sp->buffers); sp->buffers = nb; diff --git a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c index a8a65fa57930..7c280f35eea9 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c @@ -31,6 +31,7 @@ #include <linux/videodev2.h> #include <linux/module.h> #include <media/v4l2-dev.h> +#include <media/v4l2-device.h> #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> @@ -800,36 +801,6 @@ static int pvr2_log_status(struct file *file, void *priv) return 0; } -#ifdef CONFIG_VIDEO_ADV_DEBUG -static int pvr2_g_register(struct file *file, void *priv, struct v4l2_dbg_register *req) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - u64 val; - int ret; - - ret = pvr2_hdw_register_access( - hdw, &req->match, req->reg, - 0, &val); - req->val = val; - return ret; -} - -static int pvr2_s_register(struct file *file, void *priv, const struct v4l2_dbg_register *req) -{ - struct pvr2_v4l2_fh *fh = file->private_data; - struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; - u64 val; - int ret; - - val = req->val; - ret = pvr2_hdw_register_access( - hdw, &req->match, req->reg, - 1, &val); - return ret; -} -#endif - static const struct v4l2_ioctl_ops pvr2_ioctl_ops = { .vidioc_querycap = pvr2_querycap, .vidioc_g_priority = pvr2_g_priority, @@ -864,10 +835,6 @@ static const struct v4l2_ioctl_ops pvr2_ioctl_ops = { .vidioc_g_ext_ctrls = pvr2_g_ext_ctrls, .vidioc_s_ext_ctrls = pvr2_s_ext_ctrls, .vidioc_try_ext_ctrls = pvr2_try_ext_ctrls, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = pvr2_g_register, - .vidioc_s_register = pvr2_s_register, -#endif }; static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip) @@ -904,8 +871,8 @@ static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip) static void pvr2_v4l2_dev_disassociate_parent(struct pvr2_v4l2_dev *dip) { if (!dip) return; - if (!dip->devbase.parent) return; - dip->devbase.parent = NULL; + if (!dip->devbase.v4l2_dev->dev) return; + dip->devbase.v4l2_dev->dev = NULL; device_move(&dip->devbase.dev, NULL, DPM_ORDER_NONE); } @@ -1298,7 +1265,6 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, struct pvr2_v4l2 *vp, int v4l_type) { - struct usb_device *usbdev; int mindevnum; int unit_number; struct pvr2_hdw *hdw; @@ -1306,7 +1272,6 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, dip->v4lp = vp; hdw = vp->channel.mc_head->hdw; - usbdev = pvr2_hdw_get_dev(hdw); dip->v4l_type = v4l_type; switch (v4l_type) { case VFL_TYPE_GRABBER: @@ -1355,7 +1320,7 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) { mindevnum = nr_ptr[unit_number]; } - dip->devbase.parent = &usbdev->dev; + pvr2_hdw_set_v4l2_dev(hdw, &dip->devbase); if ((video_register_device(&dip->devbase, dip->v4l_type, mindevnum) < 0) && (video_register_device(&dip->devbase, diff --git a/drivers/media/usb/sn9c102/sn9c102.h b/drivers/media/usb/sn9c102/sn9c102.h index 2bc153e869be..8a917f060503 100644 --- a/drivers/media/usb/sn9c102/sn9c102.h +++ b/drivers/media/usb/sn9c102/sn9c102.h @@ -25,6 +25,7 @@ #include <linux/videodev2.h> #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> +#include <media/v4l2-device.h> #include <linux/device.h> #include <linux/list.h> #include <linux/spinlock.h> @@ -100,6 +101,8 @@ static DECLARE_RWSEM(sn9c102_dev_lock); struct sn9c102_device { struct video_device* v4ldev; + struct v4l2_device v4l2_dev; + enum sn9c102_bridge bridge; struct sn9c102_sensor sensor; diff --git a/drivers/media/usb/sn9c102/sn9c102_core.c b/drivers/media/usb/sn9c102/sn9c102_core.c index c957e9aa6077..2cb44de2b92c 100644 --- a/drivers/media/usb/sn9c102/sn9c102_core.c +++ b/drivers/media/usb/sn9c102/sn9c102_core.c @@ -1737,6 +1737,7 @@ static void sn9c102_release_resources(struct kref *kref) video_device_node_name(cam->v4ldev)); video_set_drvdata(cam->v4ldev, NULL); video_unregister_device(cam->v4ldev); + v4l2_device_unregister(&cam->v4l2_dev); usb_put_dev(cam->usbdev); kfree(cam->control_buffer); kfree(cam); @@ -3254,6 +3255,13 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) cam->usbdev = udev; + /* register v4l2_device early so it can be used for printks */ + if (v4l2_device_register(&intf->dev, &cam->v4l2_dev)) { + dev_err(&intf->dev, "v4l2_device_register failed\n"); + err = -ENOMEM; + goto fail; + } + if (!(cam->control_buffer = kzalloc(8, GFP_KERNEL))) { DBG(1, "kzalloc() failed"); err = -ENOMEM; @@ -3325,7 +3333,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) strcpy(cam->v4ldev->name, "SN9C1xx PC Camera"); cam->v4ldev->fops = &sn9c102_fops; cam->v4ldev->release = video_device_release; - cam->v4ldev->parent = &udev->dev; + cam->v4ldev->v4l2_dev = &cam->v4l2_dev; init_completion(&cam->probe); @@ -3377,6 +3385,7 @@ fail: kfree(cam->control_buffer); if (cam->v4ldev) video_device_release(cam->v4ldev); + v4l2_device_unregister(&cam->v4l2_dev); kfree(cam); } return err; @@ -3407,6 +3416,8 @@ static void sn9c102_usb_disconnect(struct usb_interface* intf) wake_up_interruptible_all(&cam->wait_open); + v4l2_device_disconnect(&cam->v4l2_dev); + kref_put(&cam->kref, sn9c102_release_resources); up_write(&sn9c102_dev_lock); diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c index a59153d2f8bf..876fc26565e3 100644 --- a/drivers/media/usb/stk1160/stk1160-v4l.c +++ b/drivers/media/usb/stk1160/stk1160-v4l.c @@ -31,7 +31,6 @@ #include <media/v4l2-ioctl.h> #include <media/v4l2-fh.h> #include <media/v4l2-event.h> -#include <media/v4l2-chip-ident.h> #include <media/videobuf2-vmalloc.h> #include <media/saa7115.h> @@ -454,19 +453,6 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) return 0; } -static int vidioc_g_chip_ident(struct file *file, void *priv, - struct v4l2_dbg_chip_ident *chip) -{ - switch (chip->match.type) { - case V4L2_CHIP_MATCH_BRIDGE: - chip->ident = V4L2_IDENT_NONE; - chip->revision = 0; - return 0; - default: - return -EINVAL; - } -} - #ifdef CONFIG_VIDEO_ADV_DEBUG static int vidioc_g_register(struct file *file, void *priv, struct v4l2_dbg_register *reg) @@ -475,19 +461,6 @@ static int vidioc_g_register(struct file *file, void *priv, int rc; u8 val; - switch (reg->match.type) { - case V4L2_CHIP_MATCH_I2C_DRIVER: - v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg); - return 0; - case V4L2_CHIP_MATCH_I2C_ADDR: - /* TODO: is this correct? */ - v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg); - return 0; - default: - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; - } - /* Match host */ rc = stk1160_read_reg(dev, reg->reg, &val); reg->val = val; @@ -501,19 +474,6 @@ static int vidioc_s_register(struct file *file, void *priv, { struct stk1160 *dev = video_drvdata(file); - switch (reg->match.type) { - case V4L2_CHIP_MATCH_I2C_DRIVER: - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg); - return 0; - case V4L2_CHIP_MATCH_I2C_ADDR: - /* TODO: is this correct? */ - v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg); - return 0; - default: - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; - } - /* Match host */ return stk1160_write_reg(dev, reg->reg, cpu_to_le16(reg->val)); } @@ -543,7 +503,6 @@ static const struct v4l2_ioctl_ops stk1160_ioctl_ops = { .vidioc_log_status = v4l2_ctrl_log_status, .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, .vidioc_unsubscribe_event = v4l2_event_unsubscribe, - .vidioc_g_chip_ident = vidioc_g_chip_ident, #ifdef CONFIG_VIDEO_ADV_DEBUG .vidioc_g_register = vidioc_g_register, diff --git a/drivers/media/usb/tm6000/tm6000-cards.c b/drivers/media/usb/tm6000/tm6000-cards.c index 307d8c5fb7cd..1ccaaddaa307 100644 --- a/drivers/media/usb/tm6000/tm6000-cards.c +++ b/drivers/media/usb/tm6000/tm6000-cards.c @@ -1114,7 +1114,7 @@ static int tm6000_init_dev(struct tm6000_core *dev) /* Default values for STD and resolutions */ dev->width = 720; dev->height = 480; - dev->norm = V4L2_STD_PAL_M; + dev->norm = V4L2_STD_NTSC_M; /* Configure tuner */ tm6000_config_tuner(dev); diff --git a/drivers/media/usb/tm6000/tm6000-video.c b/drivers/media/usb/tm6000/tm6000-video.c index a78de1d1bc9e..cc1aa14996ff 100644 --- a/drivers/media/usb/tm6000/tm6000-video.c +++ b/drivers/media/usb/tm6000/tm6000-video.c @@ -1076,6 +1076,15 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm) return 0; } +static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm) +{ + struct tm6000_fh *fh = priv; + struct tm6000_core *dev = fh->dev; + + *norm = dev->norm; + return 0; +} + static const char *iname[] = { [TM6000_INPUT_TV] = "Television", [TM6000_INPUT_COMPOSITE1] = "Composite 1", @@ -1134,7 +1143,7 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) dev->input = i; - rc = vidioc_s_std(file, priv, dev->vfd->current_norm); + rc = vidioc_s_std(file, priv, dev->norm); return rc; } @@ -1547,6 +1556,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, .vidioc_s_std = vidioc_s_std, + .vidioc_g_std = vidioc_g_std, .vidioc_enum_input = vidioc_enum_input, .vidioc_g_input = vidioc_g_input, .vidioc_s_input = vidioc_s_input, @@ -1570,7 +1580,6 @@ static struct video_device tm6000_template = { .ioctl_ops = &video_ioctl_ops, .release = video_device_release, .tvnorms = TM6000_STD, - .current_norm = V4L2_STD_NTSC_M, }; static const struct v4l2_file_operations radio_fops = { diff --git a/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c index 21b9049c7b3f..f8a60c197534 100644 --- a/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c @@ -1768,6 +1768,8 @@ err_i2c_del_adapter: i2c_del_adapter(&ttusb->i2c_adap); err_unregister_adapter: dvb_unregister_adapter (&ttusb->adapter); + ttusb_free_iso_urbs(ttusb); + kfree(ttusb); return result; } diff --git a/drivers/media/usb/usbtv/Kconfig b/drivers/media/usb/usbtv/Kconfig new file mode 100644 index 000000000000..8864436464bf --- /dev/null +++ b/drivers/media/usb/usbtv/Kconfig @@ -0,0 +1,10 @@ +config VIDEO_USBTV + tristate "USBTV007 video capture support" + depends on VIDEO_DEV + select VIDEOBUF2_VMALLOC + + ---help--- + This is a video4linux2 driver for USBTV007 based video capture devices. + + To compile this driver as a module, choose M here: the + module will be called usbtv diff --git a/drivers/media/usb/usbtv/Makefile b/drivers/media/usb/usbtv/Makefile new file mode 100644 index 000000000000..28b872fa94e1 --- /dev/null +++ b/drivers/media/usb/usbtv/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_VIDEO_USBTV) += usbtv.o diff --git a/drivers/media/usb/usbtv/usbtv.c b/drivers/media/usb/usbtv/usbtv.c new file mode 100644 index 000000000000..bf43f874685e --- /dev/null +++ b/drivers/media/usb/usbtv/usbtv.c @@ -0,0 +1,696 @@ +/* + * Fushicai USBTV007 Video Grabber Driver + * + * Product web site: + * http://www.fushicai.com/products_detail/&productId=d05449ee-b690-42f9-a661-aa7353894bed.html + * + * Following LWN articles were very useful in construction of this driver: + * Video4Linux2 API series: http://lwn.net/Articles/203924/ + * videobuf2 API explanation: http://lwn.net/Articles/447435/ + * Thanks go to Jonathan Corbet for providing this quality documentation. + * He is awesome. + * + * Copyright (c) 2013 Lubomir Rintel + * All rights reserved. + * No physical hardware was harmed running Windows during the + * reverse-engineering activity + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL"). + */ + +#include <linux/init.h> +#include <linux/list.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/usb.h> +#include <linux/version.h> +#include <linux/videodev2.h> + +#include <media/v4l2-device.h> +#include <media/v4l2-ioctl.h> +#include <media/videobuf2-core.h> +#include <media/videobuf2-vmalloc.h> + +/* Hardware. */ +#define USBTV_VIDEO_ENDP 0x81 +#define USBTV_BASE 0xc000 +#define USBTV_REQUEST_REG 12 + +/* Number of concurrent isochronous urbs submitted. + * Higher numbers was seen to overly saturate the USB bus. */ +#define USBTV_ISOC_TRANSFERS 16 +#define USBTV_ISOC_PACKETS 8 + +#define USBTV_WIDTH 720 +#define USBTV_HEIGHT 480 + +#define USBTV_CHUNK_SIZE 256 +#define USBTV_CHUNK 240 +#define USBTV_CHUNKS (USBTV_WIDTH * USBTV_HEIGHT \ + / 2 / USBTV_CHUNK) + +/* Chunk header. */ +#define USBTV_MAGIC_OK(chunk) ((be32_to_cpu(chunk[0]) & 0xff000000) \ + == 0x88000000) +#define USBTV_FRAME_ID(chunk) ((be32_to_cpu(chunk[0]) & 0x00ff0000) >> 16) +#define USBTV_ODD(chunk) ((be32_to_cpu(chunk[0]) & 0x0000f000) >> 15) +#define USBTV_CHUNK_NO(chunk) (be32_to_cpu(chunk[0]) & 0x00000fff) + +/* A single videobuf2 frame buffer. */ +struct usbtv_buf { + struct vb2_buffer vb; + struct list_head list; +}; + +/* Per-device structure. */ +struct usbtv { + struct device *dev; + struct usb_device *udev; + struct v4l2_device v4l2_dev; + struct video_device vdev; + struct vb2_queue vb2q; + struct mutex v4l2_lock; + struct mutex vb2q_lock; + + /* List of videobuf2 buffers protected by a lock. */ + spinlock_t buflock; + struct list_head bufs; + + /* Number of currently processed frame, useful find + * out when a new one begins. */ + u32 frame_id; + + int iso_size; + unsigned int sequence; + struct urb *isoc_urbs[USBTV_ISOC_TRANSFERS]; +}; + +static int usbtv_setup_capture(struct usbtv *usbtv) +{ + int ret; + int pipe = usb_rcvctrlpipe(usbtv->udev, 0); + int i; + static const u16 protoregs[][2] = { + /* These seem to enable the device. */ + { USBTV_BASE + 0x0008, 0x0001 }, + { USBTV_BASE + 0x01d0, 0x00ff }, + { USBTV_BASE + 0x01d9, 0x0002 }, + + /* These seem to influence color parameters, such as + * brightness, etc. */ + { USBTV_BASE + 0x0239, 0x0040 }, + { USBTV_BASE + 0x0240, 0x0000 }, + { USBTV_BASE + 0x0241, 0x0000 }, + { USBTV_BASE + 0x0242, 0x0002 }, + { USBTV_BASE + 0x0243, 0x0080 }, + { USBTV_BASE + 0x0244, 0x0012 }, + { USBTV_BASE + 0x0245, 0x0090 }, + { USBTV_BASE + 0x0246, 0x0000 }, + + { USBTV_BASE + 0x0278, 0x002d }, + { USBTV_BASE + 0x0279, 0x000a }, + { USBTV_BASE + 0x027a, 0x0032 }, + { 0xf890, 0x000c }, + { 0xf894, 0x0086 }, + + { USBTV_BASE + 0x00ac, 0x00c0 }, + { USBTV_BASE + 0x00ad, 0x0000 }, + { USBTV_BASE + 0x00a2, 0x0012 }, + { USBTV_BASE + 0x00a3, 0x00e0 }, + { USBTV_BASE + 0x00a4, 0x0028 }, + { USBTV_BASE + 0x00a5, 0x0082 }, + { USBTV_BASE + 0x00a7, 0x0080 }, + { USBTV_BASE + 0x0000, 0x0014 }, + { USBTV_BASE + 0x0006, 0x0003 }, + { USBTV_BASE + 0x0090, 0x0099 }, + { USBTV_BASE + 0x0091, 0x0090 }, + { USBTV_BASE + 0x0094, 0x0068 }, + { USBTV_BASE + 0x0095, 0x0070 }, + { USBTV_BASE + 0x009c, 0x0030 }, + { USBTV_BASE + 0x009d, 0x00c0 }, + { USBTV_BASE + 0x009e, 0x00e0 }, + { USBTV_BASE + 0x0019, 0x0006 }, + { USBTV_BASE + 0x008c, 0x00ba }, + { USBTV_BASE + 0x0101, 0x00ff }, + { USBTV_BASE + 0x010c, 0x00b3 }, + { USBTV_BASE + 0x01b2, 0x0080 }, + { USBTV_BASE + 0x01b4, 0x00a0 }, + { USBTV_BASE + 0x014c, 0x00ff }, + { USBTV_BASE + 0x014d, 0x00ca }, + { USBTV_BASE + 0x0113, 0x0053 }, + { USBTV_BASE + 0x0119, 0x008a }, + { USBTV_BASE + 0x013c, 0x0003 }, + { USBTV_BASE + 0x0150, 0x009c }, + { USBTV_BASE + 0x0151, 0x0071 }, + { USBTV_BASE + 0x0152, 0x00c6 }, + { USBTV_BASE + 0x0153, 0x0084 }, + { USBTV_BASE + 0x0154, 0x00bc }, + { USBTV_BASE + 0x0155, 0x00a0 }, + { USBTV_BASE + 0x0156, 0x00a0 }, + { USBTV_BASE + 0x0157, 0x009c }, + { USBTV_BASE + 0x0158, 0x001f }, + { USBTV_BASE + 0x0159, 0x0006 }, + { USBTV_BASE + 0x015d, 0x0000 }, + + { USBTV_BASE + 0x0284, 0x0088 }, + { USBTV_BASE + 0x0003, 0x0004 }, + { USBTV_BASE + 0x001a, 0x0079 }, + { USBTV_BASE + 0x0100, 0x00d3 }, + { USBTV_BASE + 0x010e, 0x0068 }, + { USBTV_BASE + 0x010f, 0x009c }, + { USBTV_BASE + 0x0112, 0x00f0 }, + { USBTV_BASE + 0x0115, 0x0015 }, + { USBTV_BASE + 0x0117, 0x0000 }, + { USBTV_BASE + 0x0118, 0x00fc }, + { USBTV_BASE + 0x012d, 0x0004 }, + { USBTV_BASE + 0x012f, 0x0008 }, + { USBTV_BASE + 0x0220, 0x002e }, + { USBTV_BASE + 0x0225, 0x0008 }, + { USBTV_BASE + 0x024e, 0x0002 }, + { USBTV_BASE + 0x024f, 0x0001 }, + { USBTV_BASE + 0x0254, 0x005f }, + { USBTV_BASE + 0x025a, 0x0012 }, + { USBTV_BASE + 0x025b, 0x0001 }, + { USBTV_BASE + 0x0263, 0x001c }, + { USBTV_BASE + 0x0266, 0x0011 }, + { USBTV_BASE + 0x0267, 0x0005 }, + { USBTV_BASE + 0x024e, 0x0002 }, + { USBTV_BASE + 0x024f, 0x0002 }, + }; + + for (i = 0; i < ARRAY_SIZE(protoregs); i++) { + u16 index = protoregs[i][0]; + u16 value = protoregs[i][1]; + + ret = usb_control_msg(usbtv->udev, pipe, USBTV_REQUEST_REG, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + value, index, NULL, 0, 0); + if (ret < 0) + return ret; + } + + return 0; +} + +/* Called for each 256-byte image chunk. + * First word identifies the chunk, followed by 240 words of image + * data and padding. */ +static void usbtv_image_chunk(struct usbtv *usbtv, u32 *chunk) +{ + int frame_id, odd, chunk_no; + u32 *frame; + struct usbtv_buf *buf; + unsigned long flags; + + /* Ignore corrupted lines. */ + if (!USBTV_MAGIC_OK(chunk)) + return; + frame_id = USBTV_FRAME_ID(chunk); + odd = USBTV_ODD(chunk); + chunk_no = USBTV_CHUNK_NO(chunk); + + /* Deinterlace. TODO: Use interlaced frame format. */ + chunk_no = (chunk_no - chunk_no % 3) * 2 + chunk_no % 3; + chunk_no += !odd * 3; + + if (chunk_no >= USBTV_CHUNKS) + return; + + /* Beginning of a frame. */ + if (chunk_no == 0) + usbtv->frame_id = frame_id; + + spin_lock_irqsave(&usbtv->buflock, flags); + if (list_empty(&usbtv->bufs)) { + /* No free buffers. Userspace likely too slow. */ + spin_unlock_irqrestore(&usbtv->buflock, flags); + return; + } + + /* First available buffer. */ + buf = list_first_entry(&usbtv->bufs, struct usbtv_buf, list); + frame = vb2_plane_vaddr(&buf->vb, 0); + + /* Copy the chunk. */ + memcpy(&frame[chunk_no * USBTV_CHUNK], &chunk[1], + USBTV_CHUNK * sizeof(chunk[1])); + + /* Last chunk in a frame, signalling an end */ + if (usbtv->frame_id && chunk_no == USBTV_CHUNKS-1) { + int size = vb2_plane_size(&buf->vb, 0); + + buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED; + buf->vb.v4l2_buf.sequence = usbtv->sequence++; + v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp); + vb2_set_plane_payload(&buf->vb, 0, size); + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE); + list_del(&buf->list); + } + + spin_unlock_irqrestore(&usbtv->buflock, flags); +} + +/* Got image data. Each packet contains a number of 256-word chunks we + * compose the image from. */ +static void usbtv_iso_cb(struct urb *ip) +{ + int ret; + int i; + struct usbtv *usbtv = (struct usbtv *)ip->context; + + switch (ip->status) { + /* All fine. */ + case 0: + break; + /* Device disconnected or capture stopped? */ + case -ENODEV: + case -ENOENT: + case -ECONNRESET: + case -ESHUTDOWN: + return; + /* Unknown error. Retry. */ + default: + dev_warn(usbtv->dev, "Bad response for ISO request.\n"); + goto resubmit; + } + + for (i = 0; i < ip->number_of_packets; i++) { + int size = ip->iso_frame_desc[i].actual_length; + unsigned char *data = ip->transfer_buffer + + ip->iso_frame_desc[i].offset; + int offset; + + for (offset = 0; USBTV_CHUNK_SIZE * offset < size; offset++) + usbtv_image_chunk(usbtv, + (u32 *)&data[USBTV_CHUNK_SIZE * offset]); + } + +resubmit: + ret = usb_submit_urb(ip, GFP_ATOMIC); + if (ret < 0) + dev_warn(usbtv->dev, "Could not resubmit ISO URB\n"); +} + +static struct urb *usbtv_setup_iso_transfer(struct usbtv *usbtv) +{ + struct urb *ip; + int size = usbtv->iso_size; + int i; + + ip = usb_alloc_urb(USBTV_ISOC_PACKETS, GFP_KERNEL); + if (ip == NULL) + return NULL; + + ip->dev = usbtv->udev; + ip->context = usbtv; + ip->pipe = usb_rcvisocpipe(usbtv->udev, USBTV_VIDEO_ENDP); + ip->interval = 1; + ip->transfer_flags = URB_ISO_ASAP; + ip->transfer_buffer = kzalloc(size * USBTV_ISOC_PACKETS, + GFP_KERNEL); + ip->complete = usbtv_iso_cb; + ip->number_of_packets = USBTV_ISOC_PACKETS; + ip->transfer_buffer_length = size * USBTV_ISOC_PACKETS; + for (i = 0; i < USBTV_ISOC_PACKETS; i++) { + ip->iso_frame_desc[i].offset = size * i; + ip->iso_frame_desc[i].length = size; + } + + return ip; +} + +static void usbtv_stop(struct usbtv *usbtv) +{ + int i; + unsigned long flags; + + /* Cancel running transfers. */ + for (i = 0; i < USBTV_ISOC_TRANSFERS; i++) { + struct urb *ip = usbtv->isoc_urbs[i]; + if (ip == NULL) + continue; + usb_kill_urb(ip); + kfree(ip->transfer_buffer); + usb_free_urb(ip); + usbtv->isoc_urbs[i] = NULL; + } + + /* Return buffers to userspace. */ + spin_lock_irqsave(&usbtv->buflock, flags); + while (!list_empty(&usbtv->bufs)) { + struct usbtv_buf *buf = list_first_entry(&usbtv->bufs, + struct usbtv_buf, list); + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); + list_del(&buf->list); + } + spin_unlock_irqrestore(&usbtv->buflock, flags); +} + +static int usbtv_start(struct usbtv *usbtv) +{ + int i; + int ret; + + ret = usb_set_interface(usbtv->udev, 0, 0); + if (ret < 0) + return ret; + + ret = usbtv_setup_capture(usbtv); + if (ret < 0) + return ret; + + ret = usb_set_interface(usbtv->udev, 0, 1); + if (ret < 0) + return ret; + + for (i = 0; i < USBTV_ISOC_TRANSFERS; i++) { + struct urb *ip; + + ip = usbtv_setup_iso_transfer(usbtv); + if (ip == NULL) { + ret = -ENOMEM; + goto start_fail; + } + usbtv->isoc_urbs[i] = ip; + + ret = usb_submit_urb(ip, GFP_KERNEL); + if (ret < 0) + goto start_fail; + } + + return 0; + +start_fail: + usbtv_stop(usbtv); + return ret; +} + +struct usb_device_id usbtv_id_table[] = { + { USB_DEVICE(0x1b71, 0x3002) }, + {} +}; +MODULE_DEVICE_TABLE(usb, usbtv_id_table); + +static int usbtv_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct usbtv *dev = video_drvdata(file); + + strlcpy(cap->driver, "usbtv", sizeof(cap->driver)); + strlcpy(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; + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; + return 0; +} + +static int usbtv_enum_input(struct file *file, void *priv, + struct v4l2_input *i) +{ + if (i->index > 0) + return -EINVAL; + + strlcpy(i->name, "Composite", sizeof(i->name)); + i->type = V4L2_INPUT_TYPE_CAMERA; + i->std = V4L2_STD_525_60; + return 0; +} + +static int usbtv_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + if (f->index > 0) + return -EINVAL; + + strlcpy(f->description, "16 bpp YUY2, 4:2:2, packed", + sizeof(f->description)); + f->pixelformat = V4L2_PIX_FMT_YUYV; + return 0; +} + +static int usbtv_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + f->fmt.pix.width = USBTV_WIDTH; + f->fmt.pix.height = USBTV_HEIGHT; + f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; + f->fmt.pix.field = V4L2_FIELD_INTERLACED; + f->fmt.pix.bytesperline = USBTV_WIDTH * 2; + f->fmt.pix.sizeimage = (f->fmt.pix.bytesperline * f->fmt.pix.height); + f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; + f->fmt.pix.priv = 0; + return 0; +} + +static int usbtv_g_std(struct file *file, void *priv, v4l2_std_id *norm) +{ + *norm = V4L2_STD_525_60; + return 0; +} + +static int usbtv_g_input(struct file *file, void *priv, unsigned int *i) +{ + *i = 0; + return 0; +} + +static int usbtv_s_input(struct file *file, void *priv, unsigned int i) +{ + if (i > 0) + return -EINVAL; + return 0; +} + +static int usbtv_s_std(struct file *file, void *priv, v4l2_std_id norm) +{ + if (norm & V4L2_STD_525_60) + return 0; + return -EINVAL; +} + +struct v4l2_ioctl_ops usbtv_ioctl_ops = { + .vidioc_querycap = usbtv_querycap, + .vidioc_enum_input = usbtv_enum_input, + .vidioc_enum_fmt_vid_cap = usbtv_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = usbtv_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = usbtv_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = usbtv_fmt_vid_cap, + .vidioc_g_std = usbtv_g_std, + .vidioc_s_std = usbtv_s_std, + .vidioc_g_input = usbtv_g_input, + .vidioc_s_input = usbtv_s_input, + + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_prepare_buf = vb2_ioctl_prepare_buf, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_create_bufs = vb2_ioctl_create_bufs, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, +}; + +struct v4l2_file_operations usbtv_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = video_ioctl2, + .mmap = vb2_fop_mmap, + .open = v4l2_fh_open, + .release = vb2_fop_release, + .read = vb2_fop_read, + .poll = vb2_fop_poll, +}; + +static int usbtv_queue_setup(struct vb2_queue *vq, + const struct v4l2_format *v4l_fmt, unsigned int *nbuffers, + unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) +{ + if (*nbuffers < 2) + *nbuffers = 2; + *nplanes = 1; + sizes[0] = USBTV_CHUNK * USBTV_CHUNKS * sizeof(u32); + + return 0; +} + +static void usbtv_buf_queue(struct vb2_buffer *vb) +{ + struct usbtv *usbtv = vb2_get_drv_priv(vb->vb2_queue); + struct usbtv_buf *buf = container_of(vb, struct usbtv_buf, vb); + unsigned long flags; + + if (usbtv->udev == NULL) { + vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); + return; + } + + spin_lock_irqsave(&usbtv->buflock, flags); + list_add_tail(&buf->list, &usbtv->bufs); + spin_unlock_irqrestore(&usbtv->buflock, flags); +} + +static int usbtv_start_streaming(struct vb2_queue *vq, unsigned int count) +{ + struct usbtv *usbtv = vb2_get_drv_priv(vq); + + if (usbtv->udev == NULL) + return -ENODEV; + + return usbtv_start(usbtv); +} + +static int usbtv_stop_streaming(struct vb2_queue *vq) +{ + struct usbtv *usbtv = vb2_get_drv_priv(vq); + + if (usbtv->udev == NULL) + return -ENODEV; + + usbtv_stop(usbtv); + return 0; +} + +struct vb2_ops usbtv_vb2_ops = { + .queue_setup = usbtv_queue_setup, + .buf_queue = usbtv_buf_queue, + .start_streaming = usbtv_start_streaming, + .stop_streaming = usbtv_stop_streaming, +}; + +static void usbtv_release(struct v4l2_device *v4l2_dev) +{ + struct usbtv *usbtv = container_of(v4l2_dev, struct usbtv, v4l2_dev); + + v4l2_device_unregister(&usbtv->v4l2_dev); + vb2_queue_release(&usbtv->vb2q); + kfree(usbtv); +} + +static int usbtv_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + int ret; + int size; + struct device *dev = &intf->dev; + struct usbtv *usbtv; + + /* Checks that the device is what we think it is. */ + if (intf->num_altsetting != 2) + return -ENODEV; + if (intf->altsetting[1].desc.bNumEndpoints != 4) + return -ENODEV; + + /* Packet size is split into 11 bits of base size and count of + * extra multiplies of it.*/ + size = usb_endpoint_maxp(&intf->altsetting[1].endpoint[0].desc); + size = (size & 0x07ff) * (((size & 0x1800) >> 11) + 1); + + /* Device structure */ + usbtv = kzalloc(sizeof(struct usbtv), GFP_KERNEL); + if (usbtv == NULL) + return -ENOMEM; + usbtv->dev = dev; + usbtv->udev = usb_get_dev(interface_to_usbdev(intf)); + usbtv->iso_size = size; + spin_lock_init(&usbtv->buflock); + mutex_init(&usbtv->v4l2_lock); + mutex_init(&usbtv->vb2q_lock); + INIT_LIST_HEAD(&usbtv->bufs); + + /* videobuf2 structure */ + usbtv->vb2q.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + usbtv->vb2q.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ; + usbtv->vb2q.drv_priv = usbtv; + usbtv->vb2q.buf_struct_size = sizeof(struct usbtv_buf); + usbtv->vb2q.ops = &usbtv_vb2_ops; + usbtv->vb2q.mem_ops = &vb2_vmalloc_memops; + usbtv->vb2q.timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + usbtv->vb2q.lock = &usbtv->vb2q_lock; + ret = vb2_queue_init(&usbtv->vb2q); + if (ret < 0) { + dev_warn(dev, "Could not initialize videobuf2 queue\n"); + goto usbtv_fail; + } + + /* v4l2 structure */ + usbtv->v4l2_dev.release = usbtv_release; + ret = v4l2_device_register(dev, &usbtv->v4l2_dev); + if (ret < 0) { + dev_warn(dev, "Could not register v4l2 device\n"); + goto v4l2_fail; + } + + usb_set_intfdata(intf, usbtv); + + /* Video structure */ + strlcpy(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; + usbtv->vdev.ioctl_ops = &usbtv_ioctl_ops; + usbtv->vdev.tvnorms = V4L2_STD_525_60; + usbtv->vdev.queue = &usbtv->vb2q; + usbtv->vdev.lock = &usbtv->v4l2_lock; + set_bit(V4L2_FL_USE_FH_PRIO, &usbtv->vdev.flags); + video_set_drvdata(&usbtv->vdev, usbtv); + ret = video_register_device(&usbtv->vdev, VFL_TYPE_GRABBER, -1); + if (ret < 0) { + dev_warn(dev, "Could not register video device\n"); + goto vdev_fail; + } + + dev_info(dev, "Fushicai USBTV007 Video Grabber\n"); + return 0; + +vdev_fail: + v4l2_device_unregister(&usbtv->v4l2_dev); +v4l2_fail: + vb2_queue_release(&usbtv->vb2q); +usbtv_fail: + kfree(usbtv); + + return ret; +} + +static void usbtv_disconnect(struct usb_interface *intf) +{ + struct usbtv *usbtv = usb_get_intfdata(intf); + + mutex_lock(&usbtv->vb2q_lock); + mutex_lock(&usbtv->v4l2_lock); + + usbtv_stop(usbtv); + usb_set_intfdata(intf, NULL); + video_unregister_device(&usbtv->vdev); + v4l2_device_disconnect(&usbtv->v4l2_dev); + usb_put_dev(usbtv->udev); + usbtv->udev = NULL; + + mutex_unlock(&usbtv->v4l2_lock); + mutex_unlock(&usbtv->vb2q_lock); + + v4l2_device_put(&usbtv->v4l2_dev); +} + +MODULE_AUTHOR("Lubomir Rintel"); +MODULE_DESCRIPTION("Fushicai USBTV007 Video Grabber Driver"); +MODULE_LICENSE("Dual BSD/GPL"); + +struct usb_driver usbtv_usb_driver = { + .name = "usbtv", + .id_table = usbtv_id_table, + .probe = usbtv_probe, + .disconnect = usbtv_disconnect, +}; + +module_usb_driver(usbtv_usb_driver); diff --git a/drivers/media/usb/usbvision/usbvision-video.c b/drivers/media/usb/usbvision/usbvision-video.c index d34c2afe2c24..5c9e3123ad2e 100644 --- a/drivers/media/usb/usbvision/usbvision-video.c +++ b/drivers/media/usb/usbvision/usbvision-video.c @@ -467,8 +467,6 @@ static int vidioc_g_register(struct file *file, void *priv, struct usb_usbvision *usbvision = video_drvdata(file); int err_code; - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; /* NT100x has a 8-bit register space */ err_code = usbvision_read_reg(usbvision, reg->reg&0xff); if (err_code < 0) { @@ -488,8 +486,6 @@ static int vidioc_s_register(struct file *file, void *priv, struct usb_usbvision *usbvision = video_drvdata(file); int err_code; - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; /* NT100x has a 8-bit register space */ err_code = usbvision_write_reg(usbvision, reg->reg & 0xff, reg->val); if (err_code < 0) { @@ -608,6 +604,14 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id) return 0; } +static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) +{ + struct usb_usbvision *usbvision = video_drvdata(file); + + *id = usbvision->tvnorm_id; + return 0; +} + static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *vt) { @@ -1248,6 +1252,7 @@ static const struct v4l2_ioctl_ops usbvision_ioctl_ops = { .vidioc_qbuf = vidioc_qbuf, .vidioc_dqbuf = vidioc_dqbuf, .vidioc_s_std = vidioc_s_std, + .vidioc_g_std = vidioc_g_std, .vidioc_enum_input = vidioc_enum_input, .vidioc_g_input = vidioc_g_input, .vidioc_s_input = vidioc_s_input, @@ -1274,7 +1279,6 @@ static struct video_device usbvision_video_template = { .name = "usbvision-video", .release = video_device_release, .tvnorms = USBVISION_NORMS, - .current_norm = V4L2_STD_PAL }; @@ -1307,9 +1311,6 @@ static struct video_device usbvision_radio_template = { .name = "usbvision-radio", .release = video_device_release, .ioctl_ops = &usbvision_radio_ioctl_ops, - - .tvnorms = USBVISION_NORMS, - .current_norm = V4L2_STD_PAL }; @@ -1459,6 +1460,7 @@ static void usbvision_release(struct usb_usbvision *usbvision) usbvision_remove_sysfs(usbvision->vdev); usbvision_unregister_video(usbvision); + kfree(usbvision->alt_max_pkt_size); usb_free_urb(usbvision->ctrl_urb); @@ -1574,6 +1576,7 @@ static int usbvision_probe(struct usb_interface *intf, usbvision->alt_max_pkt_size = kmalloc(32 * usbvision->num_alt, GFP_KERNEL); if (usbvision->alt_max_pkt_size == NULL) { dev_err(&intf->dev, "usbvision: out of memory!\n"); + usbvision_release(usbvision); return -ENOMEM; } diff --git a/drivers/media/usb/uvc/Kconfig b/drivers/media/usb/uvc/Kconfig index 541c9f1e4c6a..6ed85efabcaa 100644 --- a/drivers/media/usb/uvc/Kconfig +++ b/drivers/media/usb/uvc/Kconfig @@ -1,5 +1,6 @@ config USB_VIDEO_CLASS tristate "USB Video Class (UVC)" + depends on VIDEO_V4L2 select VIDEOBUF2_VMALLOC ---help--- Support for the USB Video Class (UVC). Currently only video diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 5dbefa68b1d2..81695d48c13e 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -1836,8 +1836,8 @@ static int uvc_probe(struct usb_interface *intf, INIT_LIST_HEAD(&dev->chains); INIT_LIST_HEAD(&dev->streams); atomic_set(&dev->nstreams, 0); - atomic_set(&dev->users, 0); atomic_set(&dev->nmappings, 0); + mutex_init(&dev->lock); dev->udev = usb_get_dev(udev); dev->intf = usb_get_intf(intf); @@ -1950,8 +1950,13 @@ static int uvc_suspend(struct usb_interface *intf, pm_message_t message) /* Controls are cached on the fly so they don't need to be saved. */ if (intf->cur_altsetting->desc.bInterfaceSubClass == - UVC_SC_VIDEOCONTROL) - return uvc_status_suspend(dev); + UVC_SC_VIDEOCONTROL) { + mutex_lock(&dev->lock); + if (dev->users) + uvc_status_stop(dev); + mutex_unlock(&dev->lock); + return 0; + } list_for_each_entry(stream, &dev->streams, list) { if (stream->intf == intf) @@ -1973,14 +1978,20 @@ static int __uvc_resume(struct usb_interface *intf, int reset) if (intf->cur_altsetting->desc.bInterfaceSubClass == UVC_SC_VIDEOCONTROL) { - if (reset) { - int ret = uvc_ctrl_resume_device(dev); + int ret = 0; + if (reset) { + ret = uvc_ctrl_resume_device(dev); if (ret < 0) return ret; } - return uvc_status_resume(dev); + mutex_lock(&dev->lock); + if (dev->users) + ret = uvc_status_start(dev, GFP_NOIO); + mutex_unlock(&dev->lock); + + return ret; } list_for_each_entry(stream, &dev->streams, list) { @@ -2163,6 +2174,24 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_PROBE_DEF }, + /* Dell Alienware X51 */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x05a9, + .idProduct = 0x2643, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_PROBE_DEF }, + /* Dell Studio Hybrid 140g (OmniVision webcam) */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x05a9, + .idProduct = 0x264a, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_PROBE_DEF }, /* Apple Built-In iSight */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, diff --git a/drivers/media/usb/uvc/uvc_status.c b/drivers/media/usb/uvc/uvc_status.c index b7492775e6ae..f552ab997956 100644 --- a/drivers/media/usb/uvc/uvc_status.c +++ b/drivers/media/usb/uvc/uvc_status.c @@ -206,32 +206,15 @@ void uvc_status_cleanup(struct uvc_device *dev) uvc_input_cleanup(dev); } -int uvc_status_start(struct uvc_device *dev) +int uvc_status_start(struct uvc_device *dev, gfp_t flags) { if (dev->int_urb == NULL) return 0; - return usb_submit_urb(dev->int_urb, GFP_KERNEL); + return usb_submit_urb(dev->int_urb, flags); } void uvc_status_stop(struct uvc_device *dev) { usb_kill_urb(dev->int_urb); } - -int uvc_status_suspend(struct uvc_device *dev) -{ - if (atomic_read(&dev->users)) - usb_kill_urb(dev->int_urb); - - return 0; -} - -int uvc_status_resume(struct uvc_device *dev) -{ - if (dev->int_urb == NULL || atomic_read(&dev->users) == 0) - return 0; - - return usb_submit_urb(dev->int_urb, GFP_NOIO); -} - diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index b2dc32623a71..3afff92804d3 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -498,16 +498,20 @@ static int uvc_v4l2_open(struct file *file) return -ENOMEM; } - if (atomic_inc_return(&stream->dev->users) == 1) { - ret = uvc_status_start(stream->dev); + mutex_lock(&stream->dev->lock); + if (stream->dev->users == 0) { + ret = uvc_status_start(stream->dev, GFP_KERNEL); if (ret < 0) { - atomic_dec(&stream->dev->users); + mutex_unlock(&stream->dev->lock); usb_autopm_put_interface(stream->dev->intf); kfree(handle); return ret; } } + stream->dev->users++; + mutex_unlock(&stream->dev->lock); + v4l2_fh_init(&handle->vfh, stream->vdev); v4l2_fh_add(&handle->vfh); handle->chain = stream->chain; @@ -538,8 +542,10 @@ static int uvc_v4l2_release(struct file *file) kfree(handle); file->private_data = NULL; - if (atomic_dec_return(&stream->dev->users) == 0) + mutex_lock(&stream->dev->lock); + if (--stream->dev->users == 0) uvc_status_stop(stream->dev); + mutex_unlock(&stream->dev->lock); usb_autopm_put_interface(stream->dev->intf); return 0; diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index af505fdd9b3f..9e35982d099a 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -514,7 +514,8 @@ struct uvc_device { char name[32]; enum uvc_device_state state; - atomic_t users; + struct mutex lock; /* Protects users */ + unsigned int users; atomic_t nmappings; /* Video control interface */ @@ -660,10 +661,8 @@ void uvc_video_clock_update(struct uvc_streaming *stream, /* Status */ extern int uvc_status_init(struct uvc_device *dev); extern void uvc_status_cleanup(struct uvc_device *dev); -extern int uvc_status_start(struct uvc_device *dev); +extern int uvc_status_start(struct uvc_device *dev, gfp_t flags); extern void uvc_status_stop(struct uvc_device *dev); -extern int uvc_status_suspend(struct uvc_device *dev); -extern int uvc_status_resume(struct uvc_device *dev); /* Controls */ extern const struct v4l2_subscribed_event_ops uvc_ctrl_sub_ev_ops; diff --git a/drivers/media/v4l2-core/Makefile b/drivers/media/v4l2-core/Makefile index aa50c46314b7..4c33b8d6520c 100644 --- a/drivers/media/v4l2-core/Makefile +++ b/drivers/media/v4l2-core/Makefile @@ -5,7 +5,8 @@ tuner-objs := tuner-core.o videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o \ - v4l2-event.o v4l2-ctrls.o v4l2-subdev.o + v4l2-event.o v4l2-ctrls.o v4l2-subdev.o v4l2-clk.o \ + v4l2-async.o ifeq ($(CONFIG_COMPAT),y) videodev-objs += v4l2-compat-ioctl32.o endif diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c new file mode 100644 index 000000000000..aae241730caa --- /dev/null +++ b/drivers/media/v4l2-core/v4l2-async.c @@ -0,0 +1,284 @@ +/* + * V4L2 asynchronous subdevice registration API + * + * Copyright (C) 2012-2013, Guennadi Liakhovetski <g.liakhovetski@gmx.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 as + * published by the Free Software Foundation. + */ + +#include <linux/device.h> +#include <linux/err.h> +#include <linux/i2c.h> +#include <linux/list.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/types.h> + +#include <media/v4l2-async.h> +#include <media/v4l2-device.h> +#include <media/v4l2-subdev.h> + +static bool match_i2c(struct device *dev, struct v4l2_async_subdev *asd) +{ +#if IS_ENABLED(CONFIG_I2C) + struct i2c_client *client = i2c_verify_client(dev); + return client && + asd->bus_type == V4L2_ASYNC_BUS_I2C && + asd->match.i2c.adapter_id == client->adapter->nr && + asd->match.i2c.address == client->addr; +#else + return false; +#endif +} + +static bool match_platform(struct device *dev, struct v4l2_async_subdev *asd) +{ + return asd->bus_type == V4L2_ASYNC_BUS_PLATFORM && + !strcmp(asd->match.platform.name, dev_name(dev)); +} + +static LIST_HEAD(subdev_list); +static LIST_HEAD(notifier_list); +static DEFINE_MUTEX(list_lock); + +static struct v4l2_async_subdev *v4l2_async_belongs(struct v4l2_async_notifier *notifier, + struct v4l2_async_subdev_list *asdl) +{ + struct v4l2_subdev *sd = v4l2_async_to_subdev(asdl); + struct v4l2_async_subdev *asd; + bool (*match)(struct device *, + struct v4l2_async_subdev *); + + list_for_each_entry(asd, ¬ifier->waiting, list) { + /* bus_type has been verified valid before */ + switch (asd->bus_type) { + case V4L2_ASYNC_BUS_CUSTOM: + match = asd->match.custom.match; + if (!match) + /* Match always */ + return asd; + break; + case V4L2_ASYNC_BUS_PLATFORM: + match = match_platform; + break; + case V4L2_ASYNC_BUS_I2C: + match = match_i2c; + break; + default: + /* Cannot happen, unless someone breaks us */ + WARN_ON(true); + return NULL; + } + + /* match cannot be NULL here */ + if (match(sd->dev, asd)) + return asd; + } + + return NULL; +} + +static int v4l2_async_test_notify(struct v4l2_async_notifier *notifier, + struct v4l2_async_subdev_list *asdl, + struct v4l2_async_subdev *asd) +{ + struct v4l2_subdev *sd = v4l2_async_to_subdev(asdl); + int ret; + + /* Remove from the waiting list */ + list_del(&asd->list); + asdl->asd = asd; + asdl->notifier = notifier; + + if (notifier->bound) { + ret = notifier->bound(notifier, sd, asd); + if (ret < 0) + return ret; + } + /* Move from the global subdevice list to notifier's done */ + list_move(&asdl->list, ¬ifier->done); + + ret = v4l2_device_register_subdev(notifier->v4l2_dev, sd); + if (ret < 0) { + if (notifier->unbind) + notifier->unbind(notifier, sd, asd); + return ret; + } + + if (list_empty(¬ifier->waiting) && notifier->complete) + return notifier->complete(notifier); + + return 0; +} + +static void v4l2_async_cleanup(struct v4l2_async_subdev_list *asdl) +{ + struct v4l2_subdev *sd = v4l2_async_to_subdev(asdl); + + v4l2_device_unregister_subdev(sd); + /* Subdevice driver will reprobe and put asdl back onto the list */ + list_del_init(&asdl->list); + asdl->asd = NULL; + sd->dev = NULL; +} + +int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev, + struct v4l2_async_notifier *notifier) +{ + struct v4l2_async_subdev_list *asdl, *tmp; + struct v4l2_async_subdev *asd; + int i; + + if (!notifier->num_subdevs || notifier->num_subdevs > V4L2_MAX_SUBDEVS) + return -EINVAL; + + notifier->v4l2_dev = v4l2_dev; + INIT_LIST_HEAD(¬ifier->waiting); + INIT_LIST_HEAD(¬ifier->done); + + for (i = 0; i < notifier->num_subdevs; i++) { + asd = notifier->subdev[i]; + + switch (asd->bus_type) { + case V4L2_ASYNC_BUS_CUSTOM: + case V4L2_ASYNC_BUS_PLATFORM: + case V4L2_ASYNC_BUS_I2C: + break; + default: + dev_err(notifier->v4l2_dev ? notifier->v4l2_dev->dev : NULL, + "Invalid bus-type %u on %p\n", + asd->bus_type, asd); + return -EINVAL; + } + list_add_tail(&asd->list, ¬ifier->waiting); + } + + mutex_lock(&list_lock); + + /* Keep also completed notifiers on the list */ + list_add(¬ifier->list, ¬ifier_list); + + list_for_each_entry_safe(asdl, tmp, &subdev_list, list) { + int ret; + + asd = v4l2_async_belongs(notifier, asdl); + if (!asd) + continue; + + ret = v4l2_async_test_notify(notifier, asdl, asd); + if (ret < 0) { + mutex_unlock(&list_lock); + return ret; + } + } + + mutex_unlock(&list_lock); + + return 0; +} +EXPORT_SYMBOL(v4l2_async_notifier_register); + +void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier) +{ + struct v4l2_async_subdev_list *asdl, *tmp; + unsigned int notif_n_subdev = notifier->num_subdevs; + unsigned int n_subdev = min(notif_n_subdev, V4L2_MAX_SUBDEVS); + struct device *dev[n_subdev]; + int i = 0; + + mutex_lock(&list_lock); + + list_del(¬ifier->list); + + list_for_each_entry_safe(asdl, tmp, ¬ifier->done, list) { + struct v4l2_subdev *sd = v4l2_async_to_subdev(asdl); + + dev[i] = get_device(sd->dev); + + v4l2_async_cleanup(asdl); + + /* If we handled USB devices, we'd have to lock the parent too */ + device_release_driver(dev[i++]); + + if (notifier->unbind) + notifier->unbind(notifier, sd, sd->asdl.asd); + } + + mutex_unlock(&list_lock); + + while (i--) { + struct device *d = dev[i]; + + if (d && device_attach(d) < 0) { + const char *name = "(none)"; + int lock = device_trylock(d); + + if (lock && d->driver) + name = d->driver->name; + dev_err(d, "Failed to re-probe to %s\n", name); + if (lock) + device_unlock(d); + } + put_device(d); + } + /* + * Don't care about the waiting list, it is initialised and populated + * upon notifier registration. + */ +} +EXPORT_SYMBOL(v4l2_async_notifier_unregister); + +int v4l2_async_register_subdev(struct v4l2_subdev *sd) +{ + struct v4l2_async_subdev_list *asdl = &sd->asdl; + struct v4l2_async_notifier *notifier; + + mutex_lock(&list_lock); + + INIT_LIST_HEAD(&asdl->list); + + list_for_each_entry(notifier, ¬ifier_list, list) { + struct v4l2_async_subdev *asd = v4l2_async_belongs(notifier, asdl); + if (asd) { + int ret = v4l2_async_test_notify(notifier, asdl, asd); + mutex_unlock(&list_lock); + return ret; + } + } + + /* None matched, wait for hot-plugging */ + list_add(&asdl->list, &subdev_list); + + mutex_unlock(&list_lock); + + return 0; +} +EXPORT_SYMBOL(v4l2_async_register_subdev); + +void v4l2_async_unregister_subdev(struct v4l2_subdev *sd) +{ + struct v4l2_async_subdev_list *asdl = &sd->asdl; + struct v4l2_async_notifier *notifier = asdl->notifier; + + if (!asdl->asd) { + if (!list_empty(&asdl->list)) + v4l2_async_cleanup(asdl); + return; + } + + mutex_lock(&list_lock); + + list_add(&asdl->asd->list, ¬ifier->waiting); + + v4l2_async_cleanup(asdl); + + if (notifier->unbind) + notifier->unbind(notifier, sd, sd->asdl.asd); + + mutex_unlock(&list_lock); +} +EXPORT_SYMBOL(v4l2_async_unregister_subdev); diff --git a/drivers/media/v4l2-core/v4l2-clk.c b/drivers/media/v4l2-core/v4l2-clk.c new file mode 100644 index 000000000000..b67de8642b5a --- /dev/null +++ b/drivers/media/v4l2-core/v4l2-clk.c @@ -0,0 +1,242 @@ +/* + * V4L2 clock service + * + * Copyright (C) 2012-2013, Guennadi Liakhovetski <g.liakhovetski@gmx.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 as + * published by the Free Software Foundation. + */ + +#include <linux/atomic.h> +#include <linux/device.h> +#include <linux/errno.h> +#include <linux/list.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/slab.h> +#include <linux/string.h> + +#include <media/v4l2-clk.h> +#include <media/v4l2-subdev.h> + +static DEFINE_MUTEX(clk_lock); +static LIST_HEAD(clk_list); + +static struct v4l2_clk *v4l2_clk_find(const char *dev_id, const char *id) +{ + struct v4l2_clk *clk; + + list_for_each_entry(clk, &clk_list, list) { + if (strcmp(dev_id, clk->dev_id)) + continue; + + if (!id || !clk->id || !strcmp(clk->id, id)) + return clk; + } + + return ERR_PTR(-ENODEV); +} + +struct v4l2_clk *v4l2_clk_get(struct device *dev, const char *id) +{ + struct v4l2_clk *clk; + + mutex_lock(&clk_lock); + clk = v4l2_clk_find(dev_name(dev), id); + + if (!IS_ERR(clk)) + atomic_inc(&clk->use_count); + mutex_unlock(&clk_lock); + + return clk; +} +EXPORT_SYMBOL(v4l2_clk_get); + +void v4l2_clk_put(struct v4l2_clk *clk) +{ + struct v4l2_clk *tmp; + + if (IS_ERR(clk)) + return; + + mutex_lock(&clk_lock); + + list_for_each_entry(tmp, &clk_list, list) + if (tmp == clk) + atomic_dec(&clk->use_count); + + mutex_unlock(&clk_lock); +} +EXPORT_SYMBOL(v4l2_clk_put); + +static int v4l2_clk_lock_driver(struct v4l2_clk *clk) +{ + struct v4l2_clk *tmp; + int ret = -ENODEV; + + mutex_lock(&clk_lock); + + list_for_each_entry(tmp, &clk_list, list) + if (tmp == clk) { + ret = !try_module_get(clk->ops->owner); + if (ret) + ret = -EFAULT; + break; + } + + mutex_unlock(&clk_lock); + + return ret; +} + +static void v4l2_clk_unlock_driver(struct v4l2_clk *clk) +{ + module_put(clk->ops->owner); +} + +int v4l2_clk_enable(struct v4l2_clk *clk) +{ + int ret = v4l2_clk_lock_driver(clk); + + if (ret < 0) + return ret; + + mutex_lock(&clk->lock); + + if (++clk->enable == 1 && clk->ops->enable) { + ret = clk->ops->enable(clk); + if (ret < 0) + clk->enable--; + } + + mutex_unlock(&clk->lock); + + return ret; +} +EXPORT_SYMBOL(v4l2_clk_enable); + +/* + * You might Oops if you try to disabled a disabled clock, because then the + * driver isn't locked and could have been unloaded by now, so, don't do that + */ +void v4l2_clk_disable(struct v4l2_clk *clk) +{ + int enable; + + mutex_lock(&clk->lock); + + enable = --clk->enable; + if (WARN(enable < 0, "Unbalanced %s() on %s:%s!\n", __func__, + clk->dev_id, clk->id)) + clk->enable++; + else if (!enable && clk->ops->disable) + clk->ops->disable(clk); + + mutex_unlock(&clk->lock); + + v4l2_clk_unlock_driver(clk); +} +EXPORT_SYMBOL(v4l2_clk_disable); + +unsigned long v4l2_clk_get_rate(struct v4l2_clk *clk) +{ + int ret = v4l2_clk_lock_driver(clk); + + if (ret < 0) + return ret; + + mutex_lock(&clk->lock); + if (!clk->ops->get_rate) + ret = -ENOSYS; + else + ret = clk->ops->get_rate(clk); + mutex_unlock(&clk->lock); + + v4l2_clk_unlock_driver(clk); + + return ret; +} +EXPORT_SYMBOL(v4l2_clk_get_rate); + +int v4l2_clk_set_rate(struct v4l2_clk *clk, unsigned long rate) +{ + int ret = v4l2_clk_lock_driver(clk); + + if (ret < 0) + return ret; + + mutex_lock(&clk->lock); + if (!clk->ops->set_rate) + ret = -ENOSYS; + else + ret = clk->ops->set_rate(clk, rate); + mutex_unlock(&clk->lock); + + v4l2_clk_unlock_driver(clk); + + return ret; +} +EXPORT_SYMBOL(v4l2_clk_set_rate); + +struct v4l2_clk *v4l2_clk_register(const struct v4l2_clk_ops *ops, + const char *dev_id, + const char *id, void *priv) +{ + struct v4l2_clk *clk; + int ret; + + if (!ops || !dev_id) + return ERR_PTR(-EINVAL); + + clk = kzalloc(sizeof(struct v4l2_clk), GFP_KERNEL); + if (!clk) + return ERR_PTR(-ENOMEM); + + clk->id = kstrdup(id, GFP_KERNEL); + clk->dev_id = kstrdup(dev_id, GFP_KERNEL); + if ((id && !clk->id) || !clk->dev_id) { + ret = -ENOMEM; + goto ealloc; + } + clk->ops = ops; + clk->priv = priv; + atomic_set(&clk->use_count, 0); + mutex_init(&clk->lock); + + mutex_lock(&clk_lock); + if (!IS_ERR(v4l2_clk_find(dev_id, id))) { + mutex_unlock(&clk_lock); + ret = -EEXIST; + goto eexist; + } + list_add_tail(&clk->list, &clk_list); + mutex_unlock(&clk_lock); + + return clk; + +eexist: +ealloc: + kfree(clk->id); + kfree(clk->dev_id); + kfree(clk); + return ERR_PTR(ret); +} +EXPORT_SYMBOL(v4l2_clk_register); + +void v4l2_clk_unregister(struct v4l2_clk *clk) +{ + if (WARN(atomic_read(&clk->use_count), + "%s(): Refusing to unregister ref-counted %s:%s clock!\n", + __func__, clk->dev_id, clk->id)) + return; + + mutex_lock(&clk_lock); + list_del(&clk->list); + mutex_unlock(&clk_lock); + + kfree(clk->id); + kfree(clk->dev_id); + kfree(clk); +} +EXPORT_SYMBOL(v4l2_clk_unregister); diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c index 3fed63f4e026..a95e5e23403f 100644 --- a/drivers/media/v4l2-core/v4l2-common.c +++ b/drivers/media/v4l2-core/v4l2-common.c @@ -61,7 +61,6 @@ #include <media/v4l2-common.h> #include <media/v4l2-device.h> #include <media/v4l2-ctrls.h> -#include <media/v4l2-chip-ident.h> #include <linux/videodev2.h> @@ -227,62 +226,9 @@ u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id) } EXPORT_SYMBOL(v4l2_ctrl_next); -int v4l2_chip_match_host(const struct v4l2_dbg_match *match) -{ - switch (match->type) { - case V4L2_CHIP_MATCH_BRIDGE: - return match->addr == 0; - default: - return 0; - } -} -EXPORT_SYMBOL(v4l2_chip_match_host); - -#if IS_ENABLED(CONFIG_I2C) -int v4l2_chip_match_i2c_client(struct i2c_client *c, const struct v4l2_dbg_match *match) -{ - int len; - - if (c == NULL || match == NULL) - return 0; - - switch (match->type) { - case V4L2_CHIP_MATCH_I2C_DRIVER: - if (c->driver == NULL || c->driver->driver.name == NULL) - return 0; - len = strlen(c->driver->driver.name); - return len && !strncmp(c->driver->driver.name, match->name, len); - case V4L2_CHIP_MATCH_I2C_ADDR: - return c->addr == match->addr; - case V4L2_CHIP_MATCH_SUBDEV: - return 1; - default: - return 0; - } -} -EXPORT_SYMBOL(v4l2_chip_match_i2c_client); - -int v4l2_chip_ident_i2c_client(struct i2c_client *c, struct v4l2_dbg_chip_ident *chip, - u32 ident, u32 revision) -{ - if (!v4l2_chip_match_i2c_client(c, &chip->match)) - return 0; - if (chip->ident == V4L2_IDENT_NONE) { - chip->ident = ident; - chip->revision = revision; - } - else { - chip->ident = V4L2_IDENT_AMBIGUOUS; - chip->revision = 0; - } - return 0; -} -EXPORT_SYMBOL(v4l2_chip_ident_i2c_client); - -/* ----------------------------------------------------------------- */ - /* I2C Helper functions */ +#if IS_ENABLED(CONFIG_I2C) void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client, const struct v4l2_subdev_ops *ops) @@ -291,6 +237,7 @@ void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client, sd->flags |= V4L2_SUBDEV_FL_IS_I2C; /* the owner is the same as the i2c_client's driver owner */ sd->owner = client->driver->driver.owner; + sd->dev = &client->dev; /* i2c_client and v4l2_subdev point to one another */ v4l2_set_subdevdata(sd, client); i2c_set_clientdata(client, sd); @@ -301,8 +248,6 @@ void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client, } EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_init); - - /* Load an i2c sub-device. */ struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev, struct i2c_adapter *adapter, struct i2c_board_info *info, @@ -426,6 +371,7 @@ void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi, sd->flags |= V4L2_SUBDEV_FL_IS_SPI; /* the owner is the same as the spi_device's driver owner */ sd->owner = spi->dev.driver->owner; + sd->dev = &spi->dev; /* spi_device and v4l2_subdev point to one another */ v4l2_set_subdevdata(sd, spi); spi_set_drvdata(spi, sd); diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index f1295519f285..8f7a6a454a4c 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -1074,7 +1074,6 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) case VIDIOC_TRY_DECODER_CMD: case VIDIOC_DBG_S_REGISTER: case VIDIOC_DBG_G_REGISTER: - case VIDIOC_DBG_G_CHIP_IDENT: case VIDIOC_S_HW_FREQ_SEEK: case VIDIOC_S_DV_TIMINGS: case VIDIOC_G_DV_TIMINGS: diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c index 5923c5dfacd5..c8859d6ff6ad 100644 --- a/drivers/media/v4l2-core/v4l2-dev.c +++ b/drivers/media/v4l2-core/v4l2-dev.c @@ -495,8 +495,8 @@ static const struct file_operations v4l2_fops = { }; /** - * get_index - assign stream index number based on parent device - * @vdev: video_device to assign index number to, vdev->parent should be assigned + * get_index - assign stream index number based on v4l2_dev + * @vdev: video_device to assign index number to, vdev->v4l2_dev should be assigned * * Note that when this is called the new device has not yet been registered * in the video_device array, but it was able to obtain a minor number. @@ -514,15 +514,11 @@ static int get_index(struct video_device *vdev) static DECLARE_BITMAP(used, VIDEO_NUM_DEVICES); int i; - /* Some drivers do not set the parent. In that case always return 0. */ - if (vdev->parent == NULL) - return 0; - bitmap_zero(used, VIDEO_NUM_DEVICES); for (i = 0; i < VIDEO_NUM_DEVICES; i++) { if (video_device[i] != NULL && - video_device[i]->parent == vdev->parent) { + video_device[i]->v4l2_dev == vdev->v4l2_dev) { set_bit(video_device[i]->index, used); } } @@ -596,7 +592,6 @@ static void determine_valid_ioctls(struct video_device *vdev) set_bit(_IOC_NR(VIDIOC_DBG_G_REGISTER), valid_ioctls); set_bit(_IOC_NR(VIDIOC_DBG_S_REGISTER), valid_ioctls); #endif - SET_VALID_IOCTL(ops, VIDIOC_DBG_G_CHIP_IDENT, vidioc_g_chip_ident); /* yes, really vidioc_subscribe_event */ SET_VALID_IOCTL(ops, VIDIOC_DQEVENT, vidioc_subscribe_event); SET_VALID_IOCTL(ops, VIDIOC_SUBSCRIBE_EVENT, vidioc_subscribe_event); @@ -675,9 +670,8 @@ static void determine_valid_ioctls(struct video_device *vdev) SET_VALID_IOCTL(ops, VIDIOC_PREPARE_BUF, vidioc_prepare_buf); if (ops->vidioc_s_std) set_bit(_IOC_NR(VIDIOC_ENUMSTD), valid_ioctls); - if (ops->vidioc_g_std || vdev->current_norm) - set_bit(_IOC_NR(VIDIOC_G_STD), valid_ioctls); SET_VALID_IOCTL(ops, VIDIOC_S_STD, vidioc_s_std); + SET_VALID_IOCTL(ops, VIDIOC_G_STD, vidioc_g_std); if (is_rx) { SET_VALID_IOCTL(ops, VIDIOC_QUERYSTD, vidioc_querystd); SET_VALID_IOCTL(ops, VIDIOC_ENUMINPUT, vidioc_enum_input); @@ -705,7 +699,7 @@ static void determine_valid_ioctls(struct video_device *vdev) if (ops->vidioc_cropcap || ops->vidioc_g_selection) set_bit(_IOC_NR(VIDIOC_CROPCAP), valid_ioctls); if (ops->vidioc_g_parm || (vdev->vfl_type == VFL_TYPE_GRABBER && - (ops->vidioc_g_std || vdev->current_norm))) + ops->vidioc_g_std)) set_bit(_IOC_NR(VIDIOC_G_PARM), valid_ioctls); SET_VALID_IOCTL(ops, VIDIOC_S_PARM, vidioc_s_parm); SET_VALID_IOCTL(ops, VIDIOC_S_DV_TIMINGS, vidioc_s_dv_timings); @@ -777,6 +771,9 @@ int __video_register_device(struct video_device *vdev, int type, int nr, /* the release callback MUST be present */ if (WARN_ON(!vdev->release)) return -EINVAL; + /* the v4l2_dev pointer MUST be present */ + if (WARN_ON(!vdev->v4l2_dev)) + return -EINVAL; /* v4l2_fh support */ spin_lock_init(&vdev->fh_lock); @@ -804,16 +801,14 @@ int __video_register_device(struct video_device *vdev, int type, int nr, vdev->vfl_type = type; vdev->cdev = NULL; - if (vdev->v4l2_dev) { - if (vdev->v4l2_dev->dev) - vdev->parent = vdev->v4l2_dev->dev; - if (vdev->ctrl_handler == NULL) - vdev->ctrl_handler = vdev->v4l2_dev->ctrl_handler; - /* If the prio state pointer is NULL, then use the v4l2_device - prio state. */ - if (vdev->prio == NULL) - vdev->prio = &vdev->v4l2_dev->prio; - } + if (vdev->dev_parent == NULL) + vdev->dev_parent = vdev->v4l2_dev->dev; + if (vdev->ctrl_handler == NULL) + vdev->ctrl_handler = vdev->v4l2_dev->ctrl_handler; + /* If the prio state pointer is NULL, then use the v4l2_device + prio state. */ + if (vdev->prio == NULL) + vdev->prio = &vdev->v4l2_dev->prio; /* Part 2: find a free minor, device node number and device index. */ #ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES @@ -898,8 +893,7 @@ int __video_register_device(struct video_device *vdev, int type, int nr, /* Part 4: register the device with sysfs */ vdev->dev.class = &video_class; vdev->dev.devt = MKDEV(VIDEO_MAJOR, vdev->minor); - if (vdev->parent) - vdev->dev.parent = vdev->parent; + vdev->dev.parent = vdev->dev_parent; dev_set_name(&vdev->dev, "%s%d", name_base, vdev->num); ret = device_register(&vdev->dev); if (ret < 0) { diff --git a/drivers/media/v4l2-core/v4l2-device.c b/drivers/media/v4l2-core/v4l2-device.c index 8ed5da2170bf..02d1b6327117 100644 --- a/drivers/media/v4l2-core/v4l2-device.c +++ b/drivers/media/v4l2-core/v4l2-device.c @@ -44,7 +44,8 @@ int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev) v4l2_dev->dev = dev; if (dev == NULL) { /* If dev == NULL, then name must be filled in by the caller */ - WARN_ON(!v4l2_dev->name[0]); + if (WARN_ON(!v4l2_dev->name[0])) + return -EINVAL; return 0; } @@ -105,7 +106,9 @@ void v4l2_device_unregister(struct v4l2_device *v4l2_dev) { struct v4l2_subdev *sd, *next; - if (v4l2_dev == NULL) + /* Just return if v4l2_dev is NULL or if it was already + * unregistered before. */ + if (v4l2_dev == NULL || !v4l2_dev->name[0]) return; v4l2_device_disconnect(v4l2_dev); @@ -135,6 +138,8 @@ void v4l2_device_unregister(struct v4l2_device *v4l2_dev) } #endif } + /* Mark as unregistered, thus preventing duplicate unregistrations */ + v4l2_dev->name[0] = '\0'; } EXPORT_SYMBOL_GPL(v4l2_device_unregister); @@ -269,8 +274,10 @@ void v4l2_device_unregister_subdev(struct v4l2_subdev *sd) sd->v4l2_dev = NULL; #if defined(CONFIG_MEDIA_CONTROLLER) - if (v4l2_dev->mdev) + if (v4l2_dev->mdev) { + media_entity_remove_links(&sd->entity); media_device_unregister_entity(&sd->entity); + } #endif video_unregister_device(sd->devnode); module_put(sd->owner); diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 7658586fe5f4..68e6b5e912ff 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -26,7 +26,6 @@ #include <media/v4l2-fh.h> #include <media/v4l2-event.h> #include <media/v4l2-device.h> -#include <media/v4l2-chip-ident.h> #include <media/videobuf2-core.h> /* Zero out the end of the struct pointed to by p. Everything after, but @@ -619,20 +618,6 @@ static void v4l_print_decoder_cmd(const void *arg, bool write_only) pr_info("pts=%llu\n", p->stop.pts); } -static void v4l_print_dbg_chip_ident(const void *arg, bool write_only) -{ - const struct v4l2_dbg_chip_ident *p = arg; - - pr_cont("type=%u, ", p->match.type); - if (p->match.type == V4L2_CHIP_MATCH_I2C_DRIVER) - pr_cont("name=%.*s, ", - (int)sizeof(p->match.name), p->match.name); - else - pr_cont("addr=%u, ", p->match.addr); - pr_cont("chip_ident=%u, revision=0x%x\n", - p->ident, p->revision); -} - static void v4l_print_dbg_chip_info(const void *arg, bool write_only) { const struct v4l2_dbg_chip_info *p = arg; @@ -1359,40 +1344,18 @@ static int v4l_enumstd(const struct v4l2_ioctl_ops *ops, return 0; } -static int v4l_g_std(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) -{ - struct video_device *vfd = video_devdata(file); - v4l2_std_id *id = arg; - - /* Calls the specific handler */ - if (ops->vidioc_g_std) - return ops->vidioc_g_std(file, fh, arg); - if (vfd->current_norm) { - *id = vfd->current_norm; - return 0; - } - return -ENOTTY; -} - static int v4l_s_std(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { struct video_device *vfd = video_devdata(file); v4l2_std_id id = *(v4l2_std_id *)arg, norm; - int ret; norm = id & vfd->tvnorms; if (vfd->tvnorms && !norm) /* Check if std is supported */ return -EINVAL; /* Calls the specific handler */ - ret = ops->vidioc_s_std(file, fh, norm); - - /* Updates standard information */ - if (ret >= 0) - vfd->current_norm = norm; - return ret; + return ops->vidioc_s_std(file, fh, norm); } static int v4l_querystd(const struct v4l2_ioctl_ops *ops, @@ -1402,10 +1365,10 @@ static int v4l_querystd(const struct v4l2_ioctl_ops *ops, v4l2_std_id *p = arg; /* - * If nothing detected, it should return all supported - * standard. - * Drivers just need to mask the std argument, in order - * to remove the standards that don't apply from the mask. + * If no signal is detected, then the driver should return + * V4L2_STD_UNKNOWN. Otherwise it should return tvnorms with + * any standards that do not apply removed. + * * This means that tuners, audio and video decoders can join * their efforts to improve the standards detection. */ @@ -1495,7 +1458,6 @@ static int v4l_prepare_buf(const struct v4l2_ioctl_ops *ops, static int v4l_g_parm(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { - struct video_device *vfd = video_devdata(file); struct v4l2_streamparm *p = arg; v4l2_std_id std; int ret = check_fmt(file, p->type); @@ -1504,16 +1466,13 @@ static int v4l_g_parm(const struct v4l2_ioctl_ops *ops, return ret; if (ops->vidioc_g_parm) return ops->vidioc_g_parm(file, fh, p); - std = vfd->current_norm; if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) return -EINVAL; p->parm.capture.readbuffers = 2; - if (is_valid_ioctl(vfd, VIDIOC_G_STD) && ops->vidioc_g_std) - ret = ops->vidioc_g_std(file, fh, &std); + ret = ops->vidioc_g_std(file, fh, &std); if (ret == 0) - v4l2_video_std_frame_period(std, - &p->parm.capture.timeperframe); + v4l2_video_std_frame_period(std, &p->parm.capture.timeperframe); return ret; } @@ -1802,7 +1761,8 @@ static int v4l_dbg_g_register(const struct v4l2_ioctl_ops *ops, return v4l2_subdev_call(sd, core, g_register, p); return -EINVAL; } - if (ops->vidioc_g_register) + if (ops->vidioc_g_register && p->match.type == V4L2_CHIP_MATCH_BRIDGE && + (ops->vidioc_g_chip_info || p->match.addr == 0)) return ops->vidioc_g_register(file, fh, p); return -EINVAL; #else @@ -1829,7 +1789,8 @@ static int v4l_dbg_s_register(const struct v4l2_ioctl_ops *ops, return v4l2_subdev_call(sd, core, s_register, p); return -EINVAL; } - if (ops->vidioc_s_register) + if (ops->vidioc_s_register && p->match.type == V4L2_CHIP_MATCH_BRIDGE && + (ops->vidioc_g_chip_info || p->match.addr == 0)) return ops->vidioc_s_register(file, fh, p); return -EINVAL; #else @@ -1837,18 +1798,6 @@ static int v4l_dbg_s_register(const struct v4l2_ioctl_ops *ops, #endif } -static int v4l_dbg_g_chip_ident(const struct v4l2_ioctl_ops *ops, - struct file *file, void *fh, void *arg) -{ - struct v4l2_dbg_chip_ident *p = arg; - - p->ident = V4L2_IDENT_NONE; - p->revision = 0; - if (p->match.type == V4L2_CHIP_MATCH_SUBDEV) - return -EINVAL; - return ops->vidioc_g_chip_ident(file, fh, p); -} - static int v4l_dbg_g_chip_info(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { @@ -1864,12 +1813,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; - if (vfd->v4l2_dev) - strlcpy(p->name, vfd->v4l2_dev->name, sizeof(p->name)); - else if (vfd->parent) - strlcpy(p->name, vfd->parent->driver->name, sizeof(p->name)); - else - strlcpy(p->name, "bridge", sizeof(p->name)); + strlcpy(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) @@ -2048,7 +1992,7 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO_FNC(VIDIOC_STREAMOFF, v4l_streamoff, v4l_print_buftype, INFO_FL_PRIO | INFO_FL_QUEUE), IOCTL_INFO_FNC(VIDIOC_G_PARM, v4l_g_parm, v4l_print_streamparm, INFO_FL_CLEAR(v4l2_streamparm, type)), IOCTL_INFO_FNC(VIDIOC_S_PARM, v4l_s_parm, v4l_print_streamparm, INFO_FL_PRIO), - IOCTL_INFO_FNC(VIDIOC_G_STD, v4l_g_std, v4l_print_std, 0), + IOCTL_INFO_STD(VIDIOC_G_STD, vidioc_g_std, v4l_print_std, 0), IOCTL_INFO_FNC(VIDIOC_S_STD, v4l_s_std, v4l_print_std, INFO_FL_PRIO), IOCTL_INFO_FNC(VIDIOC_ENUMSTD, v4l_enumstd, v4l_print_standard, INFO_FL_CLEAR(v4l2_standard, index)), IOCTL_INFO_FNC(VIDIOC_ENUMINPUT, v4l_enuminput, v4l_print_enuminput, INFO_FL_CLEAR(v4l2_input, index)), @@ -2098,7 +2042,6 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO_STD(VIDIOC_TRY_DECODER_CMD, vidioc_try_decoder_cmd, v4l_print_decoder_cmd, 0), IOCTL_INFO_FNC(VIDIOC_DBG_S_REGISTER, v4l_dbg_s_register, v4l_print_dbg_register, 0), IOCTL_INFO_FNC(VIDIOC_DBG_G_REGISTER, v4l_dbg_g_register, v4l_print_dbg_register, 0), - IOCTL_INFO_FNC(VIDIOC_DBG_G_CHIP_IDENT, v4l_dbg_g_chip_ident, v4l_print_dbg_chip_ident, 0), IOCTL_INFO_FNC(VIDIOC_S_HW_FREQ_SEEK, v4l_s_hw_freq_seek, v4l_print_hw_freq_seek, INFO_FL_PRIO), IOCTL_INFO_STD(VIDIOC_S_DV_TIMINGS, vidioc_s_dv_timings, v4l_print_dv_timings, INFO_FL_PRIO), IOCTL_INFO_STD(VIDIOC_G_DV_TIMINGS, vidioc_g_dv_timings, v4l_print_dv_timings, 0), diff --git a/drivers/media/v4l2-core/videobuf-dma-contig.c b/drivers/media/v4l2-core/videobuf-dma-contig.c index 67f572c3fba2..65411adcd0ea 100644 --- a/drivers/media/v4l2-core/videobuf-dma-contig.c +++ b/drivers/media/v4l2-core/videobuf-dma-contig.c @@ -66,11 +66,14 @@ static void __videobuf_dc_free(struct device *dev, static void videobuf_vm_open(struct vm_area_struct *vma) { struct videobuf_mapping *map = vma->vm_private_data; + struct videobuf_queue *q = map->q; - dev_dbg(map->q->dev, "vm_open %p [count=%u,vma=%08lx-%08lx]\n", + dev_dbg(q->dev, "vm_open %p [count=%u,vma=%08lx-%08lx]\n", map, map->count, vma->vm_start, vma->vm_end); + videobuf_queue_lock(q); map->count++; + videobuf_queue_unlock(q); } static void videobuf_vm_close(struct vm_area_struct *vma) @@ -82,12 +85,11 @@ static void videobuf_vm_close(struct vm_area_struct *vma) dev_dbg(q->dev, "vm_close %p [count=%u,vma=%08lx-%08lx]\n", map, map->count, vma->vm_start, vma->vm_end); - map->count--; - if (0 == map->count) { + videobuf_queue_lock(q); + if (!--map->count) { struct videobuf_dma_contig_memory *mem; dev_dbg(q->dev, "munmap %p q=%p\n", map, q); - videobuf_queue_lock(q); /* We need first to cancel streams, before unmapping */ if (q->streaming) @@ -126,8 +128,8 @@ static void videobuf_vm_close(struct vm_area_struct *vma) kfree(map); - videobuf_queue_unlock(q); } + videobuf_queue_unlock(q); } static const struct vm_operations_struct videobuf_vm_ops = { @@ -303,14 +305,9 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, goto error; /* Try to remap memory */ - size = vma->vm_end - vma->vm_start; - size = (size < mem->size) ? size : mem->size; - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - retval = remap_pfn_range(vma, vma->vm_start, - mem->dma_handle >> PAGE_SHIFT, - size, vma->vm_page_prot); + retval = vm_iomap_memory(vma, vma->vm_start, size); if (retval) { dev_err(q->dev, "mmap: remap failed with error %d. ", retval); diff --git a/drivers/media/v4l2-core/videobuf-dma-sg.c b/drivers/media/v4l2-core/videobuf-dma-sg.c index 828e7c10bd70..9db674ccdc68 100644 --- a/drivers/media/v4l2-core/videobuf-dma-sg.c +++ b/drivers/media/v4l2-core/videobuf-dma-sg.c @@ -338,11 +338,14 @@ EXPORT_SYMBOL_GPL(videobuf_dma_free); static void videobuf_vm_open(struct vm_area_struct *vma) { struct videobuf_mapping *map = vma->vm_private_data; + struct videobuf_queue *q = map->q; dprintk(2, "vm_open %p [count=%d,vma=%08lx-%08lx]\n", map, map->count, vma->vm_start, vma->vm_end); + videobuf_queue_lock(q); map->count++; + videobuf_queue_unlock(q); } static void videobuf_vm_close(struct vm_area_struct *vma) @@ -355,10 +358,9 @@ static void videobuf_vm_close(struct vm_area_struct *vma) dprintk(2, "vm_close %p [count=%d,vma=%08lx-%08lx]\n", map, map->count, vma->vm_start, vma->vm_end); - map->count--; - if (0 == map->count) { + videobuf_queue_lock(q); + if (!--map->count) { dprintk(1, "munmap %p q=%p\n", map, q); - videobuf_queue_lock(q); for (i = 0; i < VIDEO_MAX_FRAME; i++) { if (NULL == q->bufs[i]) continue; @@ -374,9 +376,9 @@ static void videobuf_vm_close(struct vm_area_struct *vma) q->bufs[i]->baddr = 0; q->ops->buf_release(q, q->bufs[i]); } - videobuf_queue_unlock(q); kfree(map); } + videobuf_queue_unlock(q); return; } diff --git a/drivers/media/v4l2-core/videobuf-vmalloc.c b/drivers/media/v4l2-core/videobuf-vmalloc.c index 2ff7fcc77b11..1365c651c177 100644 --- a/drivers/media/v4l2-core/videobuf-vmalloc.c +++ b/drivers/media/v4l2-core/videobuf-vmalloc.c @@ -54,11 +54,14 @@ MODULE_LICENSE("GPL"); static void videobuf_vm_open(struct vm_area_struct *vma) { struct videobuf_mapping *map = vma->vm_private_data; + struct videobuf_queue *q = map->q; dprintk(2, "vm_open %p [count=%u,vma=%08lx-%08lx]\n", map, map->count, vma->vm_start, vma->vm_end); + videobuf_queue_lock(q); map->count++; + videobuf_queue_unlock(q); } static void videobuf_vm_close(struct vm_area_struct *vma) @@ -70,12 +73,11 @@ static void videobuf_vm_close(struct vm_area_struct *vma) dprintk(2, "vm_close %p [count=%u,vma=%08lx-%08lx]\n", map, map->count, vma->vm_start, vma->vm_end); - map->count--; - if (0 == map->count) { + videobuf_queue_lock(q); + if (!--map->count) { struct videobuf_vmalloc_memory *mem; dprintk(1, "munmap %p q=%p\n", map, q); - videobuf_queue_lock(q); /* We need first to cancel streams, before unmapping */ if (q->streaming) @@ -114,8 +116,8 @@ static void videobuf_vm_close(struct vm_area_struct *vma) kfree(map); - videobuf_queue_unlock(q); } + videobuf_queue_unlock(q); return; } diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index e3bdc3be91e1..9fc4bab2da97 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -2194,8 +2194,10 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read) */ for (i = 0; i < q->num_buffers; i++) { fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0); - if (fileio->bufs[i].vaddr == NULL) + if (fileio->bufs[i].vaddr == NULL) { + ret = -EINVAL; goto err_reqbufs; + } fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0); } diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipe.c b/drivers/staging/media/davinci_vpfe/dm365_ipipe.c index 05673ed45ce4..766a071b0a22 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_ipipe.c +++ b/drivers/staging/media/davinci_vpfe/dm365_ipipe.c @@ -1751,10 +1751,10 @@ static const struct media_entity_operations ipipe_media_ops = { */ void vpfe_ipipe_unregister_entities(struct vpfe_ipipe_device *vpfe_ipipe) { - /* cleanup entity */ - media_entity_cleanup(&vpfe_ipipe->subdev.entity); /* unregister subdev */ v4l2_device_unregister_subdev(&vpfe_ipipe->subdev); + /* cleanup entity */ + media_entity_cleanup(&vpfe_ipipe->subdev.entity); } /* diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c index b2f4ef84f3db..59540cd4bb98 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c +++ b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c @@ -947,10 +947,10 @@ void vpfe_ipipeif_unregister_entities(struct vpfe_ipipeif_device *ipipeif) /* unregister video device */ vpfe_video_unregister(&ipipeif->video_in); - /* cleanup entity */ - media_entity_cleanup(&ipipeif->subdev.entity); /* unregister subdev */ v4l2_device_unregister_subdev(&ipipeif->subdev); + /* cleanup entity */ + media_entity_cleanup(&ipipeif->subdev.entity); } int diff --git a/drivers/staging/media/davinci_vpfe/dm365_isif.c b/drivers/staging/media/davinci_vpfe/dm365_isif.c index 5829360f74c9..ff48fce94fcb 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_isif.c +++ b/drivers/staging/media/davinci_vpfe/dm365_isif.c @@ -1750,10 +1750,10 @@ static const struct media_entity_operations isif_media_ops = { void vpfe_isif_unregister_entities(struct vpfe_isif_device *isif) { vpfe_video_unregister(&isif->video_out); - /* cleanup entity */ - media_entity_cleanup(&isif->subdev.entity); /* unregister subdev */ v4l2_device_unregister_subdev(&isif->subdev); + /* cleanup entity */ + media_entity_cleanup(&isif->subdev.entity); } static void isif_restore_defaults(struct vpfe_isif_device *isif) diff --git a/drivers/staging/media/davinci_vpfe/dm365_resizer.c b/drivers/staging/media/davinci_vpfe/dm365_resizer.c index 126f84c4cb64..8e13bd494c98 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_resizer.c +++ b/drivers/staging/media/davinci_vpfe/dm365_resizer.c @@ -1777,14 +1777,14 @@ void vpfe_resizer_unregister_entities(struct vpfe_resizer_device *vpfe_rsz) vpfe_video_unregister(&vpfe_rsz->resizer_a.video_out); vpfe_video_unregister(&vpfe_rsz->resizer_b.video_out); - /* cleanup entity */ - media_entity_cleanup(&vpfe_rsz->crop_resizer.subdev.entity); - media_entity_cleanup(&vpfe_rsz->resizer_a.subdev.entity); - media_entity_cleanup(&vpfe_rsz->resizer_b.subdev.entity); /* unregister subdev */ v4l2_device_unregister_subdev(&vpfe_rsz->crop_resizer.subdev); v4l2_device_unregister_subdev(&vpfe_rsz->resizer_a.subdev); v4l2_device_unregister_subdev(&vpfe_rsz->resizer_b.subdev); + /* cleanup entity */ + media_entity_cleanup(&vpfe_rsz->crop_resizer.subdev.entity); + media_entity_cleanup(&vpfe_rsz->resizer_a.subdev.entity); + media_entity_cleanup(&vpfe_rsz->resizer_b.subdev.entity); } /* @@ -1865,12 +1865,12 @@ out_create_link: vpfe_video_unregister(&resizer->resizer_b.video_out); out_video_out2_register: vpfe_video_unregister(&resizer->resizer_a.video_out); - media_entity_cleanup(&resizer->crop_resizer.subdev.entity); - media_entity_cleanup(&resizer->resizer_a.subdev.entity); - media_entity_cleanup(&resizer->resizer_b.subdev.entity); v4l2_device_unregister_subdev(&resizer->crop_resizer.subdev); v4l2_device_unregister_subdev(&resizer->resizer_a.subdev); v4l2_device_unregister_subdev(&resizer->resizer_b.subdev); + media_entity_cleanup(&resizer->crop_resizer.subdev.entity); + media_entity_cleanup(&resizer->resizer_a.subdev.entity); + media_entity_cleanup(&resizer->resizer_b.subdev.entity); return ret; } diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.c b/drivers/staging/media/davinci_vpfe/vpfe_video.c index ba913f1d955b..24d98a6866bb 100644 --- a/drivers/staging/media/davinci_vpfe/vpfe_video.c +++ b/drivers/staging/media/davinci_vpfe/vpfe_video.c @@ -39,7 +39,7 @@ static struct media_entity *vpfe_get_input_entity struct vpfe_device *vpfe_dev = video->vpfe_dev; struct media_pad *remote; - remote = media_entity_remote_source(&vpfe_dev->vpfe_isif.pads[0]); + remote = media_entity_remote_pad(&vpfe_dev->vpfe_isif.pads[0]); if (remote == NULL) { pr_err("Invalid media connection to isif/ccdc\n"); return NULL; @@ -56,7 +56,7 @@ static int vpfe_update_current_ext_subdev(struct vpfe_video_device *video) struct media_pad *remote; int i; - remote = media_entity_remote_source(&vpfe_dev->vpfe_isif.pads[0]); + remote = media_entity_remote_pad(&vpfe_dev->vpfe_isif.pads[0]); if (remote == NULL) { pr_err("Invalid media connection to isif/ccdc\n"); return -EINVAL; @@ -89,7 +89,7 @@ static int vpfe_update_current_ext_subdev(struct vpfe_video_device *video) static struct v4l2_subdev * vpfe_video_remote_subdev(struct vpfe_video_device *video, u32 *pad) { - struct media_pad *remote = media_entity_remote_source(&video->pad); + struct media_pad *remote = media_entity_remote_pad(&video->pad); if (remote == NULL || remote->entity->type != MEDIA_ENT_T_V4L2_SUBDEV) return NULL; @@ -114,7 +114,7 @@ __vpfe_video_get_format(struct vpfe_video_device *video, return -EINVAL; fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; - remote = media_entity_remote_source(&video->pad); + remote = media_entity_remote_pad(&video->pad); fmt.pad = remote->index; ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt); @@ -245,7 +245,7 @@ static int vpfe_video_validate_pipeline(struct vpfe_pipeline *pipe) return -EPIPE; /* Retrieve the source format */ - pad = media_entity_remote_source(pad); + pad = media_entity_remote_pad(pad); if (pad == NULL || pad->entity->type != MEDIA_ENT_T_V4L2_SUBDEV) break; @@ -667,7 +667,7 @@ static int vpfe_enum_fmt(struct file *file, void *priv, return -EINVAL; } /* get the remote pad */ - remote = media_entity_remote_source(&video->pad); + remote = media_entity_remote_pad(&video->pad); if (remote == NULL) { v4l2_err(&vpfe_dev->v4l2_dev, "invalid remote pad for video node\n"); @@ -1614,7 +1614,7 @@ int vpfe_video_register(struct vpfe_video_device *video, void vpfe_video_unregister(struct vpfe_video_device *video) { if (video_is_registered(&video->video_dev)) { - media_entity_cleanup(&video->video_dev.entity); video_unregister_device(&video->video_dev); + media_entity_cleanup(&video->video_dev.entity); } } diff --git a/drivers/staging/media/dt3155v4l/dt3155v4l.c b/drivers/staging/media/dt3155v4l/dt3155v4l.c index c32e0acde4f4..90d6ac469355 100644 --- a/drivers/staging/media/dt3155v4l/dt3155v4l.c +++ b/drivers/staging/media/dt3155v4l/dt3155v4l.c @@ -829,7 +829,6 @@ static struct video_device dt3155_vdev = { .minor = -1, .release = video_device_release, .tvnorms = DT3155_CURRENT_NORM, - .current_norm = DT3155_CURRENT_NORM, }; /* same as in drivers/base/dma-coherent.c */ diff --git a/drivers/staging/media/go7007/go7007-usb.c b/drivers/staging/media/go7007/go7007-usb.c index 50066e01a6ed..46ed83245035 100644 --- a/drivers/staging/media/go7007/go7007-usb.c +++ b/drivers/staging/media/go7007/go7007-usb.c @@ -1124,7 +1124,7 @@ static int go7007_usb_probe(struct usb_interface *intf, case GO7007_BOARDID_LIFEVIEW_LR192: printk(KERN_ERR "go7007-usb: The Lifeview TV Walker Ultra " "is not supported. Sorry!\n"); - return 0; + return -ENODEV; name = "Lifeview TV Walker Ultra"; board = &board_lifeview_lr192; break; @@ -1140,7 +1140,7 @@ static int go7007_usb_probe(struct usb_interface *intf, default: printk(KERN_ERR "go7007-usb: unknown board ID %d!\n", (unsigned int)id->driver_info); - return 0; + return -ENODEV; } go = go7007_alloc(&board->main_info, &intf->dev); diff --git a/drivers/staging/media/lirc/lirc_imon.c b/drivers/staging/media/lirc/lirc_imon.c index 0a2c45dd4475..4afa7da11f37 100644 --- a/drivers/staging/media/lirc/lirc_imon.c +++ b/drivers/staging/media/lirc/lirc_imon.c @@ -911,8 +911,8 @@ static int imon_probe(struct usb_interface *interface, if (retval) { dev_err(dev, "%s: usb_submit_urb failed for intf0 (%d)\n", __func__, retval); - mutex_unlock(&context->ctx_lock); - goto exit; + alloc_status = 8; + goto unlock; } usb_set_intfdata(interface, context); @@ -937,6 +937,8 @@ unlock: alloc_status_switch: switch (alloc_status) { + case 8: + lirc_unregister_driver(driver->minor); case 7: usb_free_urb(tx_urb); case 6: @@ -959,7 +961,6 @@ alloc_status_switch: retval = 0; } -exit: mutex_unlock(&driver_lock); return retval; diff --git a/drivers/staging/media/solo6x10/solo6x10-tw28.c b/drivers/staging/media/solo6x10/solo6x10-tw28.c index ad00e2b60323..af65ea655f15 100644 --- a/drivers/staging/media/solo6x10/solo6x10-tw28.c +++ b/drivers/staging/media/solo6x10/solo6x10-tw28.c @@ -513,62 +513,82 @@ static int tw2815_setup(struct solo_dev *solo_dev, u8 dev_addr) #define FIRST_ACTIVE_LINE 0x0008 #define LAST_ACTIVE_LINE 0x0102 -static void saa7128_setup(struct solo_dev *solo_dev) +static void saa712x_write_regs(struct solo_dev *dev, const uint8_t *vals, + int start, int n) { - int i; - unsigned char regs[128] = { - 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + for (;start < n; start++, vals++) { + /* Skip read-only registers */ + switch (start) { + /* case 0x00 ... 0x25: */ + case 0x2e ... 0x37: + case 0x60: + case 0x7d: + continue; + } + solo_i2c_writebyte(dev, SOLO_I2C_SAA, 0x46, start, *vals); + } +} + +#define SAA712x_reg7c (0x80 | ((LAST_ACTIVE_LINE & 0x100) >> 2) \ + | ((FIRST_ACTIVE_LINE & 0x100) >> 4)) + +static void saa712x_setup(struct solo_dev *dev) +{ + const int reg_start = 0x26; + const uint8_t saa7128_regs_ntsc[] = { + /* :0x26 */ + 0x0d, 0x00, + /* :0x28 */ + 0x59, 0x1d, 0x75, 0x3f, 0x06, 0x3f, + /* :0x2e XXX: read-only */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x1C, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, - 0x59, 0x1d, 0x75, 0x3f, 0x06, 0x3f, 0x00, 0x00, - 0x1c, 0x33, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, + /* :0x38 */ 0x1a, 0x1a, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, + /* :0x40 */ 0x00, 0x00, 0x00, 0x68, 0x10, 0x97, 0x4c, 0x18, 0x9b, 0x93, 0x9f, 0xff, 0x7c, 0x34, 0x3f, 0x3f, + /* :0x50 */ 0x3f, 0x83, 0x83, 0x80, 0x0d, 0x0f, 0xc3, 0x06, 0x02, 0x80, 0x71, 0x77, 0xa7, 0x67, 0x66, 0x2e, + /* :0x60 */ 0x7b, 0x11, 0x4f, 0x1f, 0x7c, 0xf0, 0x21, 0x77, - 0x41, 0x88, 0x41, 0x12, 0xed, 0x10, 0x10, 0x00, + 0x41, 0x88, 0x41, 0x52, 0xed, 0x10, 0x10, 0x00, + /* :0x70 */ + 0x41, 0xc3, 0x00, 0x3e, 0xb8, 0x02, 0x00, 0x00, + 0x00, 0x00, FIRST_ACTIVE_LINE, LAST_ACTIVE_LINE & 0xff, + SAA712x_reg7c, 0x00, 0xff, 0xff, + }, saa7128_regs_pal[] = { + /* :0x26 */ + 0x0d, 0x00, + /* :0x28 */ + 0xe1, 0x1d, 0x75, 0x3f, 0x06, 0x3f, + /* :0x2e XXX: read-only */ + 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* :0x38 */ + 0x1a, 0x1a, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, + /* :0x40 */ + 0x00, 0x00, 0x00, 0x68, 0x10, 0x97, 0x4c, 0x18, + 0x9b, 0x93, 0x9f, 0xff, 0x7c, 0x34, 0x3f, 0x3f, + /* :0x50 */ + 0x3f, 0x83, 0x83, 0x80, 0x0d, 0x0f, 0xc3, 0x06, + 0x02, 0x80, 0x0f, 0x77, 0xa7, 0x67, 0x66, 0x2e, + /* :0x60 */ + 0x7b, 0x02, 0x35, 0xcb, 0x8a, 0x09, 0x2a, 0x77, + 0x41, 0x88, 0x41, 0x52, 0xf1, 0x10, 0x20, 0x00, + /* :0x70 */ 0x41, 0xc3, 0x00, 0x3e, 0xb8, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x08, 0xff, 0x80, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x12, 0x30, + SAA712x_reg7c | 0x40, 0x00, 0xff, 0xff, }; - regs[0x7A] = FIRST_ACTIVE_LINE & 0xff; - regs[0x7B] = LAST_ACTIVE_LINE & 0xff; - regs[0x7C] = ((1 << 7) | - (((LAST_ACTIVE_LINE >> 8) & 1) << 6) | - (((FIRST_ACTIVE_LINE >> 8) & 1) << 4)); - - /* PAL: XXX: We could do a second set of regs to avoid this */ - if (solo_dev->video_type != SOLO_VO_FMT_TYPE_NTSC) { - regs[0x28] = 0xE1; - - regs[0x5A] = 0x0F; - regs[0x61] = 0x02; - regs[0x62] = 0x35; - regs[0x63] = 0xCB; - regs[0x64] = 0x8A; - regs[0x65] = 0x09; - regs[0x66] = 0x2A; - - regs[0x6C] = 0xf1; - regs[0x6E] = 0x20; - - regs[0x7A] = 0x06 + 12; - regs[0x7b] = 0x24 + 12; - regs[0x7c] |= 1 << 6; - } - - /* First 0x25 bytes are read-only? */ - for (i = 0x26; i < 128; i++) { - if (i == 0x60 || i == 0x7D) - continue; - solo_i2c_writebyte(solo_dev, SOLO_I2C_SAA, 0x46, i, regs[i]); - } - - return; + if (dev->video_type == SOLO_VO_FMT_TYPE_PAL) + saa712x_write_regs(dev, saa7128_regs_pal, reg_start, + sizeof(saa7128_regs_pal)); + else + saa712x_write_regs(dev, saa7128_regs_ntsc, reg_start, + sizeof(saa7128_regs_ntsc)); } int solo_tw28_init(struct solo_dev *solo_dev) @@ -609,7 +629,7 @@ int solo_tw28_init(struct solo_dev *solo_dev) return -EINVAL; } - saa7128_setup(solo_dev); + saa712x_setup(solo_dev); for (i = 0; i < solo_dev->tw28_cnt; i++) { if ((solo_dev->tw2865 & (1 << i))) diff --git a/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c b/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c index 98e2902afd74..a4c589604b02 100644 --- a/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c +++ b/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c @@ -996,12 +996,11 @@ static int solo_g_parm(struct file *file, void *priv, struct v4l2_streamparm *sp) { struct solo_enc_dev *solo_enc = video_drvdata(file); - struct solo_dev *solo_dev = solo_enc->solo_dev; struct v4l2_captureparm *cp = &sp->parm.capture; cp->capability = V4L2_CAP_TIMEPERFRAME; cp->timeperframe.numerator = solo_enc->interval; - cp->timeperframe.denominator = solo_dev->fps; + cp->timeperframe.denominator = solo_enc->solo_dev->fps; cp->capturemode = 0; /* XXX: Shouldn't we be able to get/set this from videobuf? */ cp->readbuffers = 2; @@ -1009,36 +1008,29 @@ static int solo_g_parm(struct file *file, void *priv, return 0; } +static inline int calc_interval(u8 fps, u32 n, u32 d) +{ + if (!n || !d) + return 1; + if (d == fps) + return n; + n *= fps; + return min(15U, n / d + (n % d >= (fps >> 1))); +} + static int solo_s_parm(struct file *file, void *priv, struct v4l2_streamparm *sp) { struct solo_enc_dev *solo_enc = video_drvdata(file); - struct solo_dev *solo_dev = solo_enc->solo_dev; - struct v4l2_captureparm *cp = &sp->parm.capture; + struct v4l2_fract *t = &sp->parm.capture.timeperframe; + u8 fps = solo_enc->solo_dev->fps; if (vb2_is_streaming(&solo_enc->vidq)) return -EBUSY; - if ((cp->timeperframe.numerator == 0) || - (cp->timeperframe.denominator == 0)) { - /* reset framerate */ - cp->timeperframe.numerator = 1; - cp->timeperframe.denominator = solo_dev->fps; - } - - if (cp->timeperframe.denominator != solo_dev->fps) - cp->timeperframe.denominator = solo_dev->fps; - - if (cp->timeperframe.numerator > 15) - cp->timeperframe.numerator = 15; - - solo_enc->interval = cp->timeperframe.numerator; - - cp->capability = V4L2_CAP_TIMEPERFRAME; - cp->readbuffers = 2; - + solo_enc->interval = calc_interval(fps, t->numerator, t->denominator); solo_update_mode(solo_enc); - return 0; + return solo_g_parm(file, priv, sp); } static long solo_enc_default(struct file *file, void *fh, diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c index 5f91c7a59946..e2a1f50bd93c 100644 --- a/drivers/usb/gadget/f_uvc.c +++ b/drivers/usb/gadget/f_uvc.c @@ -406,7 +406,7 @@ uvc_register_video(struct uvc_device *uvc) if (video == NULL) return -ENOMEM; - video->parent = &cdev->gadget->dev; + video->v4l2_dev = &uvc->v4l2_dev; video->fops = &uvc_v4l2_fops; video->release = video_device_release; strlcpy(video->name, cdev->gadget->name, sizeof(video->name)); @@ -563,6 +563,7 @@ uvc_function_unbind(struct usb_configuration *c, struct usb_function *f) INFO(cdev, "uvc_function_unbind\n"); video_unregister_device(uvc->vdev); + v4l2_device_unregister(&uvc->v4l2_dev); uvc->control_ep->driver_data = NULL; uvc->video.ep->driver_data = NULL; @@ -690,6 +691,11 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) if ((ret = usb_function_deactivate(f)) < 0) goto error; + if (v4l2_device_register(&cdev->gadget->dev, &uvc->v4l2_dev)) { + printk(KERN_INFO "v4l2_device_register failed\n"); + goto error; + } + /* Initialise video. */ ret = uvc_video_init(&uvc->video); if (ret < 0) @@ -705,6 +711,7 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) return 0; error: + v4l2_device_unregister(&uvc->v4l2_dev); if (uvc->vdev) video_device_release(uvc->vdev); diff --git a/drivers/usb/gadget/uvc.h b/drivers/usb/gadget/uvc.h index 817e9e19cecf..7a9111de8054 100644 --- a/drivers/usb/gadget/uvc.h +++ b/drivers/usb/gadget/uvc.h @@ -57,6 +57,7 @@ struct uvc_event #include <linux/videodev2.h> #include <linux/version.h> #include <media/v4l2-fh.h> +#include <media/v4l2-device.h> #include "uvc_queue.h" @@ -145,6 +146,7 @@ enum uvc_state struct uvc_device { struct video_device *vdev; + struct v4l2_device v4l2_dev; enum uvc_state state; struct usb_function func; struct uvc_video video; diff --git a/include/media/davinci/vpbe_osd.h b/include/media/davinci/vpbe_osd.h index 42628fcfe1bd..de59364d7ed2 100644 --- a/include/media/davinci/vpbe_osd.h +++ b/include/media/davinci/vpbe_osd.h @@ -82,9 +82,9 @@ enum osd_pix_format { PIXFMT_4BPP, PIXFMT_8BPP, PIXFMT_RGB565, - PIXFMT_YCbCrI, + PIXFMT_YCBCRI, PIXFMT_RGB888, - PIXFMT_YCrCbI, + PIXFMT_YCRCBI, PIXFMT_NV12, PIXFMT_OSD_ATTR, }; diff --git a/include/media/media-device.h b/include/media/media-device.h index eaade9815bb6..12155a9596c4 100644 --- a/include/media/media-device.h +++ b/include/media/media-device.h @@ -45,6 +45,7 @@ struct device; * @entities: List of registered entities * @lock: Entities list lock * @graph_mutex: Entities graph operation lock + * @link_notify: Link state change notification callback * * This structure represents an abstract high-level media device. It allows easy * access to entities and provides basic media device-level support. The @@ -75,10 +76,14 @@ struct media_device { /* Serializes graph operations. */ struct mutex graph_mutex; - int (*link_notify)(struct media_pad *source, - struct media_pad *sink, u32 flags); + int (*link_notify)(struct media_link *link, u32 flags, + unsigned int notification); }; +/* Supported link_notify @notification values. */ +#define MEDIA_DEV_NOTIFY_PRE_LINK_CH 0 +#define MEDIA_DEV_NOTIFY_POST_LINK_CH 1 + /* media_devnode to media_device */ #define to_media_device(node) container_of(node, struct media_device, devnode) diff --git a/include/media/media-entity.h b/include/media/media-entity.h index 0c16f518ee09..06bacf937d61 100644 --- a/include/media/media-entity.h +++ b/include/media/media-entity.h @@ -128,11 +128,14 @@ void media_entity_cleanup(struct media_entity *entity); int media_entity_create_link(struct media_entity *source, u16 source_pad, struct media_entity *sink, u16 sink_pad, u32 flags); +void __media_entity_remove_links(struct media_entity *entity); +void media_entity_remove_links(struct media_entity *entity); + int __media_entity_setup_link(struct media_link *link, u32 flags); int media_entity_setup_link(struct media_link *link, u32 flags); struct media_link *media_entity_find_link(struct media_pad *source, struct media_pad *sink); -struct media_pad *media_entity_remote_source(struct media_pad *pad); +struct media_pad *media_entity_remote_pad(struct media_pad *pad); struct media_entity *media_entity_get(struct media_entity *entity); void media_entity_put(struct media_entity *entity); diff --git a/include/media/rc-map.h b/include/media/rc-map.h index 5d5d3a30f04a..6628f5d01f52 100644 --- a/include/media/rc-map.h +++ b/include/media/rc-map.h @@ -111,6 +111,7 @@ void rc_map_init(void); #define RC_MAP_BUDGET_CI_OLD "rc-budget-ci-old" #define RC_MAP_CINERGY_1400 "rc-cinergy-1400" #define RC_MAP_CINERGY "rc-cinergy" +#define RC_MAP_DELOCK_61959 "rc-delock-61959" #define RC_MAP_DIB0700_NEC_TABLE "rc-dib0700-nec" #define RC_MAP_DIB0700_RC5_TABLE "rc-dib0700-rc5" #define RC_MAP_DIGITALNOW_TINYTWIN "rc-digitalnow-tinytwin" diff --git a/include/media/s5p_fimc.h b/include/media/s5p_fimc.h index f50969025ef3..b975c285c8a9 100644 --- a/include/media/s5p_fimc.h +++ b/include/media/s5p_fimc.h @@ -13,6 +13,7 @@ #define S5P_FIMC_H_ #include <media/media-entity.h> +#include <media/v4l2-dev.h> #include <media/v4l2-mediabus.h> /* @@ -115,6 +116,7 @@ struct s5p_platform_fimc { * @color: the driver's private color format id * @memplanes: number of physically non-contiguous data planes * @colplanes: number of physically contiguous data planes + * @colorspace: v4l2 colorspace (V4L2_COLORSPACE_*) * @depth: per plane driver's private 'number of bits per pixel' * @mdataplanes: bitmask indicating meta data plane(s), (1 << plane_no) * @flags: flags indicating which operation mode format applies to @@ -126,6 +128,7 @@ struct fimc_fmt { u32 color; u16 memplanes; u16 colplanes; + u8 colorspace; u8 depth[FIMC_MAX_PLANES]; u16 mdataplanes; u16 flags; @@ -140,37 +143,40 @@ struct fimc_fmt { #define FMT_FLAGS_YUV (1 << 7) }; -enum fimc_subdev_index { - IDX_SENSOR, - IDX_CSIS, - IDX_FLITE, - IDX_IS_ISP, - IDX_FIMC, - IDX_MAX, -}; +struct exynos_media_pipeline; -struct media_pipeline; -struct v4l2_subdev; +/* + * Media pipeline operations to be called from within a video node, i.e. the + * last entity within the pipeline. Implemented by related media device driver. + */ +struct exynos_media_pipeline_ops { + int (*prepare)(struct exynos_media_pipeline *p, + struct media_entity *me); + int (*unprepare)(struct exynos_media_pipeline *p); + int (*open)(struct exynos_media_pipeline *p, struct media_entity *me, + bool resume); + int (*close)(struct exynos_media_pipeline *p); + int (*set_stream)(struct exynos_media_pipeline *p, bool state); +}; -struct fimc_pipeline { - struct v4l2_subdev *subdevs[IDX_MAX]; - struct media_pipeline *m_pipeline; +struct exynos_video_entity { + struct video_device vdev; + struct exynos_media_pipeline *pipe; }; -/* - * Media pipeline operations to be called from within the fimc(-lite) - * video node when it is the last entity of the pipeline. Implemented - * by corresponding media device driver. - */ -struct fimc_pipeline_ops { - int (*open)(struct fimc_pipeline *p, struct media_entity *me, - bool resume); - int (*close)(struct fimc_pipeline *p); - int (*set_stream)(struct fimc_pipeline *p, bool state); +struct exynos_media_pipeline { + struct media_pipeline mp; + const struct exynos_media_pipeline_ops *ops; }; -#define fimc_pipeline_call(f, op, p, args...) \ - (!(f) ? -ENODEV : (((f)->pipeline_ops && (f)->pipeline_ops->op) ? \ - (f)->pipeline_ops->op((p), ##args) : -ENOIOCTLCMD)) +static inline struct exynos_video_entity *vdev_to_exynos_video_entity( + struct video_device *vdev) +{ + return container_of(vdev, struct exynos_video_entity, vdev); +} + +#define fimc_pipeline_call(ent, op, args...) \ + (!(ent) ? -ENOENT : (((ent)->pipe->ops && (ent)->pipe->ops->op) ? \ + (ent)->pipe->ops->op(((ent)->pipe), ##args) : -ENOIOCTLCMD)) \ #endif /* S5P_FIMC_H_ */ diff --git a/include/media/sh_mobile_ceu.h b/include/media/sh_mobile_ceu.h index 6fdb6adf6b2b..7f57056c22ba 100644 --- a/include/media/sh_mobile_ceu.h +++ b/include/media/sh_mobile_ceu.h @@ -22,6 +22,8 @@ struct sh_mobile_ceu_info { int max_width; int max_height; struct sh_mobile_ceu_companion *csi2; + struct v4l2_async_subdev **asd; /* Flat array, arranged in groups */ + unsigned int *asd_sizes; /* 0-terminated array pf asd group sizes */ }; #endif /* __ASM_SH_MOBILE_CEU_H__ */ diff --git a/include/media/sh_mobile_csi2.h b/include/media/sh_mobile_csi2.h index c586c4f7f16b..14030db51f13 100644 --- a/include/media/sh_mobile_csi2.h +++ b/include/media/sh_mobile_csi2.h @@ -33,6 +33,7 @@ struct sh_csi2_client_config { unsigned char lanes; /* bitmask[3:0] */ unsigned char channel; /* 0..3 */ struct platform_device *pdev; /* client platform device */ + const char *name; /* async matching: client name */ }; struct v4l2_device; @@ -42,7 +43,6 @@ struct sh_csi2_pdata { unsigned int flags; struct sh_csi2_client_config *clients; int num_clients; - struct v4l2_device *v4l2_dev; }; #endif diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index ff77d08c30fd..34d2414f2b8c 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h @@ -19,11 +19,13 @@ #include <linux/videodev2.h> #include <media/videobuf-core.h> #include <media/videobuf2-core.h> +#include <media/v4l2-async.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> struct file; struct soc_camera_desc; +struct soc_camera_async_client; struct soc_camera_device { struct list_head list; /* list of all registered devices */ @@ -49,6 +51,10 @@ struct soc_camera_device { /* soc_camera.c private count. Only accessed with .host_lock held */ int use_count; struct file *streamer; /* stream owner */ + struct v4l2_clk *clk; + /* Asynchronous subdevice management */ + struct soc_camera_async_client *sasc; + /* video buffer queue */ union { struct videobuf_queue vb_vidq; struct vb2_queue vb2_vidq; @@ -58,21 +64,38 @@ struct soc_camera_device { /* Host supports programmable stride */ #define SOCAM_HOST_CAP_STRIDE (1 << 0) +enum soc_camera_subdev_role { + SOCAM_SUBDEV_DATA_SOURCE = 1, + SOCAM_SUBDEV_DATA_SINK, + SOCAM_SUBDEV_DATA_PROCESSOR, +}; + +struct soc_camera_async_subdev { + struct v4l2_async_subdev asd; + enum soc_camera_subdev_role role; +}; + struct soc_camera_host { struct v4l2_device v4l2_dev; struct list_head list; - struct mutex host_lock; /* Protect pipeline modifications */ + struct mutex host_lock; /* Main synchronisation lock */ + struct mutex clk_lock; /* Protect pipeline modifications */ unsigned char nr; /* Host number */ u32 capabilities; + struct soc_camera_device *icd; /* Currently attached client */ void *priv; const char *drv_name; struct soc_camera_host_ops *ops; + struct v4l2_async_subdev **asd; /* Flat array, arranged in groups */ + unsigned int *asd_sizes; /* 0-terminated array of asd group sizes */ }; struct soc_camera_host_ops { struct module *owner; int (*add)(struct soc_camera_device *); void (*remove)(struct soc_camera_device *); + int (*clock_start)(struct soc_camera_host *); + void (*clock_stop)(struct soc_camera_host *); /* * .get_formats() is called for each client device format, but * .put_formats() is only called once. Further, if any of the calls to @@ -157,6 +180,7 @@ struct soc_camera_host_desc { }; /* + * Platform data for "soc-camera-pdrv" * This MUST be kept binary-identical to struct soc_camera_link below, until * it is completely replaced by this one, after which we can split it into its * two components. @@ -322,14 +346,17 @@ static inline void soc_camera_limit_side(int *start, int *length, unsigned long soc_camera_apply_board_flags(struct soc_camera_subdev_desc *ssdd, const struct v4l2_mbus_config *cfg); -int soc_camera_power_on(struct device *dev, struct soc_camera_subdev_desc *ssdd); -int soc_camera_power_off(struct device *dev, struct soc_camera_subdev_desc *ssdd); +int soc_camera_power_init(struct device *dev, struct soc_camera_subdev_desc *ssdd); +int soc_camera_power_on(struct device *dev, struct soc_camera_subdev_desc *ssdd, + struct v4l2_clk *clk); +int soc_camera_power_off(struct device *dev, struct soc_camera_subdev_desc *ssdd, + struct v4l2_clk *clk); static inline int soc_camera_set_power(struct device *dev, - struct soc_camera_subdev_desc *ssdd, bool on) + struct soc_camera_subdev_desc *ssdd, struct v4l2_clk *clk, bool on) { - return on ? soc_camera_power_on(dev, ssdd) - : soc_camera_power_off(dev, ssdd); + return on ? soc_camera_power_on(dev, ssdd, clk) + : soc_camera_power_off(dev, ssdd, clk); } /* This is only temporary here - until v4l2-subdev begins to link to video_device */ @@ -346,9 +373,9 @@ static inline struct soc_camera_subdev_desc *soc_camera_i2c_to_desc(const struct return client->dev.platform_data; } -static inline struct v4l2_subdev *soc_camera_vdev_to_subdev(const struct video_device *vdev) +static inline struct v4l2_subdev *soc_camera_vdev_to_subdev(struct video_device *vdev) { - struct soc_camera_device *icd = dev_get_drvdata(vdev->parent); + struct soc_camera_device *icd = video_get_drvdata(vdev); return soc_camera_to_subdev(icd); } diff --git a/include/media/ths7303.h b/include/media/ths7303.h index 980ec51d574d..a7b49297da82 100644 --- a/include/media/ths7303.h +++ b/include/media/ths7303.h @@ -30,13 +30,11 @@ * @ch_1: Bias value for channel one. * @ch_2: Bias value for channel two. * @ch_3: Bias value for channel three. - * @init_enable: initalize on init. */ struct ths7303_platform_data { u8 ch_1; u8 ch_2; u8 ch_3; - u8 init_enable; }; #endif diff --git a/include/media/tveeprom.h b/include/media/tveeprom.h index a8ad75a9152a..4a1191abd936 100644 --- a/include/media/tveeprom.h +++ b/include/media/tveeprom.h @@ -1,6 +1,17 @@ /* */ +enum tveeprom_audio_processor { + /* No audio processor present */ + TVEEPROM_AUDPROC_NONE, + /* The audio processor is internal to the video processor */ + TVEEPROM_AUDPROC_INTERNAL, + /* The audio processor is a MSPXXXX device */ + TVEEPROM_AUDPROC_MSP, + /* The audio processor is another device */ + TVEEPROM_AUDPROC_OTHER, +}; + struct tveeprom { u32 has_radio; /* If has_ir == 0, then it is unknown what the IR capabilities are, diff --git a/include/media/tvp7002.h b/include/media/tvp7002.h index ee4353459ef5..fadb6afe9ef0 100644 --- a/include/media/tvp7002.h +++ b/include/media/tvp7002.h @@ -26,31 +26,29 @@ #ifndef _TVP7002_H_ #define _TVP7002_H_ -/* Platform-dependent data - * - * clk_polarity: - * 0 -> data clocked out on rising edge of DATACLK signal - * 1 -> data clocked out on falling edge of DATACLK signal - * hs_polarity: - * 0 -> active low HSYNC output - * 1 -> active high HSYNC output - * sog_polarity: - * 0 -> normal operation - * 1 -> operation with polarity inverted - * vs_polarity: - * 0 -> active low VSYNC output - * 1 -> active high VSYNC output - * fid_polarity: - * 0 -> the field ID output is set to logic 1 for an odd - * field (field 1) and set to logic 0 for an even - * field (field 0). - * 1 -> operation with polarity inverted. +#define TVP7002_MODULE_NAME "tvp7002" + +/** + * struct tvp7002_config - Platform dependent data + *@clk_polarity: Clock polarity + * 0 - Data clocked out on rising edge of DATACLK signal + * 1 - Data clocked out on falling edge of DATACLK signal + *@hs_polarity: HSYNC polarity + * 0 - Active low HSYNC output, 1 - Active high HSYNC output + *@vs_polarity: VSYNC Polarity + * 0 - Active low VSYNC output, 1 - Active high VSYNC output + *@fid_polarity: Active-high Field ID polarity. + * 0 - The field ID output is set to logic 1 for an odd field + * (field 1) and set to logic 0 for an even field (field 0). + * 1 - Operation with polarity inverted. + *@sog_polarity: Active high Sync on Green output polarity. + * 0 - Normal operation, 1 - Operation with polarity inverted */ struct tvp7002_config { - u8 clk_polarity; - u8 hs_polarity; - u8 vs_polarity; - u8 fid_polarity; - u8 sog_polarity; + bool clk_polarity; + bool hs_polarity; + bool vs_polarity; + bool fid_polarity; + bool sog_polarity; }; #endif diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h new file mode 100644 index 000000000000..c3ec6ac75f7e --- /dev/null +++ b/include/media/v4l2-async.h @@ -0,0 +1,105 @@ +/* + * V4L2 asynchronous subdevice registration API + * + * Copyright (C) 2012-2013, Guennadi Liakhovetski <g.liakhovetski@gmx.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 as + * published by the Free Software Foundation. + */ + +#ifndef V4L2_ASYNC_H +#define V4L2_ASYNC_H + +#include <linux/list.h> +#include <linux/mutex.h> + +struct device; +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_bus_type { + V4L2_ASYNC_BUS_CUSTOM, + V4L2_ASYNC_BUS_PLATFORM, + V4L2_ASYNC_BUS_I2C, +}; + +/** + * struct v4l2_async_subdev - sub-device descriptor, as known to a bridge + * @bus_type: subdevice bus type to select the appropriate matching method + * @match: union of per-bus type matching data sets + * @list: used to link struct v4l2_async_subdev objects, waiting to be + * probed, to a notifier->waiting list + */ +struct v4l2_async_subdev { + enum v4l2_async_bus_type bus_type; + union { + struct { + const char *name; + } platform; + struct { + int adapter_id; + unsigned short address; + } i2c; + struct { + bool (*match)(struct device *, + struct v4l2_async_subdev *); + void *priv; + } custom; + } match; + + /* v4l2-async core private: not to be used by drivers */ + struct list_head list; +}; + +/** + * v4l2_async_subdev_list - provided by subdevices + * @list: links struct v4l2_async_subdev_list objects to a global list + * before probing, and onto notifier->done after probing + * @asd: pointer to respective struct v4l2_async_subdev + * @notifier: pointer to managing notifier + */ +struct v4l2_async_subdev_list { + struct list_head list; + struct v4l2_async_subdev *asd; + struct v4l2_async_notifier *notifier; +}; + +/** + * v4l2_async_notifier - v4l2_device notifier data + * @num_subdevs:number of subdevices + * @subdev: array of pointers to subdevice descriptors + * @v4l2_dev: pointer to struct v4l2_device + * @waiting: list of struct v4l2_async_subdev, waiting for their drivers + * @done: list of struct v4l2_async_subdev_list, already probed + * @list: member in a global list of notifiers + * @bound: a subdevice driver has successfully probed one of subdevices + * @complete: all subdevices have been probed successfully + * @unbind: a subdevice is leaving + */ +struct v4l2_async_notifier { + unsigned int num_subdevs; + struct v4l2_async_subdev **subdev; + struct v4l2_device *v4l2_dev; + struct list_head waiting; + struct list_head done; + struct list_head list; + int (*bound)(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *subdev, + struct v4l2_async_subdev *asd); + int (*complete)(struct v4l2_async_notifier *notifier); + void (*unbind)(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *subdev, + struct v4l2_async_subdev *asd); +}; + +int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev, + struct v4l2_async_notifier *notifier); +void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier); +int v4l2_async_register_subdev(struct v4l2_subdev *sd); +void v4l2_async_unregister_subdev(struct v4l2_subdev *sd); +#endif diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h deleted file mode 100644 index c259b36bf1e9..000000000000 --- a/include/media/v4l2-chip-ident.h +++ /dev/null @@ -1,352 +0,0 @@ -/* - v4l2 chip identifiers header - - This header provides a list of chip identifiers that can be returned - through the VIDIOC_DBG_G_CHIP_IDENT ioctl. - - Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> - - 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. - - 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. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef V4L2_CHIP_IDENT_H_ -#define V4L2_CHIP_IDENT_H_ - -/* VIDIOC_DBG_G_CHIP_IDENT: identifies the actual chip installed on the board */ - -/* KEEP THIS LIST ORDERED BY ID! - Otherwise it will be hard to see which ranges are already in use when - adding support to a new chip family. */ -enum { - /* general idents: reserved range 0-49 */ - V4L2_IDENT_NONE = 0, /* No chip matched */ - V4L2_IDENT_AMBIGUOUS = 1, /* Match too general, multiple chips matched */ - V4L2_IDENT_UNKNOWN = 2, /* Chip found, but cannot identify */ - - /* module tvaudio: reserved range 50-99 */ - V4L2_IDENT_TVAUDIO = 50, /* A tvaudio chip, unknown which it is exactly */ - - /* Sony IMX074 */ - V4L2_IDENT_IMX074 = 74, - - /* module saa7110: just ident 100 */ - V4L2_IDENT_SAA7110 = 100, - - /* module saa7115: reserved range 101-149 */ - V4L2_IDENT_SAA7111 = 101, - V4L2_IDENT_SAA7111A = 102, - V4L2_IDENT_SAA7113 = 103, - V4L2_IDENT_SAA7114 = 104, - V4L2_IDENT_SAA7115 = 105, - V4L2_IDENT_SAA7118 = 108, - - /* module saa7127: reserved range 150-199 */ - V4L2_IDENT_SAA7127 = 157, - V4L2_IDENT_SAA7129 = 159, - - /* module cx25840: reserved range 200-249 */ - V4L2_IDENT_CX25836 = 236, - V4L2_IDENT_CX25837 = 237, - V4L2_IDENT_CX25840 = 240, - V4L2_IDENT_CX25841 = 241, - V4L2_IDENT_CX25842 = 242, - V4L2_IDENT_CX25843 = 243, - - /* OmniVision sensors: reserved range 250-299 */ - V4L2_IDENT_OV7670 = 250, - V4L2_IDENT_OV7720 = 251, - V4L2_IDENT_OV7725 = 252, - V4L2_IDENT_OV7660 = 253, - V4L2_IDENT_OV9650 = 254, - V4L2_IDENT_OV9655 = 255, - V4L2_IDENT_SOI968 = 256, - V4L2_IDENT_OV9640 = 257, - V4L2_IDENT_OV6650 = 258, - V4L2_IDENT_OV2640 = 259, - V4L2_IDENT_OV9740 = 260, - V4L2_IDENT_OV5642 = 261, - - /* module saa7146: reserved range 300-309 */ - V4L2_IDENT_SAA7146 = 300, - - /* Conexant MPEG encoder/decoders: reserved range 400-420 */ - V4L2_IDENT_CX23418_843 = 403, /* Integrated A/V Decoder on the '418 */ - V4L2_IDENT_CX23415 = 415, - V4L2_IDENT_CX23416 = 416, - V4L2_IDENT_CX23417 = 417, - V4L2_IDENT_CX23418 = 418, - - /* module bt819: reserved range 810-819 */ - V4L2_IDENT_BT815A = 815, - V4L2_IDENT_BT817A = 817, - V4L2_IDENT_BT819A = 819, - - /* module au0828 */ - V4L2_IDENT_AU0828 = 828, - - /* module bttv: ident 848 + 849 */ - V4L2_IDENT_BT848 = 848, - V4L2_IDENT_BT849 = 849, - - /* module bt856: just ident 856 */ - V4L2_IDENT_BT856 = 856, - - /* module bt866: just ident 866 */ - V4L2_IDENT_BT866 = 866, - - /* module bttv: ident 878 + 879 */ - V4L2_IDENT_BT878 = 878, - V4L2_IDENT_BT879 = 879, - - /* module ks0127: reserved range 1120-1129 */ - V4L2_IDENT_KS0122S = 1122, - V4L2_IDENT_KS0127 = 1127, - V4L2_IDENT_KS0127B = 1128, - - /* module indycam: just ident 2000 */ - V4L2_IDENT_INDYCAM = 2000, - - /* module vp27smpx: just ident 2700 */ - V4L2_IDENT_VP27SMPX = 2700, - - /* module vpx3220: reserved range: 3210-3229 */ - V4L2_IDENT_VPX3214C = 3214, - V4L2_IDENT_VPX3216B = 3216, - V4L2_IDENT_VPX3220A = 3220, - - /* VX855 just ident 3409 */ - /* Other via devs could use 3314, 3324, 3327, 3336, 3364, 3353 */ - V4L2_IDENT_VIA_VX855 = 3409, - - /* module tvp5150 */ - V4L2_IDENT_TVP5150 = 5150, - - /* module saa5246a: just ident 5246 */ - V4L2_IDENT_SAA5246A = 5246, - - /* module saa5249: just ident 5249 */ - V4L2_IDENT_SAA5249 = 5249, - - /* module cs5345: just ident 5345 */ - V4L2_IDENT_CS5345 = 5345, - - /* module tea6415c: just ident 6415 */ - V4L2_IDENT_TEA6415C = 6415, - - /* module tea6420: just ident 6420 */ - V4L2_IDENT_TEA6420 = 6420, - - /* module saa6588: just ident 6588 */ - V4L2_IDENT_SAA6588 = 6588, - - /* module vs6624: just ident 6624 */ - V4L2_IDENT_VS6624 = 6624, - - /* module saa6752hs: reserved range 6750-6759 */ - V4L2_IDENT_SAA6752HS = 6752, - V4L2_IDENT_SAA6752HS_AC3 = 6753, - - /* modules tef6862: just ident 6862 */ - V4L2_IDENT_TEF6862 = 6862, - - /* module tvp7002: just ident 7002 */ - V4L2_IDENT_TVP7002 = 7002, - - /* module adv7170: just ident 7170 */ - V4L2_IDENT_ADV7170 = 7170, - - /* module adv7175: just ident 7175 */ - V4L2_IDENT_ADV7175 = 7175, - - /* module adv7180: just ident 7180 */ - V4L2_IDENT_ADV7180 = 7180, - - /* module adv7183: just ident 7183 */ - V4L2_IDENT_ADV7183 = 7183, - - /* module saa7185: just ident 7185 */ - V4L2_IDENT_SAA7185 = 7185, - - /* module saa7191: just ident 7191 */ - V4L2_IDENT_SAA7191 = 7191, - - /* module ths7303: just ident 7303 */ - V4L2_IDENT_THS7303 = 7303, - - /* module adv7343: just ident 7343 */ - V4L2_IDENT_ADV7343 = 7343, - - /* module ths7353: just ident 7353 */ - V4L2_IDENT_THS7353 = 7353, - - /* module adv7393: just ident 7393 */ - V4L2_IDENT_ADV7393 = 7393, - - /* module adv7604: just ident 7604 */ - V4L2_IDENT_ADV7604 = 7604, - - /* module saa7706h: just ident 7706 */ - V4L2_IDENT_SAA7706H = 7706, - - /* module mt9v011, just ident 8243 */ - V4L2_IDENT_MT9V011 = 8243, - - /* module wm8739: just ident 8739 */ - V4L2_IDENT_WM8739 = 8739, - - /* module wm8775: just ident 8775 */ - V4L2_IDENT_WM8775 = 8775, - - /* Marvell controllers starting at 8801 */ - V4L2_IDENT_CAFE = 8801, - V4L2_IDENT_ARMADA610 = 8802, - - /* AKM AK8813/AK8814 */ - V4L2_IDENT_AK8813 = 8813, - V4L2_IDENT_AK8814 = 8814, - - /* module cx23885 and cx25840 */ - V4L2_IDENT_CX23885 = 8850, - V4L2_IDENT_CX23885_AV = 8851, /* Integrated A/V decoder */ - V4L2_IDENT_CX23887 = 8870, - V4L2_IDENT_CX23887_AV = 8871, /* Integrated A/V decoder */ - V4L2_IDENT_CX23888 = 8880, - V4L2_IDENT_CX23888_AV = 8881, /* Integrated A/V decoder */ - V4L2_IDENT_CX23888_IR = 8882, /* Integrated infrared controller */ - - /* module ad9389b: just ident 9389 */ - V4L2_IDENT_AD9389B = 9389, - - /* module tda9840: just ident 9840 */ - V4L2_IDENT_TDA9840 = 9840, - - /* module tw9910: just ident 9910 */ - V4L2_IDENT_TW9910 = 9910, - - /* module sn9c20x: just ident 10000 */ - V4L2_IDENT_SN9C20X = 10000, - - /* module cx231xx and cx25840 */ - V4L2_IDENT_CX2310X_AV = 23099, /* Integrated A/V decoder; not in '100 */ - V4L2_IDENT_CX23100 = 23100, - V4L2_IDENT_CX23101 = 23101, - V4L2_IDENT_CX23102 = 23102, - - /* module msp3400: reserved range 34000-34999 for msp34xx */ - V4L2_IDENT_MSPX4XX = 34000, /* generic MSPX4XX identifier, only - use internally (tveeprom.c). */ - - V4L2_IDENT_MSP3400B = 34002, - V4L2_IDENT_MSP3400C = 34003, - V4L2_IDENT_MSP3400D = 34004, - V4L2_IDENT_MSP3400G = 34007, - V4L2_IDENT_MSP3401G = 34017, - V4L2_IDENT_MSP3402G = 34027, - V4L2_IDENT_MSP3405D = 34054, - V4L2_IDENT_MSP3405G = 34057, - V4L2_IDENT_MSP3407D = 34074, - V4L2_IDENT_MSP3407G = 34077, - - V4L2_IDENT_MSP3410B = 34102, - V4L2_IDENT_MSP3410C = 34103, - V4L2_IDENT_MSP3410D = 34104, - V4L2_IDENT_MSP3410G = 34107, - V4L2_IDENT_MSP3411G = 34117, - V4L2_IDENT_MSP3412G = 34127, - V4L2_IDENT_MSP3415D = 34154, - V4L2_IDENT_MSP3415G = 34157, - V4L2_IDENT_MSP3417D = 34174, - V4L2_IDENT_MSP3417G = 34177, - - V4L2_IDENT_MSP3420G = 34207, - V4L2_IDENT_MSP3421G = 34217, - V4L2_IDENT_MSP3422G = 34227, - V4L2_IDENT_MSP3425G = 34257, - V4L2_IDENT_MSP3427G = 34277, - - V4L2_IDENT_MSP3430G = 34307, - V4L2_IDENT_MSP3431G = 34317, - V4L2_IDENT_MSP3435G = 34357, - V4L2_IDENT_MSP3437G = 34377, - - V4L2_IDENT_MSP3440G = 34407, - V4L2_IDENT_MSP3441G = 34417, - V4L2_IDENT_MSP3442G = 34427, - V4L2_IDENT_MSP3445G = 34457, - V4L2_IDENT_MSP3447G = 34477, - - V4L2_IDENT_MSP3450G = 34507, - V4L2_IDENT_MSP3451G = 34517, - V4L2_IDENT_MSP3452G = 34527, - V4L2_IDENT_MSP3455G = 34557, - V4L2_IDENT_MSP3457G = 34577, - - V4L2_IDENT_MSP3460G = 34607, - V4L2_IDENT_MSP3461G = 34617, - V4L2_IDENT_MSP3465G = 34657, - V4L2_IDENT_MSP3467G = 34677, - - /* module msp3400: reserved range 44000-44999 for msp44xx */ - V4L2_IDENT_MSP4400G = 44007, - V4L2_IDENT_MSP4408G = 44087, - V4L2_IDENT_MSP4410G = 44107, - V4L2_IDENT_MSP4418G = 44187, - V4L2_IDENT_MSP4420G = 44207, - V4L2_IDENT_MSP4428G = 44287, - V4L2_IDENT_MSP4440G = 44407, - V4L2_IDENT_MSP4448G = 44487, - V4L2_IDENT_MSP4450G = 44507, - V4L2_IDENT_MSP4458G = 44587, - - /* Micron CMOS sensor chips: 45000-45099 */ - V4L2_IDENT_MT9M001C12ST = 45000, - V4L2_IDENT_MT9M001C12STM = 45005, - V4L2_IDENT_MT9M111 = 45007, - V4L2_IDENT_MT9M112 = 45008, - V4L2_IDENT_MT9V022IX7ATC = 45010, /* No way to detect "normal" I77ATx */ - V4L2_IDENT_MT9V022IX7ATM = 45015, /* and "lead free" IA7ATx chips */ - V4L2_IDENT_MT9T031 = 45020, - V4L2_IDENT_MT9T111 = 45021, - V4L2_IDENT_MT9T112 = 45022, - V4L2_IDENT_MT9V111 = 45031, - V4L2_IDENT_MT9V112 = 45032, - - /* HV7131R CMOS sensor: just ident 46000 */ - V4L2_IDENT_HV7131R = 46000, - - /* Sharp RJ54N1CB0C, 0xCB0C = 51980 */ - V4L2_IDENT_RJ54N1CB0C = 51980, - - /* module m52790: just ident 52790 */ - V4L2_IDENT_M52790 = 52790, - - /* module cs53132a: just ident 53132 */ - V4L2_IDENT_CS53l32A = 53132, - - /* modules upd61151 MPEG2 encoder: just ident 54000 */ - V4L2_IDENT_UPD61161 = 54000, - /* modules upd61152 MPEG2 encoder with AC3: just ident 54001 */ - V4L2_IDENT_UPD61162 = 54001, - - /* module upd64031a: just ident 64031 */ - V4L2_IDENT_UPD64031A = 64031, - - /* module upd64083: just ident 64083 */ - V4L2_IDENT_UPD64083 = 64083, - - /* Don't just add new IDs at the end: KEEP THIS LIST ORDERED BY ID! */ -}; - -#endif diff --git a/include/media/v4l2-clk.h b/include/media/v4l2-clk.h new file mode 100644 index 000000000000..0503a90b48bb --- /dev/null +++ b/include/media/v4l2-clk.h @@ -0,0 +1,54 @@ +/* + * V4L2 clock service + * + * Copyright (C) 2012-2013, Guennadi Liakhovetski <g.liakhovetski@gmx.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 as + * published by the Free Software Foundation. + * + * ATTENTION: This is a temporary API and it shall be replaced by the generic + * clock API, when the latter becomes widely available. + */ + +#ifndef MEDIA_V4L2_CLK_H +#define MEDIA_V4L2_CLK_H + +#include <linux/atomic.h> +#include <linux/list.h> +#include <linux/mutex.h> + +struct module; +struct device; + +struct v4l2_clk { + struct list_head list; + const struct v4l2_clk_ops *ops; + const char *dev_id; + const char *id; + int enable; + struct mutex lock; /* Protect the enable count */ + atomic_t use_count; + void *priv; +}; + +struct v4l2_clk_ops { + struct module *owner; + int (*enable)(struct v4l2_clk *clk); + void (*disable)(struct v4l2_clk *clk); + unsigned long (*get_rate)(struct v4l2_clk *clk); + int (*set_rate)(struct v4l2_clk *clk, unsigned long); +}; + +struct v4l2_clk *v4l2_clk_register(const struct v4l2_clk_ops *ops, + const char *dev_name, + const char *name, void *priv); +void v4l2_clk_unregister(struct v4l2_clk *clk); +struct v4l2_clk *v4l2_clk_get(struct device *dev, const char *id); +void v4l2_clk_put(struct v4l2_clk *clk); +int v4l2_clk_enable(struct v4l2_clk *clk); +void v4l2_clk_disable(struct v4l2_clk *clk); +unsigned long v4l2_clk_get_rate(struct v4l2_clk *clk); +int v4l2_clk_set_rate(struct v4l2_clk *clk, unsigned long rate); + +#endif diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index 1d93c48cb371..015ff82da73c 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -100,16 +100,6 @@ u32 v4l2_ctrl_next(const u32 * const *ctrl_classes, u32 id); /* ------------------------------------------------------------------------- */ -/* Register/chip ident helper function */ - -struct i2c_client; /* forward reference */ -int v4l2_chip_match_i2c_client(struct i2c_client *c, const struct v4l2_dbg_match *match); -int v4l2_chip_ident_i2c_client(struct i2c_client *c, struct v4l2_dbg_chip_ident *chip, - u32 ident, u32 revision); -int v4l2_chip_match_host(const struct v4l2_dbg_match *match); - -/* ------------------------------------------------------------------------- */ - /* I2C Helper functions */ struct i2c_driver; diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index 95d1c91770f4..c768c9f8abc2 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -96,9 +96,9 @@ struct video_device struct device dev; /* v4l device */ struct cdev *cdev; /* character device */ - /* Set either parent or v4l2_dev if your driver uses v4l2_device */ - struct device *parent; /* device parent */ struct v4l2_device *v4l2_dev; /* v4l2_device parent */ + /* Only set parent if that can't be deduced from v4l2_dev */ + struct device *dev_parent; /* device parent */ /* Control handler associated with this device node. May be NULL. */ struct v4l2_ctrl_handler *ctrl_handler; @@ -129,7 +129,6 @@ struct video_device /* Video standard vars */ v4l2_std_id tvnorms; /* Supported tv norms */ - v4l2_std_id current_norm; /* Current tvnorm */ /* callbacks */ void (*release)(struct video_device *vdev); diff --git a/include/media/v4l2-int-device.h b/include/media/v4l2-int-device.h index e6aa2318367b..0286c95814ff 100644 --- a/include/media/v4l2-int-device.h +++ b/include/media/v4l2-int-device.h @@ -220,8 +220,6 @@ enum v4l2_int_ioctl_num { vidioc_int_reset_num, /* VIDIOC_INT_INIT */ vidioc_int_init_num, - /* VIDIOC_DBG_G_CHIP_IDENT */ - vidioc_int_g_chip_ident_num, /* * @@ -303,6 +301,5 @@ V4L2_INT_WRAPPER_1(enum_frameintervals, struct v4l2_frmivalenum, *); V4L2_INT_WRAPPER_0(reset); V4L2_INT_WRAPPER_0(init); -V4L2_INT_WRAPPER_1(g_chip_ident, int, *); #endif diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h index 931652f0e2af..e0b74a430b3a 100644 --- a/include/media/v4l2-ioctl.h +++ b/include/media/v4l2-ioctl.h @@ -247,8 +247,6 @@ struct v4l2_ioctl_ops { int (*vidioc_g_chip_info) (struct file *file, void *fh, struct v4l2_dbg_chip_info *chip); #endif - int (*vidioc_g_chip_ident) (struct file *file, void *fh, - struct v4l2_dbg_chip_ident *chip); int (*vidioc_enum_framesizes) (struct file *file, void *fh, struct v4l2_frmsizeenum *fsize); diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 5298d678d0f3..3250cc5e7925 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -24,6 +24,7 @@ #include <linux/types.h> #include <linux/v4l2-subdev.h> #include <media/media-entity.h> +#include <media/v4l2-async.h> #include <media/v4l2-common.h> #include <media/v4l2-dev.h> #include <media/v4l2-fh.h> @@ -88,7 +89,6 @@ struct v4l2_decode_vbi_line { /* Core ops: it is highly recommended to implement at least these ops: - g_chip_ident log_status g_register s_register @@ -145,7 +145,6 @@ struct v4l2_subdev_io_pin_config { performed later. It must not sleep. *Called from an IRQ context*. */ struct v4l2_subdev_core_ops { - int (*g_chip_ident)(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip); int (*log_status)(struct v4l2_subdev *sd); int (*s_io_pin_config)(struct v4l2_subdev *sd, size_t n, struct v4l2_subdev_io_pin_config *pincfg); @@ -585,8 +584,17 @@ struct v4l2_subdev { void *host_priv; /* subdev device node */ struct video_device *devnode; + /* pointer to the physical device, if any */ + struct device *dev; + struct v4l2_async_subdev_list asdl; }; +static inline struct v4l2_subdev *v4l2_async_to_subdev( + struct v4l2_async_subdev_list *asdl) +{ + return container_of(asdl, struct v4l2_subdev, asdl); +} + #define media_entity_to_v4l2_subdev(ent) \ container_of(ent, struct v4l2_subdev, entity) #define vdev_to_v4l2_subdev(vdev) \ @@ -660,7 +668,7 @@ void v4l2_subdev_init(struct v4l2_subdev *sd, /* Call an ops of a v4l2_subdev, doing the right checks against NULL pointers. - Example: err = v4l2_subdev_call(sd, core, g_chip_ident, &chip); + Example: err = v4l2_subdev_call(sd, core, s_std, norm); */ #define v4l2_subdev_call(sd, o, f, args...) \ (!(sd) ? -ENODEV : (((sd)->ops->o && (sd)->ops->o->f) ? \ diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index 69bd5bb0d5af..e90a88a8708f 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -53,13 +53,13 @@ #define V4L2_CTRL_CLASS_USER 0x00980000 /* Old-style 'user' controls */ #define V4L2_CTRL_CLASS_MPEG 0x00990000 /* MPEG-compression controls */ #define V4L2_CTRL_CLASS_CAMERA 0x009a0000 /* Camera class controls */ -#define V4L2_CTRL_CLASS_FM_TX 0x009b0000 /* FM Modulator control class */ +#define V4L2_CTRL_CLASS_FM_TX 0x009b0000 /* FM Modulator controls */ #define V4L2_CTRL_CLASS_FLASH 0x009c0000 /* Camera flash controls */ #define V4L2_CTRL_CLASS_JPEG 0x009d0000 /* JPEG-compression controls */ #define V4L2_CTRL_CLASS_IMAGE_SOURCE 0x009e0000 /* Image source controls */ #define V4L2_CTRL_CLASS_IMAGE_PROC 0x009f0000 /* Image processing controls */ #define V4L2_CTRL_CLASS_DV 0x00a00000 /* Digital Video controls */ -#define V4L2_CTRL_CLASS_FM_RX 0x00a10000 /* Digital Video controls */ +#define V4L2_CTRL_CLASS_FM_RX 0x00a10000 /* FM Receiver controls */ /* User-class control IDs */ diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index f40b41c7e108..95ef4551edc1 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -395,7 +395,7 @@ struct v4l2_pix_format { #define V4L2_PIX_FMT_H263 v4l2_fourcc('H', '2', '6', '3') /* H263 */ #define V4L2_PIX_FMT_MPEG1 v4l2_fourcc('M', 'P', 'G', '1') /* MPEG-1 ES */ #define V4L2_PIX_FMT_MPEG2 v4l2_fourcc('M', 'P', 'G', '2') /* MPEG-2 ES */ -#define V4L2_PIX_FMT_MPEG4 v4l2_fourcc('M', 'P', 'G', '4') /* MPEG-4 ES */ +#define V4L2_PIX_FMT_MPEG4 v4l2_fourcc('M', 'P', 'G', '4') /* MPEG-4 part 2 ES */ #define V4L2_PIX_FMT_XVID v4l2_fourcc('X', 'V', 'I', 'D') /* Xvid */ #define V4L2_PIX_FMT_VC1_ANNEX_G v4l2_fourcc('V', 'C', '1', 'G') /* SMPTE 421M Annex G compliant stream */ #define V4L2_PIX_FMT_VC1_ANNEX_L v4l2_fourcc('V', 'C', '1', 'L') /* SMPTE 421M Annex L compliant stream */ @@ -555,7 +555,7 @@ struct v4l2_jpegcompression { __u32 jpeg_markers; /* Which markers should go into the JPEG * output. Unless you exactly know what * you do, leave them untouched. - * Inluding less markers will make the + * Including less markers will make the * resulting code smaller, but there will * be fewer applications which can read it. * The presence of the APP and COM marker @@ -567,7 +567,7 @@ struct v4l2_jpegcompression { #define V4L2_JPEG_MARKER_DRI (1<<5) /* Define Restart Interval */ #define V4L2_JPEG_MARKER_COM (1<<6) /* Comment segment */ #define V4L2_JPEG_MARKER_APP (1<<7) /* App segment, driver will - * allways use APP0 */ + * always use APP0 */ }; /* @@ -900,7 +900,7 @@ typedef __u64 v4l2_std_id; /* * "Common" PAL - This macro is there to be compatible with the old * V4L1 concept of "PAL": /BGDKHI. - * Several PAL standards are mising here: /M, /N and /Nc + * Several PAL standards are missing here: /M, /N and /Nc */ #define V4L2_STD_PAL (V4L2_STD_PAL_BG |\ V4L2_STD_PAL_DK |\ @@ -1787,11 +1787,13 @@ struct v4l2_event_subscription { /* VIDIOC_DBG_G_REGISTER and VIDIOC_DBG_S_REGISTER */ #define V4L2_CHIP_MATCH_BRIDGE 0 /* Match against chip ID on the bridge (0 for the bridge) */ +#define V4L2_CHIP_MATCH_SUBDEV 4 /* Match against subdev index */ + +/* The following four defines are no longer in use */ #define V4L2_CHIP_MATCH_HOST V4L2_CHIP_MATCH_BRIDGE #define V4L2_CHIP_MATCH_I2C_DRIVER 1 /* Match against I2C driver name */ #define V4L2_CHIP_MATCH_I2C_ADDR 2 /* Match against I2C 7-bit address */ -#define V4L2_CHIP_MATCH_AC97 3 /* Match against anciliary AC97 chip */ -#define V4L2_CHIP_MATCH_SUBDEV 4 /* Match against subdev index */ +#define V4L2_CHIP_MATCH_AC97 3 /* Match against ancillary AC97 chip */ struct v4l2_dbg_match { __u32 type; /* Match type */ @@ -1808,13 +1810,6 @@ struct v4l2_dbg_register { __u64 val; } __attribute__ ((packed)); -/* VIDIOC_DBG_G_CHIP_IDENT */ -struct v4l2_dbg_chip_ident { - struct v4l2_dbg_match match; - __u32 ident; /* chip identifier as specified in <media/v4l2-chip-ident.h> */ - __u32 revision; /* chip revision, chip specific */ -} __attribute__ ((packed)); - #define V4L2_CHIP_FL_READABLE (1 << 0) #define V4L2_CHIP_FL_WRITABLE (1 << 1) @@ -1915,12 +1910,6 @@ struct v4l2_create_buffers { #define VIDIOC_DBG_S_REGISTER _IOW('V', 79, struct v4l2_dbg_register) #define VIDIOC_DBG_G_REGISTER _IOWR('V', 80, struct v4l2_dbg_register) -/* Experimental, meant for debugging, testing and internal use. - Never use this ioctl in applications! - Note: this ioctl is deprecated in favor of VIDIOC_DBG_G_CHIP_INFO and - will go away in the future. */ -#define VIDIOC_DBG_G_CHIP_IDENT _IOWR('V', 81, struct v4l2_dbg_chip_ident) - #define VIDIOC_S_HW_FREQ_SEEK _IOW('V', 82, struct v4l2_hw_freq_seek) #define VIDIOC_S_DV_TIMINGS _IOWR('V', 87, struct v4l2_dv_timings) |