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
  ...
This commit is contained in:
Linus Torvalds 2013-07-13 12:09:57 -07:00
commit 858655116b
359 changed files with 10926 additions and 9886 deletions

View File

@ -77,7 +77,7 @@ Description: Read/Write attribute file that controls memory scrubbing.
What: /sys/devices/system/edac/mc/mc*/max_location What: /sys/devices/system/edac/mc/mc*/max_location
Date: April 2012 Date: April 2012
Contact: Mauro Carvalho Chehab <mchehab@redhat.com> Contact: Mauro Carvalho Chehab <m.chehab@samsung.com>
linux-edac@vger.kernel.org linux-edac@vger.kernel.org
Description: This attribute file displays the information about the last Description: This attribute file displays the information about the last
available memory slot in this memory controller. It is used by 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 What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/size
Date: April 2012 Date: April 2012
Contact: Mauro Carvalho Chehab <mchehab@redhat.com> Contact: Mauro Carvalho Chehab <m.chehab@samsung.com>
linux-edac@vger.kernel.org linux-edac@vger.kernel.org
Description: This attribute file will display the size of dimm or rank. 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 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 What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_dev_type
Date: April 2012 Date: April 2012
Contact: Mauro Carvalho Chehab <mchehab@redhat.com> Contact: Mauro Carvalho Chehab <m.chehab@samsung.com>
linux-edac@vger.kernel.org linux-edac@vger.kernel.org
Description: This attribute file will display what type of DRAM device is Description: This attribute file will display what type of DRAM device is
being utilized on this DIMM (x1, x2, x4, x8, ...). being utilized on this DIMM (x1, x2, x4, x8, ...).
What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_edac_mode What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_edac_mode
Date: April 2012 Date: April 2012
Contact: Mauro Carvalho Chehab <mchehab@redhat.com> Contact: Mauro Carvalho Chehab <m.chehab@samsung.com>
linux-edac@vger.kernel.org linux-edac@vger.kernel.org
Description: This attribute file will display what type of Error detection Description: This attribute file will display what type of Error detection
and correction is being utilized. For example: S4ECD4ED would 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 What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_label
Date: April 2012 Date: April 2012
Contact: Mauro Carvalho Chehab <mchehab@redhat.com> Contact: Mauro Carvalho Chehab <m.chehab@samsung.com>
linux-edac@vger.kernel.org linux-edac@vger.kernel.org
Description: This control file allows this DIMM to have a label assigned Description: This control file allows this DIMM to have a label assigned
to it. With this label in the module, when errors occur 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 What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_location
Date: April 2012 Date: April 2012
Contact: Mauro Carvalho Chehab <mchehab@redhat.com> Contact: Mauro Carvalho Chehab <m.chehab@samsung.com>
linux-edac@vger.kernel.org linux-edac@vger.kernel.org
Description: This attribute file will display the location (csrow/channel, Description: This attribute file will display the location (csrow/channel,
branch/channel/slot or channel/slot) of the dimm or rank. branch/channel/slot or channel/slot) of the dimm or rank.
What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_mem_type What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_mem_type
Date: April 2012 Date: April 2012
Contact: Mauro Carvalho Chehab <mchehab@redhat.com> Contact: Mauro Carvalho Chehab <m.chehab@samsung.com>
linux-edac@vger.kernel.org linux-edac@vger.kernel.org
Description: This attribute file will display what type of memory is Description: This attribute file will display what type of memory is
currently on this csrow. Normally, either buffered or currently on this csrow. Normally, either buffered or

View File

@ -2254,7 +2254,7 @@ video encoding.</para>
<orderedlist> <orderedlist>
<listitem> <listitem>
<para>The <constant>VIDIOC_G_CHIP_IDENT</constant> ioctl was renamed <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 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> was renamed to <structname id="v4l2-chip-ident-old">v4l2_chip_ident_old</structname>.</para>
</listitem> </listitem>
@ -2513,6 +2513,16 @@ that used it. It was originally scheduled for removal in 2.6.35.
</orderedlist> </orderedlist>
</section> </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"> <section id="other">
<title>Relation of V4L2 to other Linux multimedia APIs</title> <title>Relation of V4L2 to other Linux multimedia APIs</title>
@ -2596,7 +2606,7 @@ and may change in the future.</para>
ioctls.</para> ioctls.</para>
</listitem> </listitem>
<listitem> <listitem>
<para>&VIDIOC-DBG-G-CHIP-IDENT; ioctl.</para> <para>&VIDIOC-DBG-G-CHIP-INFO; ioctl.</para>
</listitem> </listitem>
<listitem> <listitem>
<para>&VIDIOC-ENUM-DV-TIMINGS;, &VIDIOC-QUERY-DV-TIMINGS; and <para>&VIDIOC-ENUM-DV-TIMINGS;, &VIDIOC-QUERY-DV-TIMINGS; and

View File

@ -140,6 +140,14 @@ structs, ioctls) must be noted in more detail in the history chapter
(compat.xml), along with the possible impact on existing drivers and (compat.xml), along with the possible impact on existing drivers and
applications. --> 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> <revision>
<revnumber>3.10</revnumber> <revnumber>3.10</revnumber>
<date>2013-03-25</date> <date>2013-03-25</date>
@ -493,7 +501,7 @@ and discussions on the V4L mailing list.</revremark>
</partinfo> </partinfo>
<title>Video for Linux Two API Specification</title> <title>Video for Linux Two API Specification</title>
<subtitle>Revision 3.10</subtitle> <subtitle>Revision 3.11</subtitle>
<chapter id="common"> <chapter id="common">
&sub-common; &sub-common;
@ -547,7 +555,6 @@ and discussions on the V4L mailing list.</revremark>
<!-- All ioctls go here. --> <!-- All ioctls go here. -->
&sub-create-bufs; &sub-create-bufs;
&sub-cropcap; &sub-cropcap;
&sub-dbg-g-chip-ident;
&sub-dbg-g-chip-info; &sub-dbg-g-chip-info;
&sub-dbg-g-register; &sub-dbg-g-register;
&sub-decoder-cmd; &sub-decoder-cmd;

View File

@ -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, &eg; 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>

View File

@ -73,8 +73,7 @@ fields of a &v4l2-dbg-chip-info;
and call <constant>VIDIOC_DBG_G_CHIP_INFO</constant> with a pointer to and call <constant>VIDIOC_DBG_G_CHIP_INFO</constant> with a pointer to
this structure. On success the driver stores information about the this structure. On success the driver stores information about the
selected chip in the <structfield>name</structfield> and selected chip in the <structfield>name</structfield> and
<structfield>flags</structfield> fields. On failure the structure <structfield>flags</structfield> fields.</para>
remains unchanged.</para>
<para>When <structfield>match.type</structfield> is <para>When <structfield>match.type</structfield> is
<constant>V4L2_CHIP_MATCH_BRIDGE</constant>, <constant>V4L2_CHIP_MATCH_BRIDGE</constant>,
@ -132,7 +131,7 @@ to the <structfield>type</structfield> field.</entry>
<entry>char</entry> <entry>char</entry>
<entry><structfield>name[32]</structfield></entry> <entry><structfield>name[32]</structfield></entry>
<entry>Match a chip by this name, interpreted according <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> </row>
</tbody> </tbody>
</tgroup> </tgroup>
@ -182,21 +181,6 @@ is set, then the driver supports reading registers from the device. If
<entry>Match the nth chip on the card, zero for the <entry>Match the nth chip on the card, zero for the
bridge chip. Does not match sub-devices.</entry> bridge chip. Does not match sub-devices.</entry>
</row> </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> <row>
<entry><constant>V4L2_CHIP_MATCH_SUBDEV</constant></entry> <entry><constant>V4L2_CHIP_MATCH_SUBDEV</constant></entry>
<entry>4</entry> <entry>4</entry>

View File

@ -76,7 +76,7 @@ compiled with the <constant>CONFIG_VIDEO_ADV_DEBUG</constant> option
to enable these ioctls.</para> to enable these ioctls.</para>
<para>To write a register applications must initialize all fields <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 <constant>VIDIOC_DBG_S_REGISTER</constant> with a pointer to this
structure. The <structfield>match.type</structfield> and structure. The <structfield>match.type</structfield> and
<structfield>match.addr</structfield> or <structfield>match.name</structfield> <structfield>match.addr</structfield> or <structfield>match.name</structfield>
@ -91,8 +91,8 @@ written into the register.</para>
<structfield>reg</structfield> fields, and call <structfield>reg</structfield> fields, and call
<constant>VIDIOC_DBG_G_REGISTER</constant> with a pointer to this <constant>VIDIOC_DBG_G_REGISTER</constant> with a pointer to this
structure. On success the driver stores the register value in the structure. On success the driver stores the register value in the
<structfield>val</structfield> field. On failure the structure remains <structfield>val</structfield> field and the size (in bytes) of the
unchanged.</para> value in <structfield>size</structfield>.</para>
<para>When <structfield>match.type</structfield> is <para>When <structfield>match.type</structfield> is
<constant>V4L2_CHIP_MATCH_BRIDGE</constant>, <constant>V4L2_CHIP_MATCH_BRIDGE</constant>,
@ -101,40 +101,10 @@ on the TV card. The number zero always selects the host chip, &eg; the
chip connected to the PCI or USB bus. You can find out which chips are 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> 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 <para>When <structfield>match.type</structfield> is
<constant>V4L2_CHIP_MATCH_SUBDEV</constant>, <constant>V4L2_CHIP_MATCH_SUBDEV</constant>,
<structfield>match.addr</structfield> selects the nth sub-device.</para> <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. <para>These ioctls are optional, not all drivers may support them.
However when a driver supports these ioctls it must also support However when a driver supports these ioctls it must also support
&VIDIOC-DBG-G-CHIP-INFO;. Conversely it may 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 url="http://linuxtv.org/repo/">http://linuxtv.org/repo/</ulink> for
access instructions.</para> 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. --> contains a duplicate of this table. -->
<table pgwide="1" frame="none" id="v4l2-dbg-match"> <table pgwide="1" frame="none" id="v4l2-dbg-match">
<title>struct <structname>v4l2_dbg_match</structname></title> <title>struct <structname>v4l2_dbg_match</structname></title>
@ -160,7 +130,7 @@ access instructions.</para>
<row> <row>
<entry>__u32</entry> <entry>__u32</entry>
<entry><structfield>type</structfield></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> possible types.</entry>
</row> </row>
<row> <row>
@ -179,7 +149,7 @@ to the <structfield>type</structfield> field.</entry>
<entry>char</entry> <entry>char</entry>
<entry><structfield>name[32]</structfield></entry> <entry><structfield>name[32]</structfield></entry>
<entry>Match a chip by this name, interpreted according <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> </row>
</tbody> </tbody>
</tgroup> </tgroup>
@ -198,6 +168,11 @@ to the <structfield>type</structfield> field.</entry>
<entry><structfield>match</structfield></entry> <entry><structfield>match</structfield></entry>
<entry>How to match the chip, see <xref linkend="v4l2-dbg-match" />.</entry> <entry>How to match the chip, see <xref linkend="v4l2-dbg-match" />.</entry>
</row> </row>
<row>
<entry>__u32</entry>
<entry><structfield>size</structfield></entry>
<entry>The register size in bytes.</entry>
</row>
<row> <row>
<entry>__u64</entry> <entry>__u64</entry>
<entry><structfield>reg</structfield></entry> <entry><structfield>reg</structfield></entry>
@ -213,7 +188,7 @@ register.</entry>
</tgroup> </tgroup>
</table> </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. --> contains a duplicate of this table. -->
<table pgwide="1" frame="none" id="chip-match-types"> <table pgwide="1" frame="none" id="chip-match-types">
<title>Chip Match Types</title> <title>Chip Match Types</title>
@ -226,21 +201,6 @@ register.</entry>
<entry>Match the nth chip on the card, zero for the <entry>Match the nth chip on the card, zero for the
bridge chip. Does not match sub-devices.</entry> bridge chip. Does not match sub-devices.</entry>
</row> </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> <row>
<entry><constant>V4L2_CHIP_MATCH_SUBDEV</constant></entry> <entry><constant>V4L2_CHIP_MATCH_SUBDEV</constant></entry>
<entry>4</entry> <entry>4</entry>

View File

@ -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 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 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 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 possible or fails, the set must contain all standards supported by the
current video input or output.</para> current video input or output.</para>

View File

@ -2,8 +2,10 @@ Exynos4x12/Exynos5 SoC series camera host interface (FIMC-LITE)
Required properties: Required properties:
- compatible : should be "samsung,exynos4212-fimc-lite" for Exynos4212 and - compatible : should be one of:
Exynos4412 SoCs; "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 - reg : physical base address and size of the device memory mapped
registers; registers;
- interrupts : should contain FIMC-LITE interrupt; - interrupts : should contain FIMC-LITE interrupt;

View File

@ -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>;
};
};
};
...
};

View File

@ -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>;
};
};
};
...
};

View File

@ -127,22 +127,22 @@ Example:
}; };
}; };
}; };
};
/* MIPI CSI-2 bus IF sensor */ /* MIPI CSI-2 bus IF sensor */
s5c73m3: sensor@0x1a { s5c73m3: sensor@0x1a {
compatible = "samsung,s5c73m3"; compatible = "samsung,s5c73m3";
reg = <0x1a>; reg = <0x1a>;
vddio-supply = <...>; vddio-supply = <...>;
clock-frequency = <24000000>; clock-frequency = <24000000>;
clocks = <...>; clocks = <...>;
clock-names = "mclk"; clock-names = "mclk";
port { port {
s5c73m3_1: endpoint { s5c73m3_1: endpoint {
data-lanes = <1 2 3 4>; data-lanes = <1 2 3 4>;
remote-endpoint = <&csis0_ep>; remote-endpoint = <&csis0_ep>;
};
}; };
}; };
}; };

View File

@ -5,8 +5,8 @@ Required properties:
- compatible : "samsung,s5pv210-csis" for S5PV210 (S5PC110), - compatible : "samsung,s5pv210-csis" for S5PV210 (S5PC110),
"samsung,exynos4210-csis" for Exynos4210 (S5PC210), "samsung,exynos4210-csis" for Exynos4210 (S5PC210),
"samsung,exynos4212-csis" for Exynos4212/Exynos4412 "samsung,exynos4212-csis" for Exynos4212/Exynos4412,
SoC series; "samsung,exynos5250-csis" for Exynos5250;
- reg : offset and length of the register set for the device; - reg : offset and length of the register set for the device;
- interrupts : should contain MIPI CSIS interrupt; the format of the - interrupts : should contain MIPI CSIS interrupt; the format of the
interrupt specifier depends on the interrupt controller; interrupt specifier depends on the interrupt controller;

View File

@ -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>;
};

View File

@ -265,7 +265,7 @@ connected to another pad through an enabled link
media_entity_find_link(struct media_pad *source, media_entity_find_link(struct media_pad *source,
struct media_pad *sink); 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. Refer to the kerneldoc documentation for more information.

View File

@ -160,3 +160,6 @@
159 -> ProVideo PV183 [1830:1540,1831:1540,1832:1540,1833:1540,1834:1540,1835:1540,1836:1540,1837:1540] 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] 160 -> Tongwei Video Technology TD-3116 [f200:3116]
161 -> Aposonic W-DVR [0279:0228] 161 -> Aposonic W-DVR [0279:0228]
162 -> Adlink MPG24
163 -> Bt848 Capture 14MHz
164 -> CyberVision CV06 (SV)

View File

@ -190,3 +190,4 @@
189 -> Kworld PC150-U [17de:a134] 189 -> Kworld PC150-U [17de:a134]
190 -> Asus My Cinema PS3-100 [1043:48cd] 190 -> Asus My Cinema PS3-100 [1043:48cd]
191 -> Hawell HW-9004V1 191 -> Hawell HW-9004V1
192 -> AverMedia AverTV Satellite Hybrid+FM A706 [1461:2055]

View File

@ -86,6 +86,6 @@ tuner=85 - Philips FQ1236 MK5
tuner=86 - Tena TNF5337 MFD tuner=86 - Tena TNF5337 MFD
tuner=87 - Xceive 4000 tuner tuner=87 - Xceive 4000 tuner
tuner=88 - Xceive 5000C tuner tuner=88 - Xceive 5000C tuner
tuner=89 - Sony PAL+SECAM (BTF-PG472Z) tuner=89 - Sony BTF-PG472Z PAL/SECAM
tuner=90 - Sony NTSC-M-JP (BTF-PK467Z) tuner=90 - Sony BTF-PK467Z NTSC-M-JP
tuner=91 - Sony NTSC-M (BTF-PB463Z) tuner=91 - Sony BTF-PB463Z NTSC-M

View File

@ -1,6 +1,6 @@
Samsung S5P/EXYNOS4 FIMC driver 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 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 path. There are multiple FIMC instances in the SoCs (up to 4), having
slightly different capabilities, like pixel alignment constraints, rotator slightly different capabilities, like pixel alignment constraints, rotator
availability, LCD writeback support, etc. The driver is located at 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 1. Supported SoCs
================= =================
@ -36,21 +36,21 @@ Not currently supported:
===================== =====================
- media device driver - media device driver
drivers/media/platform/s5p-fimc/fimc-mdevice.[ch] drivers/media/platform/exynos4-is/media-dev.[ch]
- camera capture video device driver - 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 - 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) - video post-processor (mem-to-mem)
drivers/media/platform/s5p-fimc/fimc-core.c drivers/media/platform/exynos4-is/fimc-core.c
- common files - common files
drivers/media/platform/s5p-fimc/fimc-core.h drivers/media/platform/exynos4-is/fimc-core.h
drivers/media/platform/s5p-fimc/fimc-reg.h drivers/media/platform/exynos4-is/fimc-reg.h
drivers/media/platform/s5p-fimc/regs-fimc.h drivers/media/platform/exynos4-is/regs-fimc.h
4. User space interfaces 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 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_FIMC0 mandatory
CONFIG_S5P_DEV_FIMC1 \ CONFIG_S5P_DEV_FIMC1 \

View File

@ -246,7 +246,6 @@ may be NULL if the subdev driver does not support anything from that category.
It looks like this: It looks like this:
struct v4l2_subdev_core_ops { 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 (*log_status)(struct v4l2_subdev *sd);
int (*init)(struct v4l2_subdev *sd, u32 val); 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 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. perform the checks mentioned above in addition to their own checks.
A device (bridge) driver needs to register the v4l2_subdev with the There are currently two ways to register subdevices with the V4L2 core. The
v4l2_device: 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); 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: 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: 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 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 is NULL, -ENOIOCTLCMD if either subdev->core or subdev->core->g_std is
NULL, or the actual result of the subdev->ops->core->g_chip_ident ops. 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: 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 Any subdev that does not support this ops is skipped and error results are
ignored. If you want to check for errors use this: 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 Any error except -ENOIOCTLCMD will exit the loop with that error. If no
errors (except -ENOIOCTLCMD) occurred, then 0 is returned. 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. 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 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 The default video_device_release() callback just calls kfree to free the
allocated memory. 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: 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. - 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), 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. 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 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. 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 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 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 a particular (cx8802). Since the v4l2_device cannot be associated with two PCI devices
PCI device it is setup without a parent device. But when the struct at the same time it is setup without a parent device. But when the struct
video_device is setup you do know which parent PCI device to use. 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 - 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 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 An example on how the V4L2 events may be used can be found in the OMAP
3 ISP driver (drivers/media/platform/omap3isp). 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.

View File

@ -247,7 +247,6 @@ i2c_client 结构体i2c_set_clientdata() 函数可用于保存一个 v4l2_sub
这些结构体定义如下: 这些结构体定义如下:
struct v4l2_subdev_core_ops { 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 (*log_status)(struct v4l2_subdev *sd);
int (*init)(struct v4l2_subdev *sd, u32 val); 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如果 这个宏将会做 NULL 指针检查,如果 subdev 为 NULL则返回-ENODEV如果
subdev->core 或 subdev->core->g_chip_ident 为 NULL则返回 -ENOIOCTLCMD subdev->core 或 subdev->core->g_std 为 NULL则返回 -ENOIOCTLCMD
否则将返回 subdev->ops->core->g_chip_ident ops 调用的实际结果。 否则将返回 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 除 -ENOIOCTLCMD 外的任何错误都会跳出循环并返回错误值。如果(除 -ENOIOCTLCMD
外)没有错误发生,则返回 0。 外)没有错误发生,则返回 0。

View File

@ -1165,15 +1165,6 @@ L: linux-media@vger.kernel.org
S: Maintained S: Maintained
F: drivers/media/platform/s5p-g2d/ 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 ARM/SAMSUNG S5P SERIES Multi Format Codec (MFC) SUPPORT
M: Kyungmin Park <kyungmin.park@samsung.com> M: Kyungmin Park <kyungmin.park@samsung.com>
M: Kamil Debski <k.debski@samsung.com> M: Kamil Debski <k.debski@samsung.com>
@ -1595,7 +1586,7 @@ F: include/net/ax25.h
F: net/ax25/ F: net/ax25/
AZ6007 DVB DRIVER AZ6007 DVB DRIVER
M: Mauro Carvalho Chehab <mchehab@redhat.com> M: Mauro Carvalho Chehab <m.chehab@samsung.com>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
W: http://linuxtv.org W: http://linuxtv.org
T: git git://linuxtv.org/media_tree.git T: git git://linuxtv.org/media_tree.git
@ -1880,7 +1871,7 @@ F: Documentation/filesystems/btrfs.txt
F: fs/btrfs/ F: fs/btrfs/
BTTV VIDEO4LINUX DRIVER BTTV VIDEO4LINUX DRIVER
M: Mauro Carvalho Chehab <mchehab@redhat.com> M: Mauro Carvalho Chehab <m.chehab@samsung.com>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
W: http://linuxtv.org W: http://linuxtv.org
T: git git://linuxtv.org/media_tree.git T: git git://linuxtv.org/media_tree.git
@ -2368,7 +2359,7 @@ F: drivers/media/common/cx2341x*
F: include/media/cx2341x* F: include/media/cx2341x*
CX88 VIDEO4LINUX DRIVER CX88 VIDEO4LINUX DRIVER
M: Mauro Carvalho Chehab <mchehab@redhat.com> M: Mauro Carvalho Chehab <m.chehab@samsung.com>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
W: http://linuxtv.org W: http://linuxtv.org
T: git git://linuxtv.org/media_tree.git T: git git://linuxtv.org/media_tree.git
@ -2990,7 +2981,7 @@ S: Maintained
F: drivers/edac/e7xxx_edac.c F: drivers/edac/e7xxx_edac.c
EDAC-GHES EDAC-GHES
M: Mauro Carvalho Chehab <mchehab@redhat.com> M: Mauro Carvalho Chehab <m.chehab@samsung.com>
L: linux-edac@vger.kernel.org L: linux-edac@vger.kernel.org
W: bluesmoke.sourceforge.net W: bluesmoke.sourceforge.net
S: Maintained S: Maintained
@ -3018,21 +3009,21 @@ S: Maintained
F: drivers/edac/i5000_edac.c F: drivers/edac/i5000_edac.c
EDAC-I5400 EDAC-I5400
M: Mauro Carvalho Chehab <mchehab@redhat.com> M: Mauro Carvalho Chehab <m.chehab@samsung.com>
L: linux-edac@vger.kernel.org L: linux-edac@vger.kernel.org
W: bluesmoke.sourceforge.net W: bluesmoke.sourceforge.net
S: Maintained S: Maintained
F: drivers/edac/i5400_edac.c F: drivers/edac/i5400_edac.c
EDAC-I7300 EDAC-I7300
M: Mauro Carvalho Chehab <mchehab@redhat.com> M: Mauro Carvalho Chehab <m.chehab@samsung.com>
L: linux-edac@vger.kernel.org L: linux-edac@vger.kernel.org
W: bluesmoke.sourceforge.net W: bluesmoke.sourceforge.net
S: Maintained S: Maintained
F: drivers/edac/i7300_edac.c F: drivers/edac/i7300_edac.c
EDAC-I7CORE EDAC-I7CORE
M: Mauro Carvalho Chehab <mchehab@redhat.com> M: Mauro Carvalho Chehab <m.chehab@samsung.com>
L: linux-edac@vger.kernel.org L: linux-edac@vger.kernel.org
W: bluesmoke.sourceforge.net W: bluesmoke.sourceforge.net
S: Maintained S: Maintained
@ -3061,7 +3052,7 @@ S: Maintained
F: drivers/edac/r82600_edac.c F: drivers/edac/r82600_edac.c
EDAC-SBRIDGE EDAC-SBRIDGE
M: Mauro Carvalho Chehab <mchehab@redhat.com> M: Mauro Carvalho Chehab <m.chehab@samsung.com>
L: linux-edac@vger.kernel.org L: linux-edac@vger.kernel.org
W: bluesmoke.sourceforge.net W: bluesmoke.sourceforge.net
S: Maintained S: Maintained
@ -3121,7 +3112,7 @@ S: Maintained
F: drivers/net/ethernet/ibm/ehea/ F: drivers/net/ethernet/ibm/ehea/
EM28XX VIDEO4LINUX DRIVER EM28XX VIDEO4LINUX DRIVER
M: Mauro Carvalho Chehab <mchehab@redhat.com> M: Mauro Carvalho Chehab <m.chehab@samsung.com>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
W: http://linuxtv.org W: http://linuxtv.org
T: git git://linuxtv.org/media_tree.git T: git git://linuxtv.org/media_tree.git
@ -5317,7 +5308,7 @@ S: Maintained
F: drivers/media/radio/radio-maxiradio* F: drivers/media/radio/radio-maxiradio*
MEDIA INPUT INFRASTRUCTURE (V4L/DVB) MEDIA INPUT INFRASTRUCTURE (V4L/DVB)
M: Mauro Carvalho Chehab <mchehab@redhat.com> M: Mauro Carvalho Chehab <m.chehab@samsung.com>
P: LinuxTV.org Project P: LinuxTV.org Project
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
W: http://linuxtv.org W: http://linuxtv.org
@ -7013,7 +7004,7 @@ S: Odd Fixes
F: drivers/media/i2c/saa6588* F: drivers/media/i2c/saa6588*
SAA7134 VIDEO4LINUX DRIVER SAA7134 VIDEO4LINUX DRIVER
M: Mauro Carvalho Chehab <mchehab@redhat.com> M: Mauro Carvalho Chehab <m.chehab@samsung.com>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
W: http://linuxtv.org W: http://linuxtv.org
T: git git://linuxtv.org/media_tree.git T: git git://linuxtv.org/media_tree.git
@ -7058,6 +7049,15 @@ F: drivers/regulator/s5m*.c
F: drivers/rtc/rtc-sec.c F: drivers/rtc/rtc-sec.c
F: include/linux/mfd/samsung/ 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 SAMSUNG S3C24XX/S3C64XX SOC SERIES CAMIF DRIVER
M: Sylwester Nawrocki <sylvester.nawrocki@gmail.com> M: Sylwester Nawrocki <sylvester.nawrocki@gmail.com>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
@ -7375,7 +7375,7 @@ S: Odd Fixes
F: drivers/media/radio/radio-si4713.h F: drivers/media/radio/radio-si4713.h
SIANO DVB DRIVER SIANO DVB DRIVER
M: Mauro Carvalho Chehab <mchehab@redhat.com> M: Mauro Carvalho Chehab <m.chehab@samsung.com>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
W: http://linuxtv.org W: http://linuxtv.org
T: git git://linuxtv.org/media_tree.git T: git git://linuxtv.org/media_tree.git
@ -8080,7 +8080,7 @@ S: Maintained
F: drivers/media/i2c/tda9840* F: drivers/media/i2c/tda9840*
TEA5761 TUNER DRIVER TEA5761 TUNER DRIVER
M: Mauro Carvalho Chehab <mchehab@redhat.com> M: Mauro Carvalho Chehab <m.chehab@samsung.com>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
W: http://linuxtv.org W: http://linuxtv.org
T: git git://linuxtv.org/media_tree.git T: git git://linuxtv.org/media_tree.git
@ -8088,7 +8088,7 @@ S: Odd fixes
F: drivers/media/tuners/tea5761.* F: drivers/media/tuners/tea5761.*
TEA5767 TUNER DRIVER TEA5767 TUNER DRIVER
M: Mauro Carvalho Chehab <mchehab@redhat.com> M: Mauro Carvalho Chehab <m.chehab@samsung.com>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
W: http://linuxtv.org W: http://linuxtv.org
T: git git://linuxtv.org/media_tree.git T: git git://linuxtv.org/media_tree.git
@ -8327,7 +8327,7 @@ F: include/linux/shmem_fs.h
F: mm/shmem.c F: mm/shmem.c
TM6000 VIDEO4LINUX DRIVER TM6000 VIDEO4LINUX DRIVER
M: Mauro Carvalho Chehab <mchehab@redhat.com> M: Mauro Carvalho Chehab <m.chehab@samsung.com>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
W: http://linuxtv.org W: http://linuxtv.org
T: git git://linuxtv.org/media_tree.git T: git git://linuxtv.org/media_tree.git
@ -9184,7 +9184,7 @@ S: Maintained
F: arch/x86/kernel/cpu/mcheck/* F: arch/x86/kernel/cpu/mcheck/*
XC2028/3028 TUNER DRIVER 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 L: linux-media@vger.kernel.org
W: http://linuxtv.org W: http://linuxtv.org
T: git git://linuxtv.org/media_tree.git T: git git://linuxtv.org/media_tree.git

View File

@ -509,7 +509,6 @@ struct ths7303_platform_data ths7303_pdata = {
.ch_1 = 3, .ch_1 = 3,
.ch_2 = 3, .ch_2 = 3,
.ch_3 = 3, .ch_3 = 3,
.init_enable = 1,
}; };
static struct amp_config_info vpbe_amp = { static struct amp_config_info vpbe_amp = {

View File

@ -680,10 +680,7 @@ int dma_buf_debugfs_create_file(const char *name,
d = debugfs_create_file(name, S_IRUGO, dma_buf_debugfs_dir, d = debugfs_create_file(name, S_IRUGO, dma_buf_debugfs_dir,
write, &dma_buf_debug_fops); write, &dma_buf_debug_fops);
if (IS_ERR(d)) return PTR_RET(d);
return PTR_ERR(d);
return 0;
} }
#else #else
static inline int dma_buf_init_debugfs(void) static inline int dma_buf_init_debugfs(void)

View File

@ -1,7 +1,6 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <media/saa7146_vv.h> #include <media/saa7146_vv.h>
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-event.h> #include <media/v4l2-event.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <linux/module.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; 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 = { const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = {
.vidioc_querycap = vidioc_querycap, .vidioc_querycap = vidioc_querycap,
.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, .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_g_fmt_vid_overlay = vidioc_g_fmt_vid_overlay,
.vidioc_try_fmt_vid_overlay = vidioc_try_fmt_vid_overlay, .vidioc_try_fmt_vid_overlay = vidioc_try_fmt_vid_overlay,
.vidioc_s_fmt_vid_overlay = vidioc_s_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_overlay = vidioc_overlay,
.vidioc_g_fbuf = vidioc_g_fbuf, .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 = { const struct v4l2_ioctl_ops saa7146_vbi_ioctl_ops = {
.vidioc_querycap = vidioc_querycap, .vidioc_querycap = vidioc_querycap,
.vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap, .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
.vidioc_g_chip_ident = vidioc_g_chip_ident,
.vidioc_reqbufs = vidioc_reqbufs, .vidioc_reqbufs = vidioc_reqbufs,
.vidioc_querybuf = vidioc_querybuf, .vidioc_querybuf = vidioc_querybuf,

View File

@ -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); char *fw_filename = smscore_get_fw_filename(coredev, mode);
if (!fw_filename) { 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; return -ENOENT;
} }
sms_debug("Firmware name: %s", fw_filename); 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); rc = request_firmware(&fw, fw_filename, coredev->device);
if (rc < 0) { if (rc < 0) {
sms_info("failed to open \"%s\"", fw_filename); sms_err("failed to open firmware file \"%s\"", fw_filename);
return rc; return rc;
} }
sms_info("read fw %s, buffer size=0x%zx", fw_filename, fw->size); sms_info("read fw %s, buffer size=0x%zx", fw_filename, fw->size);
fw_buf = kmalloc(ALIGN(fw->size, SMS_ALLOC_ALIGNMENT), fw_buf = kmalloc(ALIGN(fw->size, SMS_ALLOC_ALIGNMENT),
GFP_KERNEL | GFP_DMA); GFP_KERNEL | GFP_DMA);
if (!fw_buf) { if (!fw_buf) {
sms_info("failed to allocate firmware buffer"); sms_err("failed to allocate firmware buffer");
return -ENOMEM; rc = -ENOMEM;
} } else {
memcpy(fw_buf, fw->data, fw->size); memcpy(fw_buf, fw->data, fw->size);
fw_buf_size = fw->size; fw_buf_size = fw->size;
rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ? rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ?
smscore_load_firmware_family2(coredev, fw_buf, fw_buf_size) smscore_load_firmware_family2(coredev, fw_buf, fw_buf_size)
: loadfirmware_handler(coredev->context, fw_buf, : loadfirmware_handler(coredev->context, fw_buf,
fw_buf_size); fw_buf_size);
}
kfree(fw_buf); kfree(fw_buf);
release_firmware(fw); release_firmware(fw);

View File

@ -140,6 +140,7 @@ static void smsdvb_stats_not_ready(struct dvb_frontend *fe)
case DEVICE_MODE_ISDBT: case DEVICE_MODE_ISDBT:
case DEVICE_MODE_ISDBT_BDA: case DEVICE_MODE_ISDBT_BDA:
n_layers = 4; n_layers = 4;
break;
default: default:
n_layers = 1; n_layers = 1;
} }

View File

@ -40,7 +40,6 @@
#include <media/tuner.h> #include <media/tuner.h>
#include <media/tveeprom.h> #include <media/tveeprom.h>
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include <media/v4l2-chip-ident.h>
MODULE_DESCRIPTION("i2c Hauppauge eeprom decoder driver"); MODULE_DESCRIPTION("i2c Hauppauge eeprom decoder driver");
MODULE_AUTHOR("John Klar"); 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 * The Hauppauge eeprom uses an 8bit field to determine which
* tuner formats the tuner supports. * tuner formats the tuner supports.
*/ */
static struct HAUPPAUGE_TUNER_FMT static const struct {
{
int id; int id;
char *name; const char * const name;
} } hauppauge_tuner_fmt[] = {
hauppauge_tuner_fmt[] =
{
{ V4L2_STD_UNKNOWN, " UNKNOWN" }, { V4L2_STD_UNKNOWN, " UNKNOWN" },
{ V4L2_STD_UNKNOWN, " FM" }, { V4L2_STD_UNKNOWN, " FM" },
{ V4L2_STD_B|V4L2_STD_GH, " PAL(B/G)" }, { 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 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 testing and never made it to the outside world. So you will only see
a subset in actual produced cards. */ a subset in actual produced cards. */
static struct HAUPPAUGE_TUNER static const struct {
{
int id; int id;
char *name; const char * const name;
} } hauppauge_tuner[] = {
hauppauge_tuner[] =
{
/* 0-9 */ /* 0-9 */
{ TUNER_ABSENT, "None" }, { TUNER_ABSENT, "None" },
{ TUNER_ABSENT, "External" }, { TUNER_ABSENT, "External" },
@ -298,69 +291,66 @@ hauppauge_tuner[] =
{ TUNER_ABSENT, "NXP 18272S"}, { 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. */ * internal to a video chip, i.e. not a separate audio chip. */
static struct HAUPPAUGE_AUDIOIC static const struct {
{
u32 id; u32 id;
char *name; const char * const name;
} } audio_ic[] = {
audioIC[] =
{
/* 0-4 */ /* 0-4 */
{ V4L2_IDENT_NONE, "None" }, { TVEEPROM_AUDPROC_NONE, "None" },
{ V4L2_IDENT_UNKNOWN, "TEA6300" }, { TVEEPROM_AUDPROC_OTHER, "TEA6300" },
{ V4L2_IDENT_UNKNOWN, "TEA6320" }, { TVEEPROM_AUDPROC_OTHER, "TEA6320" },
{ V4L2_IDENT_UNKNOWN, "TDA9850" }, { TVEEPROM_AUDPROC_OTHER, "TDA9850" },
{ V4L2_IDENT_MSPX4XX, "MSP3400C" }, { TVEEPROM_AUDPROC_MSP, "MSP3400C" },
/* 5-9 */ /* 5-9 */
{ V4L2_IDENT_MSPX4XX, "MSP3410D" }, { TVEEPROM_AUDPROC_MSP, "MSP3410D" },
{ V4L2_IDENT_MSPX4XX, "MSP3415" }, { TVEEPROM_AUDPROC_MSP, "MSP3415" },
{ V4L2_IDENT_MSPX4XX, "MSP3430" }, { TVEEPROM_AUDPROC_MSP, "MSP3430" },
{ V4L2_IDENT_MSPX4XX, "MSP3438" }, { TVEEPROM_AUDPROC_MSP, "MSP3438" },
{ V4L2_IDENT_UNKNOWN, "CS5331" }, { TVEEPROM_AUDPROC_OTHER, "CS5331" },
/* 10-14 */ /* 10-14 */
{ V4L2_IDENT_MSPX4XX, "MSP3435" }, { TVEEPROM_AUDPROC_MSP, "MSP3435" },
{ V4L2_IDENT_MSPX4XX, "MSP3440" }, { TVEEPROM_AUDPROC_MSP, "MSP3440" },
{ V4L2_IDENT_MSPX4XX, "MSP3445" }, { TVEEPROM_AUDPROC_MSP, "MSP3445" },
{ V4L2_IDENT_MSPX4XX, "MSP3411" }, { TVEEPROM_AUDPROC_MSP, "MSP3411" },
{ V4L2_IDENT_MSPX4XX, "MSP3416" }, { TVEEPROM_AUDPROC_MSP, "MSP3416" },
/* 15-19 */ /* 15-19 */
{ V4L2_IDENT_MSPX4XX, "MSP3425" }, { TVEEPROM_AUDPROC_MSP, "MSP3425" },
{ V4L2_IDENT_MSPX4XX, "MSP3451" }, { TVEEPROM_AUDPROC_MSP, "MSP3451" },
{ V4L2_IDENT_MSPX4XX, "MSP3418" }, { TVEEPROM_AUDPROC_MSP, "MSP3418" },
{ V4L2_IDENT_UNKNOWN, "Type 0x12" }, { TVEEPROM_AUDPROC_OTHER, "Type 0x12" },
{ V4L2_IDENT_UNKNOWN, "OKI7716" }, { TVEEPROM_AUDPROC_OTHER, "OKI7716" },
/* 20-24 */ /* 20-24 */
{ V4L2_IDENT_MSPX4XX, "MSP4410" }, { TVEEPROM_AUDPROC_MSP, "MSP4410" },
{ V4L2_IDENT_MSPX4XX, "MSP4420" }, { TVEEPROM_AUDPROC_MSP, "MSP4420" },
{ V4L2_IDENT_MSPX4XX, "MSP4440" }, { TVEEPROM_AUDPROC_MSP, "MSP4440" },
{ V4L2_IDENT_MSPX4XX, "MSP4450" }, { TVEEPROM_AUDPROC_MSP, "MSP4450" },
{ V4L2_IDENT_MSPX4XX, "MSP4408" }, { TVEEPROM_AUDPROC_MSP, "MSP4408" },
/* 25-29 */ /* 25-29 */
{ V4L2_IDENT_MSPX4XX, "MSP4418" }, { TVEEPROM_AUDPROC_MSP, "MSP4418" },
{ V4L2_IDENT_MSPX4XX, "MSP4428" }, { TVEEPROM_AUDPROC_MSP, "MSP4428" },
{ V4L2_IDENT_MSPX4XX, "MSP4448" }, { TVEEPROM_AUDPROC_MSP, "MSP4448" },
{ V4L2_IDENT_MSPX4XX, "MSP4458" }, { TVEEPROM_AUDPROC_MSP, "MSP4458" },
{ V4L2_IDENT_MSPX4XX, "Type 0x1d" }, { TVEEPROM_AUDPROC_MSP, "Type 0x1d" },
/* 30-34 */ /* 30-34 */
{ V4L2_IDENT_AMBIGUOUS, "CX880" }, { TVEEPROM_AUDPROC_INTERNAL, "CX880" },
{ V4L2_IDENT_AMBIGUOUS, "CX881" }, { TVEEPROM_AUDPROC_INTERNAL, "CX881" },
{ V4L2_IDENT_AMBIGUOUS, "CX883" }, { TVEEPROM_AUDPROC_INTERNAL, "CX883" },
{ V4L2_IDENT_AMBIGUOUS, "CX882" }, { TVEEPROM_AUDPROC_INTERNAL, "CX882" },
{ V4L2_IDENT_AMBIGUOUS, "CX25840" }, { TVEEPROM_AUDPROC_INTERNAL, "CX25840" },
/* 35-39 */ /* 35-39 */
{ V4L2_IDENT_AMBIGUOUS, "CX25841" }, { TVEEPROM_AUDPROC_INTERNAL, "CX25841" },
{ V4L2_IDENT_AMBIGUOUS, "CX25842" }, { TVEEPROM_AUDPROC_INTERNAL, "CX25842" },
{ V4L2_IDENT_AMBIGUOUS, "CX25843" }, { TVEEPROM_AUDPROC_INTERNAL, "CX25843" },
{ V4L2_IDENT_AMBIGUOUS, "CX23418" }, { TVEEPROM_AUDPROC_INTERNAL, "CX23418" },
{ V4L2_IDENT_AMBIGUOUS, "CX23885" }, { TVEEPROM_AUDPROC_INTERNAL, "CX23885" },
/* 40-44 */ /* 40-44 */
{ V4L2_IDENT_AMBIGUOUS, "CX23888" }, { TVEEPROM_AUDPROC_INTERNAL, "CX23888" },
{ V4L2_IDENT_AMBIGUOUS, "SAA7131" }, { TVEEPROM_AUDPROC_INTERNAL, "SAA7131" },
{ V4L2_IDENT_AMBIGUOUS, "CX23887" }, { TVEEPROM_AUDPROC_INTERNAL, "CX23887" },
{ V4L2_IDENT_AMBIGUOUS, "SAA7164" }, { TVEEPROM_AUDPROC_INTERNAL, "SAA7164" },
{ V4L2_IDENT_AMBIGUOUS, "AU8522" }, { TVEEPROM_AUDPROC_INTERNAL, "AU8522" },
}; };
/* This list is supplied by Hauppauge. Thanks! */ /* 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 i, j, len, done, beenhere, tag, start;
int tuner1 = 0, t_format1 = 0, audioic = -1; int tuner1 = 0, t_format1 = 0, audioic = -1;
char *t_name1 = NULL; const char *t_name1 = NULL;
const char *t_fmt_name1[8] = { " none", "", "", "", "", "", "", "" }; const char *t_fmt_name1[8] = { " none", "", "", "", "", "", "", "" };
int tuner2 = 0, t_format2 = 0; int tuner2 = 0, t_format2 = 0;
char *t_name2 = NULL; const char *t_name2 = NULL;
const char *t_fmt_name2[8] = { " none", "", "", "", "", "", "", "" }; const char *t_fmt_name2[8] = { " none", "", "", "", "", "", "", "" };
memset(tvee, 0, sizeof(*tvee)); 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 to indicate 4052 mux was removed in favor of using MSP
inputs directly. */ inputs directly. */
audioic = eeprom_data[i+2] & 0x7f; audioic = eeprom_data[i+2] & 0x7f;
if (audioic < ARRAY_SIZE(audioIC)) if (audioic < ARRAY_SIZE(audio_ic))
tvee->audio_processor = audioIC[audioic].id; tvee->audio_processor = audio_ic[audioic].id;
else else
tvee->audio_processor = V4L2_IDENT_UNKNOWN; tvee->audio_processor = TVEEPROM_AUDPROC_OTHER;
break; break;
/* case 0x03: tag 'EEInfo' */ /* 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 to indicate 4052 mux was removed in favor of using MSP
inputs directly. */ inputs directly. */
audioic = eeprom_data[i+1] & 0x7f; audioic = eeprom_data[i+1] & 0x7f;
if (audioic < ARRAY_SIZE(audioIC)) if (audioic < ARRAY_SIZE(audio_ic))
tvee->audio_processor = audioIC[audioic].id; tvee->audio_processor = audio_ic[audioic].id;
else else
tvee->audio_processor = V4L2_IDENT_UNKNOWN; tvee->audio_processor = TVEEPROM_AUDPROC_OTHER;
break; 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); t_fmt_name2[6], t_fmt_name2[7], t_format2);
if (audioic < 0) { if (audioic < 0) {
tveeprom_info("audio processor is unknown (no idx)\n"); tveeprom_info("audio processor is unknown (no idx)\n");
tvee->audio_processor = V4L2_IDENT_UNKNOWN; tvee->audio_processor = TVEEPROM_AUDPROC_OTHER;
} else { } else {
if (audioic < ARRAY_SIZE(audioIC)) if (audioic < ARRAY_SIZE(audio_ic))
tveeprom_info("audio processor is %s (idx %d)\n", tveeprom_info("audio processor is %s (idx %d)\n",
audioIC[audioic].name, audioic); audio_ic[audioic].name, audioic);
else else
tveeprom_info("audio processor is unknown (idx %d)\n", tveeprom_info("audio processor is unknown (idx %d)\n",
audioic); audioic);

View File

@ -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, ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer2,
buffer2_len); buffer2_len);
} }
if (ret < 0) { if (ret < 0)
dvb_ringbuffer_flush(&dmxdevfilter->buffer);
dmxdevfilter->buffer.error = ret; dmxdevfilter->buffer.error = ret;
}
if (dmxdevfilter->params.sec.flags & DMX_ONESHOT) if (dmxdevfilter->params.sec.flags & DMX_ONESHOT)
dmxdevfilter->state = DMXDEV_STATE_DONE; dmxdevfilter->state = DMXDEV_STATE_DONE;
spin_unlock(&dmxdevfilter->dev->lock); 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); ret = dvb_dmxdev_buffer_write(buffer, buffer1, buffer1_len);
if (ret == buffer1_len) if (ret == buffer1_len)
ret = dvb_dmxdev_buffer_write(buffer, buffer2, buffer2_len); ret = dvb_dmxdev_buffer_write(buffer, buffer2, buffer2_len);
if (ret < 0) { if (ret < 0)
dvb_ringbuffer_flush(buffer);
buffer->error = ret; buffer->error = ret;
}
spin_unlock(&dmxdevfilter->dev->lock); spin_unlock(&dmxdevfilter->dev->lock);
wake_up(&buffer->queue); wake_up(&buffer->queue);
return 0; return 0;

View File

@ -367,4 +367,6 @@
#define USB_PID_TECHNISAT_USB2_HDCI_V2 0x0002 #define USB_PID_TECHNISAT_USB2_HDCI_V2 0x0002
#define USB_PID_TECHNISAT_AIRSTAR_TELESTICK_2 0x0004 #define USB_PID_TECHNISAT_AIRSTAR_TELESTICK_2 0x0004
#define USB_PID_TECHNISAT_USB2_DVB_S2 0x0500 #define USB_PID_TECHNISAT_USB2_DVB_S2 0x0500
#define USB_PID_CPYTO_REDI_PC50A 0xa803
#define USB_PID_CTVDIGDUAL_V2 0xe410
#endif #endif

View File

@ -35,7 +35,6 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include "au8522.h" #include "au8522.h"
#include "au8522_priv.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, static int au8522_g_register(struct v4l2_subdev *sd,
struct v4l2_dbg_register *reg) struct v4l2_dbg_register *reg)
{ {
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct au8522_state *state = to_state(sd); struct au8522_state *state = to_state(sd);
if (!v4l2_chip_match_i2c_client(client, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
reg->val = au8522_readreg(state, reg->reg & 0xffff); reg->val = au8522_readreg(state, reg->reg & 0xffff);
return 0; return 0;
} }
@ -538,13 +532,8 @@ static int au8522_g_register(struct v4l2_subdev *sd,
static int au8522_s_register(struct v4l2_subdev *sd, static int au8522_s_register(struct v4l2_subdev *sd,
const struct v4l2_dbg_register *reg) const struct v4l2_dbg_register *reg)
{ {
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct au8522_state *state = to_state(sd); struct au8522_state *state = to_state(sd);
if (!v4l2_chip_match_i2c_client(client, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
au8522_writereg(state, reg->reg, reg->val & 0xff); au8522_writereg(state, reg->reg, reg->val & 0xff);
return 0; return 0;
} }
@ -636,20 +625,10 @@ static int au8522_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
return 0; 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 = { static const struct v4l2_subdev_core_ops au8522_core_ops = {
.log_status = v4l2_ctrl_subdev_log_status, .log_status = v4l2_ctrl_subdev_log_status,
.g_chip_ident = au8522_g_chip_ident,
.reset = au8522_reset, .reset = au8522_reset,
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
.g_register = au8522_g_register, .g_register = au8522_g_register,

View File

@ -3406,7 +3406,7 @@ static int dib8000_set_frontend(struct dvb_frontend *fe)
{ {
struct dib8000_state *state = fe->demodulator_priv; struct dib8000_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache; 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; u8 exit_condition, index_frontend;
u32 delay, callback_time; 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) static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat)

View File

@ -8,7 +8,7 @@
/** /**
* struct drxk_config - Configure the initial parameters for DRX-K * 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, * @parallel_ts: True means that the device uses parallel TS,
* Serial otherwise. * Serial otherwise.
* @dynamic_clk: True means that the clock will be dynamically * @dynamic_clk: True means that the clock will be dynamically

File diff suppressed because it is too large Load Diff

View File

@ -46,7 +46,7 @@
#define IQM_RC_ADJ_SEL_B_QAM 0x1 #define IQM_RC_ADJ_SEL_B_QAM 0x1
#define IQM_RC_ADJ_SEL_B_VSB 0x2 #define IQM_RC_ADJ_SEL_B_VSB 0x2
enum OperationMode { enum operation_mode {
OM_NONE, OM_NONE,
OM_QAM_ITU_A, OM_QAM_ITU_A,
OM_QAM_ITU_B, OM_QAM_ITU_B,
@ -54,7 +54,7 @@ enum OperationMode {
OM_DVBT OM_DVBT
}; };
enum DRXPowerMode { enum drx_power_mode {
DRX_POWER_UP = 0, DRX_POWER_UP = 0,
DRX_POWER_MODE_1, DRX_POWER_MODE_1,
DRX_POWER_MODE_2, 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 #ifndef DRXK_POWER_DOWN_OFDM
#define DRXK_POWER_DOWN_OFDM DRX_POWER_MODE_1 #define DRXK_POWER_DOWN_OFDM DRX_POWER_MODE_1
#endif #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 #ifndef DRXK_POWER_DOWN_CORE
#define DRXK_POWER_DOWN_CORE DRX_POWER_MODE_9 #define DRXK_POWER_DOWN_CORE DRX_POWER_MODE_9
#endif #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 #ifndef DRXK_POWER_DOWN_PLL
#define DRXK_POWER_DOWN_PLL DRX_POWER_MODE_10 #define DRXK_POWER_DOWN_PLL DRX_POWER_MODE_10
#endif #endif
enum AGC_CTRL_MODE { DRXK_AGC_CTRL_AUTO = 0, DRXK_AGC_CTRL_USER, DRXK_AGC_CTRL_OFF }; enum agc_ctrl_mode {
enum EDrxkState { DRXK_AGC_CTRL_AUTO = 0,
DRXK_AGC_CTRL_USER,
DRXK_AGC_CTRL_OFF
};
enum e_drxk_state {
DRXK_UNINITIALIZED = 0, DRXK_UNINITIALIZED = 0,
DRXK_STOPPED, DRXK_STOPPED,
DRXK_DTV_STARTED, DRXK_DTV_STARTED,
@ -103,7 +108,7 @@ enum EDrxkState {
DRXK_NO_DEV /* If drxk init failed */ DRXK_NO_DEV /* If drxk init failed */
}; };
enum EDrxkCoefArrayIndex { enum e_drxk_coef_array_index {
DRXK_COEF_IDX_MN = 0, DRXK_COEF_IDX_MN = 0,
DRXK_COEF_IDX_FM , DRXK_COEF_IDX_FM ,
DRXK_COEF_IDX_L , DRXK_COEF_IDX_L ,
@ -113,13 +118,13 @@ enum EDrxkCoefArrayIndex {
DRXK_COEF_IDX_I , DRXK_COEF_IDX_I ,
DRXK_COEF_IDX_MAX DRXK_COEF_IDX_MAX
}; };
enum EDrxkSifAttenuation { enum e_drxk_sif_attenuation {
DRXK_SIF_ATTENUATION_0DB, DRXK_SIF_ATTENUATION_0DB,
DRXK_SIF_ATTENUATION_3DB, DRXK_SIF_ATTENUATION_3DB,
DRXK_SIF_ATTENUATION_6DB, DRXK_SIF_ATTENUATION_6DB,
DRXK_SIF_ATTENUATION_9DB DRXK_SIF_ATTENUATION_9DB
}; };
enum EDrxkConstellation { enum e_drxk_constellation {
DRX_CONSTELLATION_BPSK = 0, DRX_CONSTELLATION_BPSK = 0,
DRX_CONSTELLATION_QPSK, DRX_CONSTELLATION_QPSK,
DRX_CONSTELLATION_PSK8, DRX_CONSTELLATION_PSK8,
@ -133,7 +138,7 @@ enum EDrxkConstellation {
DRX_CONSTELLATION_UNKNOWN = DRX_UNKNOWN, DRX_CONSTELLATION_UNKNOWN = DRX_UNKNOWN,
DRX_CONSTELLATION_AUTO = DRX_AUTO DRX_CONSTELLATION_AUTO = DRX_AUTO
}; };
enum EDrxkInterleaveMode { enum e_drxk_interleave_mode {
DRXK_QAM_I12_J17 = 16, DRXK_QAM_I12_J17 = 16,
DRXK_QAM_I_UNKNOWN = DRX_UNKNOWN DRXK_QAM_I_UNKNOWN = DRX_UNKNOWN
}; };
@ -144,14 +149,14 @@ enum {
DRXK_SPIN_UNKNOWN DRXK_SPIN_UNKNOWN
}; };
enum DRXKCfgDvbtSqiSpeed { enum drxk_cfg_dvbt_sqi_speed {
DRXK_DVBT_SQI_SPEED_FAST = 0, DRXK_DVBT_SQI_SPEED_FAST = 0,
DRXK_DVBT_SQI_SPEED_MEDIUM, DRXK_DVBT_SQI_SPEED_MEDIUM,
DRXK_DVBT_SQI_SPEED_SLOW, DRXK_DVBT_SQI_SPEED_SLOW,
DRXK_DVBT_SQI_SPEED_UNKNOWN = DRX_UNKNOWN DRXK_DVBT_SQI_SPEED_UNKNOWN = DRX_UNKNOWN
} ; } ;
enum DRXFftmode_t { enum drx_fftmode_t {
DRX_FFTMODE_2K = 0, DRX_FFTMODE_2K = 0,
DRX_FFTMODE_4K, DRX_FFTMODE_4K,
DRX_FFTMODE_8K, DRX_FFTMODE_8K,
@ -159,47 +164,47 @@ enum DRXFftmode_t {
DRX_FFTMODE_AUTO = DRX_AUTO DRX_FFTMODE_AUTO = DRX_AUTO
}; };
enum DRXMPEGStrWidth_t { enum drxmpeg_str_width_t {
DRX_MPEG_STR_WIDTH_1, DRX_MPEG_STR_WIDTH_1,
DRX_MPEG_STR_WIDTH_8 DRX_MPEG_STR_WIDTH_8
}; };
enum DRXQamLockRange_t { enum drx_qam_lock_range_t {
DRX_QAM_LOCKRANGE_NORMAL, DRX_QAM_LOCKRANGE_NORMAL,
DRX_QAM_LOCKRANGE_EXTENDED DRX_QAM_LOCKRANGE_EXTENDED
}; };
struct DRXKCfgDvbtEchoThres_t { struct drxk_cfg_dvbt_echo_thres_t {
u16 threshold; u16 threshold;
enum DRXFftmode_t fftMode; enum drx_fftmode_t fft_mode;
} ; } ;
struct SCfgAgc { struct s_cfg_agc {
enum AGC_CTRL_MODE ctrlMode; /* off, user, auto */ enum agc_ctrl_mode ctrl_mode; /* off, user, auto */
u16 outputLevel; /* range dependent on AGC */ u16 output_level; /* range dependent on AGC */
u16 minOutputLevel; /* range dependent on AGC */ u16 min_output_level; /* range dependent on AGC */
u16 maxOutputLevel; /* range dependent on AGC */ u16 max_output_level; /* range dependent on AGC */
u16 speed; /* range dependent on AGC */ u16 speed; /* range dependent on AGC */
u16 top; /* rf-agc take over point */ 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 */ is below cut-off current */
u16 IngainTgtMax; u16 ingain_tgt_max;
u16 FastClipCtrlDelay; u16 fast_clip_ctrl_delay;
}; };
struct SCfgPreSaw { struct s_cfg_pre_saw {
u16 reference; /* pre SAW reference value, range 0 .. 31 */ 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 { struct drxk_ofdm_sc_cmd_t {
u16 cmd; /**< Command number */ u16 cmd; /* Command number */
u16 subcmd; /**< Sub-command parameter*/ u16 subcmd; /* Sub-command parameter*/
u16 param0; /**< General purpous param */ u16 param0; /* General purpous param */
u16 param1; /**< General purpous param */ u16 param1; /* General purpous param */
u16 param2; /**< General purpous param */ u16 param2; /* General purpous param */
u16 param3; /**< General purpous param */ u16 param3; /* General purpous param */
u16 param4; /**< General purpous param */ u16 param4; /* General purpous param */
}; };
struct drxk_state { struct drxk_state {
@ -213,121 +218,121 @@ struct drxk_state {
struct mutex mutex; struct mutex mutex;
u32 m_Instance; /**< Channel 1,2,3 or 4 */ u32 m_instance; /* Channel 1,2,3 or 4 */
int m_ChunkSize; int m_chunk_size;
u8 Chunk[256]; u8 chunk[256];
bool m_hasLNA; bool m_has_lna;
bool m_hasDVBT; bool m_has_dvbt;
bool m_hasDVBC; bool m_has_dvbc;
bool m_hasAudio; bool m_has_audio;
bool m_hasATV; bool m_has_atv;
bool m_hasOOB; bool m_has_oob;
bool m_hasSAWSW; /**< TRUE if mat_tx is available */ bool m_has_sawsw; /* TRUE if mat_tx is available */
bool m_hasGPIO1; /**< TRUE if mat_rx is available */ bool m_has_gpio1; /* TRUE if mat_rx is available */
bool m_hasGPIO2; /**< TRUE if GPIO is available */ bool m_has_gpio2; /* TRUE if GPIO is available */
bool m_hasIRQN; /**< TRUE if IRQN is available */ bool m_has_irqn; /* TRUE if IRQN is available */
u16 m_oscClockFreq; u16 m_osc_clock_freq;
u16 m_HICfgTimingDiv; u16 m_hi_cfg_timing_div;
u16 m_HICfgBridgeDelay; u16 m_hi_cfg_bridge_delay;
u16 m_HICfgWakeUpKey; u16 m_hi_cfg_wake_up_key;
u16 m_HICfgTimeout; u16 m_hi_cfg_timeout;
u16 m_HICfgCtrl; u16 m_hi_cfg_ctrl;
s32 m_sysClockFreq; /**< system clock frequency in kHz */ s32 m_sys_clock_freq; /* system clock frequency in kHz */
enum EDrxkState m_DrxkState; /**< State of Drxk (init,stopped,started) */ enum e_drxk_state m_drxk_state; /* State of Drxk (init,stopped,started) */
enum OperationMode m_OperationMode; /**< digital standards */ enum operation_mode m_operation_mode; /* digital standards */
struct SCfgAgc m_vsbRfAgcCfg; /**< settings for VSB RF-AGC */ struct s_cfg_agc m_vsb_rf_agc_cfg; /* settings for VSB RF-AGC */
struct SCfgAgc m_vsbIfAgcCfg; /**< settings for VSB IF-AGC */ struct s_cfg_agc m_vsb_if_agc_cfg; /* settings for VSB IF-AGC */
u16 m_vsbPgaCfg; /**< settings for VSB PGA */ u16 m_vsb_pga_cfg; /* settings for VSB PGA */
struct SCfgPreSaw m_vsbPreSawCfg; /**< settings for pre SAW sense */ 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_Quality83percent; /* MER level (*0.1 dB) for 83% quality indication */
s32 m_Quality93percent; /**< MER level (*0.1 dB) for 93% quality indication */ s32 m_Quality93percent; /* MER level (*0.1 dB) for 93% quality indication */
bool m_smartAntInverted; bool m_smart_ant_inverted;
bool m_bDebugEnableBridge; bool m_b_debug_enable_bridge;
bool m_bPDownOpenBridge; /**< only open DRXK bridge before power-down once it has been accessed */ bool m_b_p_down_open_bridge; /* only open DRXK bridge before power-down once it has been accessed */
bool m_bPowerDown; /**< Power down when not used */ bool m_b_power_down; /* Power down when not used */
u32 m_IqmFsRateOfs; /**< frequency shift as written to DRXK register (28bit fixpoint) */ u32 m_iqm_fs_rate_ofs; /* frequency shift as written to DRXK register (28bit fixpoint) */
bool m_enableMPEGOutput; /**< If TRUE, enable MPEG output */ bool m_enable_mpeg_output; /* If TRUE, enable MPEG output */
bool m_insertRSByte; /**< If TRUE, insert RS byte */ bool m_insert_rs_byte; /* If TRUE, insert RS byte */
bool m_enableParallel; /**< If TRUE, parallel out otherwise serial */ bool m_enable_parallel; /* If TRUE, parallel out otherwise serial */
bool m_invertDATA; /**< If TRUE, invert DATA signals */ bool m_invert_data; /* If TRUE, invert DATA signals */
bool m_invertERR; /**< If TRUE, invert ERR signal */ bool m_invert_err; /* If TRUE, invert ERR signal */
bool m_invertSTR; /**< If TRUE, invert STR signals */ bool m_invert_str; /* If TRUE, invert STR signals */
bool m_invertVAL; /**< If TRUE, invert VAL signals */ bool m_invert_val; /* If TRUE, invert VAL signals */
bool m_invertCLK; /**< If TRUE, invert CLK signals */ bool m_invert_clk; /* If TRUE, invert CLK signals */
bool m_DVBCStaticCLK; bool m_dvbc_static_clk;
bool m_DVBTStaticCLK; /**< If TRUE, static MPEG clockrate will bool m_dvbt_static_clk; /* If TRUE, static MPEG clockrate will
be used, otherwise clockrate will be used, otherwise clockrate will
adapt to the bitrate of the TS */ adapt to the bitrate of the TS */
u32 m_DVBTBitrate; u32 m_dvbt_bitrate;
u32 m_DVBCBitrate; u32 m_dvbc_bitrate;
u8 m_TSDataStrength; u8 m_ts_data_strength;
u8 m_TSClockkStrength; u8 m_ts_clockk_strength;
bool m_itut_annex_c; /* If true, uses ITU-T DVB-C Annex C, instead of Annex A */ 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 */ enum drxmpeg_str_width_t m_width_str; /* MPEG start width */
u32 m_mpegTsStaticBitrate; /**< Maximum bitrate in b/s in case u32 m_mpeg_ts_static_bitrate; /* Maximum bitrate in b/s in case
static clockrate is selected */ static clockrate is selected */
/* LARGE_INTEGER m_StartTime; */ /**< Contains the time of the last demod start */ /* LARGE_INTEGER m_startTime; */ /* Contains the time of the last demod start */
s32 m_MpegLockTimeOut; /**< WaitForLockStatus Timeout (counts from start time) */ s32 m_mpeg_lock_time_out; /* WaitForLockStatus Timeout (counts from start time) */
s32 m_DemodLockTimeOut; /**< WaitForLockStatus Timeout (counts from start time) */ s32 m_demod_lock_time_out; /* WaitForLockStatus Timeout (counts from start time) */
bool m_disableTEIhandling; bool m_disable_te_ihandling;
bool m_RfAgcPol; bool m_rf_agc_pol;
bool m_IfAgcPol; bool m_if_agc_pol;
struct SCfgAgc m_atvRfAgcCfg; /**< settings for ATV RF-AGC */ struct s_cfg_agc m_atv_rf_agc_cfg; /* settings for ATV RF-AGC */
struct SCfgAgc m_atvIfAgcCfg; /**< settings for ATV IF-AGC */ struct s_cfg_agc m_atv_if_agc_cfg; /* settings for ATV IF-AGC */
struct SCfgPreSaw m_atvPreSawCfg; /**< settings for ATV pre SAW sense */ struct s_cfg_pre_saw m_atv_pre_saw_cfg; /* settings for ATV pre SAW sense */
bool m_phaseCorrectionBypass; bool m_phase_correction_bypass;
s16 m_atvTopVidPeak; s16 m_atv_top_vid_peak;
u16 m_atvTopNoiseTh; u16 m_atv_top_noise_th;
enum EDrxkSifAttenuation m_sifAttenuation; enum e_drxk_sif_attenuation m_sif_attenuation;
bool m_enableCVBSOutput; bool m_enable_cvbs_output;
bool m_enableSIFOutput; bool m_enable_sif_output;
bool m_bMirrorFreqSpect; bool m_b_mirror_freq_spect;
enum EDrxkConstellation m_Constellation; /**< Constellation type of the channel */ enum e_drxk_constellation m_constellation; /* constellation type of the channel */
u32 m_CurrSymbolRate; /**< Current QAM symbol rate */ u32 m_curr_symbol_rate; /* Current QAM symbol rate */
struct SCfgAgc m_qamRfAgcCfg; /**< settings for QAM RF-AGC */ struct s_cfg_agc m_qam_rf_agc_cfg; /* settings for QAM RF-AGC */
struct SCfgAgc m_qamIfAgcCfg; /**< settings for QAM IF-AGC */ struct s_cfg_agc m_qam_if_agc_cfg; /* settings for QAM IF-AGC */
u16 m_qamPgaCfg; /**< settings for QAM PGA */ u16 m_qam_pga_cfg; /* settings for QAM PGA */
struct SCfgPreSaw m_qamPreSawCfg; /**< settings for QAM pre SAW sense */ struct s_cfg_pre_saw m_qam_pre_saw_cfg; /* settings for QAM pre SAW sense */
enum EDrxkInterleaveMode m_qamInterleaveMode; /**< QAM Interleave mode */ enum e_drxk_interleave_mode m_qam_interleave_mode; /* QAM Interleave mode */
u16 m_fecRsPlen; u16 m_fec_rs_plen;
u16 m_fecRsPrescale; u16 m_fec_rs_prescale;
enum DRXKCfgDvbtSqiSpeed m_sqiSpeed; enum drxk_cfg_dvbt_sqi_speed m_sqi_speed;
u16 m_GPIO; u16 m_gpio;
u16 m_GPIOCfg; u16 m_gpio_cfg;
struct SCfgAgc m_dvbtRfAgcCfg; /**< settings for QAM RF-AGC */ struct s_cfg_agc m_dvbt_rf_agc_cfg; /* settings for QAM RF-AGC */
struct SCfgAgc m_dvbtIfAgcCfg; /**< settings for QAM IF-AGC */ struct s_cfg_agc m_dvbt_if_agc_cfg; /* settings for QAM IF-AGC */
struct SCfgPreSaw m_dvbtPreSawCfg; /**< settings for QAM pre SAW sense */ struct s_cfg_pre_saw m_dvbt_pre_saw_cfg; /* settings for QAM pre SAW sense */
u16 m_agcFastClipCtrlDelay; u16 m_agcfast_clip_ctrl_delay;
bool m_adcCompPassed; bool m_adc_comp_passed;
u16 m_adcCompCoef[64]; u16 m_adcCompCoef[64];
u16 m_adcState; u16 m_adc_state;
u8 *m_microcode; u8 *m_microcode;
int m_microcode_length; int m_microcode_length;
bool m_DRXK_A3_ROM_CODE; bool m_drxk_a3_rom_code;
bool m_DRXK_A3_PATCH_CODE; bool m_drxk_a3_patch_code;
bool m_rfmirror; bool m_rfmirror;
u8 m_deviceSpin; u8 m_device_spin;
u32 m_iqmRcRate; 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 */ /* when true, avoids other devices to use the I2C bus */
bool drxk_i2c_exclusive_lock; bool drxk_i2c_exclusive_lock;
@ -337,7 +342,7 @@ struct drxk_state {
* at struct drxk_config. * at struct drxk_config.
*/ */
u16 UIO_mask; /* Bits used by UIO */ u16 uio_mask; /* Bits used by UIO */
bool enable_merr_cfg; bool enable_merr_cfg;
bool single_master; bool single_master;

View File

@ -226,8 +226,8 @@ static enum stb0899_status stb0899_search_tmg(struct stb0899_state *state)
next_loop--; next_loop--;
if (next_loop) { if (next_loop) {
STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(state->config->inversion * derot_freq)); STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(internal->inversion * derot_freq));
STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->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_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency */
} }
internal->direction = -internal->direction; /* Change zigzag direction */ 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) { if (internal->status == TIMINGOK) {
stb0899_read_regs(state, STB0899_CFRM, cfr, 2); /* get derotator frequency */ 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); 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_SETFIELD_VAL(CFD_ON, reg, 1);
stb0899_write_reg(state, STB0899_CFD, reg); stb0899_write_reg(state, STB0899_CFD, reg);
STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(state->config->inversion * derot_freq)); STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(internal->inversion * derot_freq));
STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->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_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) { if (internal->status == CARRIEROK) {
stb0899_read_regs(state, STB0899_CFRM, cfr, 2); /* get derotator frequency */ 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); dprintk(state->verbose, FE_DEBUG, 1, "----> CARRIER OK !, Derot Freq=%d", internal->derot_freq);
} else { } else {
internal->derot_freq = last_derot_freq; 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_SETFIELD_VAL(CFD_ON, reg, 1);
stb0899_write_reg(state, STB0899_CFD, reg); stb0899_write_reg(state, STB0899_CFD, reg);
STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(state->config->inversion * derot_freq)); STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(internal->inversion * derot_freq));
STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->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_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency */
stb0899_check_carrier(state); stb0899_check_carrier(state);
@ -425,7 +425,15 @@ static enum stb0899_status stb0899_search_data(struct stb0899_state *state)
if (internal->status == DATAOK) { if (internal->status == DATAOK) {
stb0899_read_regs(state, STB0899_CFRM, cfr, 2); /* get derotator frequency */ 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); 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; int range_offst, tp_freq;
range_offst = internal->srch_range / 2000; 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)) { if ((tp_freq >= params->freq - range_offst) && (tp_freq <= params->freq + range_offst)) {
internal->status = RANGEOK; internal->status = RANGEOK;
@ -638,7 +646,7 @@ enum stb0899_status stb0899_dvbs_algo(struct stb0899_state *state)
"RANGE OK ! derot freq=%d, mclk=%d", "RANGE OK ! derot freq=%d, mclk=%d",
internal->derot_freq, internal->mclk); 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); reg = stb0899_read_reg(state, STB0899_PLPARM);
internal->fecrate = STB0899_GETFIELD(VITCURPUN, reg); internal->fecrate = STB0899_GETFIELD(VITCURPUN, reg);
dprintk(state->verbose, FE_DEBUG, 1, dprintk(state->verbose, FE_DEBUG, 1,
@ -1373,9 +1381,6 @@ enum stb0899_status stb0899_dvbs2_algo(struct stb0899_state *state)
case IQ_SWAP_ON: case IQ_SWAP_ON:
STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, 1); STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, 1);
break; 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_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_DMD_CNTRL2, STB0899_OFF0_DMD_CNTRL2, reg);
stb0899_dvbs2_reacquire(state); 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->status != DVBS2_FEC_LOCK) {
if (internal->inversion == IQ_SWAP_AUTO) { reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CNTRL2);
reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CNTRL2); iqSpectrum = STB0899_GETFIELD(SPECTRUM_INVERT, reg);
iqSpectrum = STB0899_GETFIELD(SPECTRUM_INVERT, reg); /* IQ Spectrum Inversion */
/* IQ Spectrum Inversion */ STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, !iqSpectrum);
STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, !iqSpectrum); stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_DMD_CNTRL2, STB0899_OFF0_DMD_CNTRL2, reg);
stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_DMD_CNTRL2, STB0899_OFF0_DMD_CNTRL2, reg); /* start acquistion process */
/* start acquistion process */ stb0899_dvbs2_reacquire(state);
stb0899_dvbs2_reacquire(state);
/* Wait for demod lock (UWP and CSM) */ /* Wait for demod lock (UWP and CSM) */
internal->status = stb0899_dvbs2_get_dmd_status(state, searchTime); internal->status = stb0899_dvbs2_get_dmd_status(state, searchTime);
if (internal->status == DVBS2_DEMOD_LOCK) { if (internal->status == DVBS2_DEMOD_LOCK) {
i = 0; i = 0;
/* Demod Locked, check FEC */ /* Demod Locked, check FEC */
internal->status = stb0899_dvbs2_get_fec_status(state, FecLockTime); internal->status = stb0899_dvbs2_get_fec_status(state, FecLockTime);
/*try thrice for false locks, (UWP and CSM Locked but no FEC) */ /*try thrice for false locks, (UWP and CSM Locked but no FEC) */
while ((internal->status != DVBS2_FEC_LOCK) && (i < 3)) { while ((internal->status != DVBS2_FEC_LOCK) && (i < 3)) {
/* Read the frequency offset*/ /* Read the frequency offset*/
offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ); offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ);
/* Set the Nominal frequency to the found frequency offset for the next reacquire*/ /* Set the Nominal frequency to the found frequency offset for the next reacquire*/
reg = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_NOM_FREQ); reg = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_NOM_FREQ);
STB0899_SETFIELD_VAL(CRL_NOM_FREQ, reg, offsetfreq); 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_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_NOM_FREQ, STB0899_OFF0_CRL_NOM_FREQ, reg);
stb0899_dvbs2_reacquire(state); stb0899_dvbs2_reacquire(state);
internal->status = stb0899_dvbs2_get_fec_status(state, searchTime); internal->status = stb0899_dvbs2_get_fec_status(state, searchTime);
i++; 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) { if (internal->status == DVBS2_FEC_LOCK) {
dprintk(state->verbose, FE_DEBUG, 1, "----------------> DVB-S2 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 */ /* Store signal parameters */
offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ); 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 = offsetfreq / ((1 << 30) / 1000);
offsetfreq *= (internal->master_clk / 1000000); offsetfreq *= (internal->master_clk / 1000000);
/* store current inversion for next run */
reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CNTRL2); reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CNTRL2);
if (STB0899_GETFIELD(SPECTRUM_INVERT, reg)) 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); internal->srate = stb0899_dvbs2_get_srate(state);
reg = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_STAT2); reg = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_STAT2);

View File

@ -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 dvb_frontend *stb0899_attach(struct stb0899_config *config, struct i2c_adapter *i2c)
{ {
struct stb0899_state *state = NULL; struct stb0899_state *state = NULL;
enum stb0899_inversion inversion;
state = kzalloc(sizeof (struct stb0899_state), GFP_KERNEL); state = kzalloc(sizeof (struct stb0899_state), GFP_KERNEL);
if (state == NULL) if (state == NULL)
goto error; goto error;
inversion = config->inversion;
state->verbose = &verbose; state->verbose = &verbose;
state->config = config; state->config = config;
state->i2c = i2c; state->i2c = i2c;
state->frontend.ops = stb0899_ops; state->frontend.ops = stb0899_ops;
state->frontend.demodulator_priv = state; 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); stb0899_wakeup(&state->frontend);
if (stb0899_get_dev_id(state) == -ENODEV) { if (stb0899_get_dev_id(state) == -ENODEV) {

View File

@ -45,9 +45,8 @@ struct stb0899_s2_reg {
}; };
enum stb0899_inversion { enum stb0899_inversion {
IQ_SWAP_OFF = 0, IQ_SWAP_OFF = +1, /* inversion affects the sign of e. g. */
IQ_SWAP_ON, IQ_SWAP_ON = -1, /* the derotator frequency register */
IQ_SWAP_AUTO
}; };
#define STB0899_GPIO00 0xf140 #define STB0899_GPIO00 0xf140

View File

@ -245,6 +245,15 @@ config VIDEO_KS0127
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called ks0127. 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 config VIDEO_SAA7110
tristate "Philips SAA7110 video decoder" tristate "Philips SAA7110 video decoder"
depends on VIDEO_V4L2 && I2C depends on VIDEO_V4L2 && I2C
@ -425,6 +434,15 @@ config VIDEO_AK881X
help help
Video output driver for AKM AK8813 and AK8814 TV encoders 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" comment "Camera sensor devices"
config VIDEO_APTINA_PLL config VIDEO_APTINA_PLL

View File

@ -34,6 +34,7 @@ obj-$(CONFIG_VIDEO_BT856) += bt856.o
obj-$(CONFIG_VIDEO_BT866) += bt866.o obj-$(CONFIG_VIDEO_BT866) += bt866.o
obj-$(CONFIG_VIDEO_KS0127) += ks0127.o obj-$(CONFIG_VIDEO_KS0127) += ks0127.o
obj-$(CONFIG_VIDEO_THS7303) += ths7303.o obj-$(CONFIG_VIDEO_THS7303) += ths7303.o
obj-$(CONFIG_VIDEO_THS8200) += ths8200.o
obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o
obj-$(CONFIG_VIDEO_TVP514X) += tvp514x.o obj-$(CONFIG_VIDEO_TVP514X) += tvp514x.o
obj-$(CONFIG_VIDEO_TVP7002) += tvp7002.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_SMIAPP_PLL) += smiapp-pll.o
obj-$(CONFIG_VIDEO_AK881X) += ak881x.o obj-$(CONFIG_VIDEO_AK881X) += ak881x.o
obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o
obj-$(CONFIG_VIDEO_ML86V7667) += ml86v7667.o

View File

@ -32,7 +32,6 @@
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/v4l2-dv-timings.h> #include <linux/v4l2-dv-timings.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/ad9389b.h> #include <media/ad9389b.h>
@ -343,12 +342,6 @@ static const struct v4l2_ctrl_ops ad9389b_ctrl_ops = {
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
static int ad9389b_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) 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, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
reg->val = ad9389b_rd(sd, reg->reg & 0xff); reg->val = ad9389b_rd(sd, reg->reg & 0xff);
reg->size = 1; reg->size = 1;
return 0; 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) 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, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
ad9389b_wr(sd, reg->reg & 0xff, reg->val & 0xff); ad9389b_wr(sd, reg->reg & 0xff, reg->val & 0xff);
return 0; return 0;
} }
#endif #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) static int ad9389b_log_status(struct v4l2_subdev *sd)
{ {
struct ad9389b_state *state = get_ad9389b_state(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 = { static const struct v4l2_subdev_core_ops ad9389b_core_ops = {
.log_status = ad9389b_log_status, .log_status = ad9389b_log_status,
.g_chip_ident = ad9389b_g_chip_ident,
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
.g_register = ad9389b_g_register, .g_register = ad9389b_g_register,
.s_register = ad9389b_s_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", v4l_dbg(1, debug, client, "detecting ad9389b client on address 0x%x\n",
client->addr << 1); client->addr << 1);
state = kzalloc(sizeof(struct ad9389b_state), GFP_KERNEL); state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
if (!state) if (!state)
return -ENOMEM; return -ENOMEM;
/* Platform data */ /* Platform data */
if (pdata == NULL) { if (pdata == NULL) {
v4l_err(client, "No platform data!\n"); v4l_err(client, "No platform data!\n");
err = -ENODEV; return -ENODEV;
goto err_free;
} }
memcpy(&state->pdata, pdata, sizeof(state->pdata)); 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)); state->edid_i2c_client = i2c_new_dummy(client->adapter, (0x7e>>1));
if (state->edid_i2c_client == NULL) { if (state->edid_i2c_client == NULL) {
v4l2_err(sd, "failed to register edid i2c client\n"); v4l2_err(sd, "failed to register edid i2c client\n");
err = -ENOMEM;
goto err_entity; goto err_entity;
} }
state->work_queue = create_singlethread_workqueue(sd->name); state->work_queue = create_singlethread_workqueue(sd->name);
if (state->work_queue == NULL) { if (state->work_queue == NULL) {
v4l2_err(sd, "could not create workqueue\n"); v4l2_err(sd, "could not create workqueue\n");
err = -ENOMEM;
goto err_unreg; goto err_unreg;
} }
@ -1276,8 +1256,6 @@ err_entity:
media_entity_cleanup(&sd->entity); media_entity_cleanup(&sd->entity);
err_hdl: err_hdl:
v4l2_ctrl_handler_free(&state->hdl); v4l2_ctrl_handler_free(&state->hdl);
err_free:
kfree(state);
return err; return err;
} }
@ -1302,15 +1280,14 @@ static int ad9389b_remove(struct i2c_client *client)
v4l2_device_unregister_subdev(sd); v4l2_device_unregister_subdev(sd);
media_entity_cleanup(&sd->entity); media_entity_cleanup(&sd->entity);
v4l2_ctrl_handler_free(sd->ctrl_handler); v4l2_ctrl_handler_free(sd->ctrl_handler);
kfree(get_ad9389b_state(sd));
return 0; return 0;
} }
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
static struct i2c_device_id ad9389b_id[] = { static struct i2c_device_id ad9389b_id[] = {
{ "ad9389b", V4L2_IDENT_AD9389B }, { "ad9389b", 0 },
{ "ad9889b", V4L2_IDENT_AD9389B }, { "ad9889b", 0 },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, ad9389b_id); MODULE_DEVICE_TABLE(i2c, ad9389b_id);

View File

@ -417,7 +417,7 @@ static int adp1653_probe(struct i2c_client *client,
if (client->dev.platform_data == NULL) if (client->dev.platform_data == NULL)
return -ENODEV; return -ENODEV;
flash = kzalloc(sizeof(*flash), GFP_KERNEL); flash = devm_kzalloc(&client->dev, sizeof(*flash), GFP_KERNEL);
if (flash == NULL) if (flash == NULL)
return -ENOMEM; return -ENOMEM;
@ -443,7 +443,6 @@ static int adp1653_probe(struct i2c_client *client,
free_and_quit: free_and_quit:
v4l2_ctrl_handler_free(&flash->ctrls); v4l2_ctrl_handler_free(&flash->ctrls);
kfree(flash);
return ret; return ret;
} }
@ -455,7 +454,7 @@ static int adp1653_remove(struct i2c_client *client)
v4l2_device_unregister_subdev(&flash->subdev); v4l2_device_unregister_subdev(&flash->subdev);
v4l2_ctrl_handler_free(&flash->ctrls); v4l2_ctrl_handler_free(&flash->ctrls);
media_entity_cleanup(&flash->subdev.entity); media_entity_cleanup(&flash->subdev.entity);
kfree(flash);
return 0; return 0;
} }

View File

@ -36,7 +36,6 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-chip-ident.h>
MODULE_DESCRIPTION("Analog Devices ADV7170 video encoder driver"); MODULE_DESCRIPTION("Analog Devices ADV7170 video encoder driver");
MODULE_AUTHOR("Maxim Yevtyushkin"); MODULE_AUTHOR("Maxim Yevtyushkin");
@ -317,19 +316,8 @@ static int adv7170_s_fmt(struct v4l2_subdev *sd,
return ret; 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 = { static const struct v4l2_subdev_video_ops adv7170_video_ops = {
.s_std_output = adv7170_s_std_output, .s_std_output = adv7170_s_std_output,
.s_routing = adv7170_s_routing, .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 = { static const struct v4l2_subdev_ops adv7170_ops = {
.core = &adv7170_core_ops,
.video = &adv7170_video_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", v4l_info(client, "chip found @ 0x%x (%s)\n",
client->addr << 1, client->adapter->name); 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) if (encoder == NULL)
return -ENOMEM; return -ENOMEM;
sd = &encoder->sd; sd = &encoder->sd;
@ -384,7 +371,6 @@ static int adv7170_remove(struct i2c_client *client)
struct v4l2_subdev *sd = i2c_get_clientdata(client); struct v4l2_subdev *sd = i2c_get_clientdata(client);
v4l2_device_unregister_subdev(sd); v4l2_device_unregister_subdev(sd);
kfree(to_adv7170(sd));
return 0; return 0;
} }

View File

@ -32,7 +32,6 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-chip-ident.h>
MODULE_DESCRIPTION("Analog Devices ADV7175 video encoder driver"); MODULE_DESCRIPTION("Analog Devices ADV7175 video encoder driver");
MODULE_AUTHOR("Dave Perks"); MODULE_AUTHOR("Dave Perks");
@ -355,13 +354,6 @@ static int adv7175_s_fmt(struct v4l2_subdev *sd,
return ret; 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) static int adv7175_s_power(struct v4l2_subdev *sd, int on)
{ {
if (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 = { static const struct v4l2_subdev_core_ops adv7175_core_ops = {
.g_chip_ident = adv7175_g_chip_ident,
.init = adv7175_init, .init = adv7175_init,
.s_power = adv7175_s_power, .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", v4l_info(client, "chip found @ 0x%x (%s)\n",
client->addr << 1, client->adapter->name); 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) if (encoder == NULL)
return -ENOMEM; return -ENOMEM;
sd = &encoder->sd; sd = &encoder->sd;
@ -434,7 +425,6 @@ static int adv7175_remove(struct i2c_client *client)
struct v4l2_subdev *sd = i2c_get_clientdata(client); struct v4l2_subdev *sd = i2c_get_clientdata(client);
v4l2_device_unregister_subdev(sd); v4l2_device_unregister_subdev(sd);
kfree(to_adv7175(sd));
return 0; return 0;
} }

View File

@ -1,6 +1,8 @@
/* /*
* adv7180.c Analog Devices ADV7180 video decoder driver * adv7180.c Analog Devices ADV7180 video decoder driver
* Copyright (c) 2009 Intel Corporation * 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 * 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 * it under the terms of the GNU General Public License version 2 as
@ -27,7 +29,6 @@
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-chip-ident.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#define ADV7180_INPUT_CONTROL_REG 0x00 #define ADV7180_INPUT_CONTROL_REG 0x00
@ -272,14 +273,6 @@ static int adv7180_g_input_status(struct v4l2_subdev *sd, u32 *status)
return ret; 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) static int adv7180_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
{ {
struct adv7180_state *state = to_state(sd); 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); 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 = { static const struct v4l2_subdev_video_ops adv7180_video_ops = {
.querystd = adv7180_querystd, .querystd = adv7180_querystd,
.g_input_status = adv7180_g_input_status, .g_input_status = adv7180_g_input_status,
.s_routing = adv7180_s_routing, .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 = { static const struct v4l2_subdev_core_ops adv7180_core_ops = {
.g_chip_ident = adv7180_g_chip_ident,
.s_std = adv7180_s_std, .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", v4l_info(client, "chip found @ 0x%02x (%s)\n",
client->addr, client->adapter->name); 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) { if (state == NULL) {
ret = -ENOMEM; ret = -ENOMEM;
goto err; goto err;
@ -582,7 +618,6 @@ err_free_ctrl:
err_unreg_subdev: err_unreg_subdev:
mutex_destroy(&state->mutex); mutex_destroy(&state->mutex);
v4l2_device_unregister_subdev(sd); v4l2_device_unregister_subdev(sd);
kfree(state);
err: err:
printk(KERN_ERR KBUILD_MODNAME ": Failed to probe: %d\n", ret); printk(KERN_ERR KBUILD_MODNAME ": Failed to probe: %d\n", ret);
return ret; return ret;
@ -607,7 +642,6 @@ static int adv7180_remove(struct i2c_client *client)
mutex_destroy(&state->mutex); mutex_destroy(&state->mutex);
v4l2_device_unregister_subdev(sd); v4l2_device_unregister_subdev(sd);
kfree(to_state(sd));
return 0; return 0;
} }
@ -616,9 +650,10 @@ static const struct i2c_device_id adv7180_id[] = {
{}, {},
}; };
#ifdef CONFIG_PM #ifdef CONFIG_PM_SLEEP
static int adv7180_suspend(struct i2c_client *client, pm_message_t state) static int adv7180_suspend(struct device *dev)
{ {
struct i2c_client *client = to_i2c_client(dev);
int ret; int ret;
ret = i2c_smbus_write_byte_data(client, ADV7180_PWR_MAN_REG, 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; 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 v4l2_subdev *sd = i2c_get_clientdata(client);
struct adv7180_state *state = to_state(sd); struct adv7180_state *state = to_state(sd);
int ret; int ret;
@ -643,6 +679,12 @@ static int adv7180_resume(struct i2c_client *client)
return ret; return ret;
return 0; 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 #endif
MODULE_DEVICE_TABLE(i2c, adv7180_id); MODULE_DEVICE_TABLE(i2c, adv7180_id);
@ -651,13 +693,10 @@ static struct i2c_driver adv7180_driver = {
.driver = { .driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = KBUILD_MODNAME, .name = KBUILD_MODNAME,
.pm = ADV7180_PM_OPS,
}, },
.probe = adv7180_probe, .probe = adv7180_probe,
.remove = adv7180_remove, .remove = adv7180_remove,
#ifdef CONFIG_PM
.suspend = adv7180_suspend,
.resume = adv7180_resume,
#endif
.id_table = adv7180_id, .id_table = adv7180_id,
}; };

View File

@ -28,7 +28,6 @@
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <media/adv7183.h> #include <media/adv7183.h>
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-device.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); reg = adv7183_read(sd, ADV7183_STATUS_1);
switch ((reg >> 0x4) & 0x7) { switch ((reg >> 0x4) & 0x7) {
case 0: case 0:
*std = V4L2_STD_NTSC; *std &= V4L2_STD_NTSC;
break; break;
case 1: case 1:
*std = V4L2_STD_NTSC_443; *std &= V4L2_STD_NTSC_443;
break; break;
case 2: case 2:
*std = V4L2_STD_PAL_M; *std &= V4L2_STD_PAL_M;
break; break;
case 3: case 3:
*std = V4L2_STD_PAL_60; *std &= V4L2_STD_PAL_60;
break; break;
case 4: case 4:
*std = V4L2_STD_PAL; *std &= V4L2_STD_PAL;
break; break;
case 5: case 5:
*std = V4L2_STD_SECAM; *std &= V4L2_STD_SECAM;
break; break;
case 6: case 6:
*std = V4L2_STD_PAL_Nc; *std &= V4L2_STD_PAL_Nc;
break; break;
case 7: case 7:
*std = V4L2_STD_SECAM; *std &= V4L2_STD_SECAM;
break; break;
default: default:
*std = V4L2_STD_UNKNOWN; *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); struct adv7183 *decoder = to_adv7183(sd);
if (enable) if (enable)
gpio_direction_output(decoder->oe_pin, 0); gpio_set_value(decoder->oe_pin, 0);
else else
gpio_direction_output(decoder->oe_pin, 1); gpio_set_value(decoder->oe_pin, 1);
udelay(1); udelay(1);
return 0; 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 #ifdef CONFIG_VIDEO_ADV_DEBUG
static int adv7183_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) 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, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
reg->val = adv7183_read(sd, reg->reg & 0xff); reg->val = adv7183_read(sd, reg->reg & 0xff);
reg->size = 1; reg->size = 1;
return 0; 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) 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, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
adv7183_write(sd, reg->reg & 0xff, reg->val & 0xff); adv7183_write(sd, reg->reg & 0xff, reg->val & 0xff);
return 0; return 0;
} }
@ -529,7 +504,6 @@ static const struct v4l2_subdev_core_ops adv7183_core_ops = {
.g_std = adv7183_g_std, .g_std = adv7183_g_std,
.s_std = adv7183_s_std, .s_std = adv7183_s_std,
.reset = adv7183_reset, .reset = adv7183_reset,
.g_chip_ident = adv7183_g_chip_ident,
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
.g_register = adv7183_g_register, .g_register = adv7183_g_register,
.s_register = adv7183_s_register, .s_register = adv7183_s_register,
@ -573,23 +547,24 @@ static int adv7183_probe(struct i2c_client *client,
if (pin_array == NULL) if (pin_array == NULL)
return -EINVAL; return -EINVAL;
decoder = kzalloc(sizeof(struct adv7183), GFP_KERNEL); decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL);
if (decoder == NULL) if (decoder == NULL)
return -ENOMEM; return -ENOMEM;
decoder->reset_pin = pin_array[0]; decoder->reset_pin = pin_array[0];
decoder->oe_pin = pin_array[1]; 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); v4l_err(client, "failed to request GPIO %d\n", decoder->reset_pin);
ret = -EBUSY; return -EBUSY;
goto err_free_decoder;
} }
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); v4l_err(client, "failed to request GPIO %d\n", decoder->oe_pin);
ret = -EBUSY; return -EBUSY;
goto err_free_reset;
} }
sd = &decoder->sd; sd = &decoder->sd;
@ -611,7 +586,7 @@ static int adv7183_probe(struct i2c_client *client,
ret = hdl->error; ret = hdl->error;
v4l2_ctrl_handler_free(hdl); v4l2_ctrl_handler_free(hdl);
goto err_free_oe; return ret;
} }
/* v4l2 doesn't support an autodetect standard, pick PAL as default */ /* 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->input = ADV7183_COMPOSITE4;
decoder->output = ADV7183_8BIT_OUT; decoder->output = ADV7183_8BIT_OUT;
gpio_direction_output(decoder->oe_pin, 1);
/* reset chip */ /* reset chip */
gpio_direction_output(decoder->reset_pin, 0);
/* reset pulse width at least 5ms */ /* reset pulse width at least 5ms */
mdelay(10); 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 */ /* wait 5ms before any further i2c writes are performed */
mdelay(5); mdelay(5);
@ -638,29 +611,18 @@ static int adv7183_probe(struct i2c_client *client,
ret = v4l2_ctrl_handler_setup(hdl); ret = v4l2_ctrl_handler_setup(hdl);
if (ret) { if (ret) {
v4l2_ctrl_handler_free(hdl); v4l2_ctrl_handler_free(hdl);
goto err_free_oe; return ret;
} }
return 0; 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) static int adv7183_remove(struct i2c_client *client)
{ {
struct v4l2_subdev *sd = i2c_get_clientdata(client); struct v4l2_subdev *sd = i2c_get_clientdata(client);
struct adv7183 *decoder = to_adv7183(sd);
v4l2_device_unregister_subdev(sd); v4l2_device_unregister_subdev(sd);
v4l2_ctrl_handler_free(sd->ctrl_handler); v4l2_ctrl_handler_free(sd->ctrl_handler);
gpio_free(decoder->oe_pin);
gpio_free(decoder->reset_pin);
kfree(decoder);
return 0; return 0;
} }

View File

@ -28,7 +28,6 @@
#include <media/adv7343.h> #include <media/adv7343.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include "adv7343_regs.h" #include "adv7343_regs.h"
@ -311,21 +310,12 @@ static int adv7343_s_ctrl(struct v4l2_ctrl *ctrl)
return -EINVAL; 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 = { static const struct v4l2_ctrl_ops adv7343_ctrl_ops = {
.s_ctrl = adv7343_s_ctrl, .s_ctrl = adv7343_s_ctrl,
}; };
static const struct v4l2_subdev_core_ops adv7343_core_ops = { static const struct v4l2_subdev_core_ops adv7343_core_ops = {
.log_status = adv7343_log_status, .log_status = adv7343_log_status,
.g_chip_ident = adv7343_g_chip_ident,
.g_ext_ctrls = v4l2_subdev_g_ext_ctrls, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
.try_ext_ctrls = v4l2_subdev_try_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
.s_ext_ctrls = v4l2_subdev_s_ext_ctrls, .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,

View File

@ -33,7 +33,6 @@
#include <media/adv7393.h> #include <media/adv7393.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include "adv7393_regs.h" #include "adv7393_regs.h"
@ -301,21 +300,12 @@ static int adv7393_s_ctrl(struct v4l2_ctrl *ctrl)
return -EINVAL; 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 = { static const struct v4l2_ctrl_ops adv7393_ctrl_ops = {
.s_ctrl = adv7393_s_ctrl, .s_ctrl = adv7393_s_ctrl,
}; };
static const struct v4l2_subdev_core_ops adv7393_core_ops = { static const struct v4l2_subdev_core_ops adv7393_core_ops = {
.log_status = adv7393_log_status, .log_status = adv7393_log_status,
.g_chip_ident = adv7393_g_chip_ident,
.g_ext_ctrls = v4l2_subdev_g_ext_ctrls, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
.try_ext_ctrls = v4l2_subdev_try_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
.s_ext_ctrls = v4l2_subdev_s_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", v4l_info(client, "chip found @ 0x%x (%s)\n",
client->addr << 1, client->adapter->name); 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) if (state == NULL)
return -ENOMEM; return -ENOMEM;
@ -444,16 +434,13 @@ static int adv7393_probe(struct i2c_client *client,
int err = state->hdl.error; int err = state->hdl.error;
v4l2_ctrl_handler_free(&state->hdl); v4l2_ctrl_handler_free(&state->hdl);
kfree(state);
return err; return err;
} }
v4l2_ctrl_handler_setup(&state->hdl); v4l2_ctrl_handler_setup(&state->hdl);
err = adv7393_initialize(&state->sd); err = adv7393_initialize(&state->sd);
if (err) { if (err)
v4l2_ctrl_handler_free(&state->hdl); v4l2_ctrl_handler_free(&state->hdl);
kfree(state);
}
return err; return err;
} }
@ -464,7 +451,6 @@ static int adv7393_remove(struct i2c_client *client)
v4l2_device_unregister_subdev(sd); v4l2_device_unregister_subdev(sd);
v4l2_ctrl_handler_free(&state->hdl); v4l2_ctrl_handler_free(&state->hdl);
kfree(state);
return 0; return 0;
} }

View File

@ -38,7 +38,6 @@
#include <linux/v4l2-dv-timings.h> #include <linux/v4l2-dv-timings.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-chip-ident.h>
#include <media/adv7604.h> #include <media/adv7604.h>
static int debug; 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, static int adv7604_g_register(struct v4l2_subdev *sd,
struct v4l2_dbg_register *reg) struct v4l2_dbg_register *reg)
{ {
struct i2c_client *client = v4l2_get_subdevdata(sd);
if (!v4l2_chip_match_i2c_client(client, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
reg->size = 1; reg->size = 1;
switch (reg->reg >> 8) { switch (reg->reg >> 8) {
case 0: case 0:
@ -701,12 +694,6 @@ static int adv7604_g_register(struct v4l2_subdev *sd,
static int adv7604_s_register(struct v4l2_subdev *sd, static int adv7604_s_register(struct v4l2_subdev *sd,
const struct v4l2_dbg_register *reg) const struct v4l2_dbg_register *reg)
{ {
struct i2c_client *client = v4l2_get_subdevdata(sd);
if (!v4l2_chip_match_i2c_client(client, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
switch (reg->reg >> 8) { switch (reg->reg >> 8) {
case 0: case 0:
io_write(sd, reg->reg & 0xff, reg->val & 0xff); io_write(sd, reg->reg & 0xff, reg->val & 0xff);
@ -984,14 +971,6 @@ static int adv7604_s_ctrl(struct v4l2_ctrl *ctrl)
return -EINVAL; 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) 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, .s_ctrl = v4l2_subdev_s_ctrl,
.queryctrl = v4l2_subdev_queryctrl, .queryctrl = v4l2_subdev_queryctrl,
.querymenu = v4l2_subdev_querymenu, .querymenu = v4l2_subdev_querymenu,
.g_chip_ident = adv7604_g_chip_ident,
.interrupt_service_routine = adv7604_isr, .interrupt_service_routine = adv7604_isr,
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
.g_register = adv7604_g_register, .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", v4l_dbg(1, debug, client, "detecting adv7604 client on address 0x%x\n",
client->addr << 1); client->addr << 1);
state = kzalloc(sizeof(struct adv7604_state), GFP_KERNEL); state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
if (!state) { if (!state) {
v4l_err(client, "Could not allocate adv7604_state memory!\n"); v4l_err(client, "Could not allocate adv7604_state memory!\n");
return -ENOMEM; return -ENOMEM;
@ -1977,8 +1955,7 @@ static int adv7604_probe(struct i2c_client *client,
/* platform data */ /* platform data */
if (!pdata) { if (!pdata) {
v4l_err(client, "No platform data!\n"); v4l_err(client, "No platform data!\n");
err = -ENODEV; return -ENODEV;
goto err_state;
} }
memcpy(&state->pdata, pdata, sizeof(state->pdata)); 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) { if (adv_smbus_read_byte_data_check(client, 0xfb, false) != 0x68) {
v4l2_info(sd, "not an adv7604 on address 0x%x\n", v4l2_info(sd, "not an adv7604 on address 0x%x\n",
client->addr << 1); client->addr << 1);
err = -ENODEV; return -ENODEV;
goto err_state;
} }
/* control handlers */ /* control handlers */
@ -2093,8 +2069,6 @@ err_i2c:
adv7604_unregister_clients(state); adv7604_unregister_clients(state);
err_hdl: err_hdl:
v4l2_ctrl_handler_free(hdl); v4l2_ctrl_handler_free(hdl);
err_state:
kfree(state);
return err; return err;
} }
@ -2111,7 +2085,6 @@ static int adv7604_remove(struct i2c_client *client)
media_entity_cleanup(&sd->entity); media_entity_cleanup(&sd->entity);
adv7604_unregister_clients(to_state(sd)); adv7604_unregister_clients(to_state(sd));
v4l2_ctrl_handler_free(sd->ctrl_handler); v4l2_ctrl_handler_free(sd->ctrl_handler);
kfree(to_state(sd));
return 0; return 0;
} }

View File

@ -16,7 +16,6 @@
#include <linux/module.h> #include <linux/module.h>
#include <media/ak881x.h> #include <media/ak881x.h>
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
@ -33,7 +32,6 @@ struct ak881x {
struct v4l2_subdev subdev; struct v4l2_subdev subdev;
struct ak881x_pdata *pdata; struct ak881x_pdata *pdata;
unsigned int lines; unsigned int lines;
int id; /* DEVICE_ID code V4L2_IDENT_AK881X code from v4l2-chip-ident.h */
char revision; /* DEVICE_REVISION content */ 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); 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 #ifdef CONFIG_VIDEO_ADV_DEBUG
static int ak881x_g_register(struct v4l2_subdev *sd, static int ak881x_g_register(struct v4l2_subdev *sd,
struct v4l2_dbg_register *reg) struct v4l2_dbg_register *reg)
{ {
struct i2c_client *client = v4l2_get_subdevdata(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; return -EINVAL;
if (reg->match.addr != client->addr) reg->size = 1;
return -ENODEV;
reg->val = reg_read(client, reg->reg); reg->val = reg_read(client, reg->reg);
if (reg->val > 0xffff) 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); 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; return -EINVAL;
if (reg->match.addr != client->addr)
return -ENODEV;
if (reg_write(client, reg->reg, reg->val) < 0) if (reg_write(client, reg->reg, reg->val) < 0)
return -EIO; 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 = { static struct v4l2_subdev_core_ops ak881x_subdev_core_ops = {
.g_chip_ident = ak881x_g_chip_ident,
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
.g_register = ak881x_g_register, .g_register = ak881x_g_register,
.s_register = ak881x_s_register, .s_register = ak881x_s_register,
@ -264,7 +238,7 @@ static int ak881x_probe(struct i2c_client *client,
return -EIO; return -EIO;
} }
ak881x = kzalloc(sizeof(struct ak881x), GFP_KERNEL); ak881x = devm_kzalloc(&client->dev, sizeof(*ak881x), GFP_KERNEL);
if (!ak881x) if (!ak881x)
return -ENOMEM; return -ENOMEM;
@ -274,15 +248,11 @@ static int ak881x_probe(struct i2c_client *client,
switch (data) { switch (data) {
case 0x13: case 0x13:
ak881x->id = V4L2_IDENT_AK8813;
break;
case 0x14: case 0x14:
ak881x->id = V4L2_IDENT_AK8814;
break; break;
default: default:
dev_err(&client->dev, dev_err(&client->dev,
"No ak881x chip detected, register read %x\n", data); "No ak881x chip detected, register read %x\n", data);
kfree(ak881x);
return -ENODEV; return -ENODEV;
} }
@ -331,7 +301,6 @@ static int ak881x_remove(struct i2c_client *client)
struct ak881x *ak881x = to_ak881x(client); struct ak881x *ak881x = to_ak881x(client);
v4l2_device_unregister_subdev(&ak881x->subdev); v4l2_device_unregister_subdev(&ak881x->subdev);
kfree(ak881x);
return 0; return 0;
} }

View File

@ -813,7 +813,7 @@ static int as3645a_probe(struct i2c_client *client,
if (client->dev.platform_data == NULL) if (client->dev.platform_data == NULL)
return -ENODEV; return -ENODEV;
flash = kzalloc(sizeof(*flash), GFP_KERNEL); flash = devm_kzalloc(&client->dev, sizeof(*flash), GFP_KERNEL);
if (flash == NULL) if (flash == NULL)
return -ENOMEM; return -ENOMEM;
@ -838,10 +838,8 @@ static int as3645a_probe(struct i2c_client *client,
flash->led_mode = V4L2_FLASH_LED_MODE_NONE; flash->led_mode = V4L2_FLASH_LED_MODE_NONE;
done: done:
if (ret < 0) { if (ret < 0)
v4l2_ctrl_handler_free(&flash->ctrls); v4l2_ctrl_handler_free(&flash->ctrls);
kfree(flash);
}
return ret; return ret;
} }
@ -855,7 +853,6 @@ static int as3645a_remove(struct i2c_client *client)
v4l2_ctrl_handler_free(&flash->ctrls); v4l2_ctrl_handler_free(&flash->ctrls);
media_entity_cleanup(&flash->subdev.entity); media_entity_cleanup(&flash->subdev.entity);
mutex_destroy(&flash->power_lock); mutex_destroy(&flash->power_lock);
kfree(flash);
return 0; return 0;
} }

View File

@ -36,7 +36,6 @@
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/bt819.h> #include <media/bt819.h>
@ -57,7 +56,6 @@ struct bt819 {
unsigned char reg[32]; unsigned char reg[32];
v4l2_std_id norm; v4l2_std_id norm;
int ident;
int input; int input;
int enable; 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); struct bt819 *decoder = to_bt819(sd);
int status = bt819_read(decoder, 0x00); int status = bt819_read(decoder, 0x00);
int res = V4L2_IN_ST_NO_SIGNAL; int res = V4L2_IN_ST_NO_SIGNAL;
v4l2_std_id std; v4l2_std_id std = pstd ? *pstd : V4L2_STD_ALL;
if ((status & 0x80)) if ((status & 0x80))
res = 0; res = 0;
else
std = V4L2_STD_UNKNOWN;
if ((status & 0x10)) if ((status & 0x10))
std = V4L2_STD_PAL; std &= V4L2_STD_PAL;
else else
std = V4L2_STD_NTSC; std &= V4L2_STD_NTSC;
if (pstd) if (pstd)
*pstd = std; *pstd = std;
if (pstatus) if (pstatus)
@ -373,14 +373,6 @@ static int bt819_s_ctrl(struct v4l2_ctrl *ctrl)
return 0; 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 = { 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 = { 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, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
.try_ext_ctrls = v4l2_subdev_try_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
.s_ext_ctrls = v4l2_subdev_s_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)) if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV; return -ENODEV;
decoder = kzalloc(sizeof(struct bt819), GFP_KERNEL); decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL);
if (decoder == NULL) if (decoder == NULL)
return -ENOMEM; return -ENOMEM;
sd = &decoder->sd; sd = &decoder->sd;
@ -435,15 +426,12 @@ static int bt819_probe(struct i2c_client *client,
switch (ver & 0xf0) { switch (ver & 0xf0) {
case 0x70: case 0x70:
name = "bt819a"; name = "bt819a";
decoder->ident = V4L2_IDENT_BT819A;
break; break;
case 0x60: case 0x60:
name = "bt817a"; name = "bt817a";
decoder->ident = V4L2_IDENT_BT817A;
break; break;
case 0x20: case 0x20:
name = "bt815a"; name = "bt815a";
decoder->ident = V4L2_IDENT_BT815A;
break; break;
default: default:
v4l2_dbg(1, debug, sd, v4l2_dbg(1, debug, sd,
@ -476,7 +464,6 @@ static int bt819_probe(struct i2c_client *client,
int err = decoder->hdl.error; int err = decoder->hdl.error;
v4l2_ctrl_handler_free(&decoder->hdl); v4l2_ctrl_handler_free(&decoder->hdl);
kfree(decoder);
return err; return err;
} }
v4l2_ctrl_handler_setup(&decoder->hdl); v4l2_ctrl_handler_setup(&decoder->hdl);
@ -490,7 +477,6 @@ static int bt819_remove(struct i2c_client *client)
v4l2_device_unregister_subdev(sd); v4l2_device_unregister_subdev(sd);
v4l2_ctrl_handler_free(&decoder->hdl); v4l2_ctrl_handler_free(&decoder->hdl);
kfree(decoder);
return 0; return 0;
} }

View File

@ -36,7 +36,6 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-chip-ident.h>
MODULE_DESCRIPTION("Brooktree-856A video encoder driver"); MODULE_DESCRIPTION("Brooktree-856A video encoder driver");
MODULE_AUTHOR("Mike Bernson & Dave Perks"); MODULE_AUTHOR("Mike Bernson & Dave Perks");
@ -177,17 +176,9 @@ static int bt856_s_routing(struct v4l2_subdev *sd,
return 0; 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 = { static const struct v4l2_subdev_core_ops bt856_core_ops = {
.g_chip_ident = bt856_g_chip_ident,
.init = bt856_init, .init = bt856_init,
}; };
@ -216,7 +207,7 @@ static int bt856_probe(struct i2c_client *client,
v4l_info(client, "chip found @ 0x%x (%s)\n", v4l_info(client, "chip found @ 0x%x (%s)\n",
client->addr << 1, client->adapter->name); 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) if (encoder == NULL)
return -ENOMEM; return -ENOMEM;
sd = &encoder->sd; sd = &encoder->sd;
@ -250,7 +241,6 @@ static int bt856_remove(struct i2c_client *client)
struct v4l2_subdev *sd = i2c_get_clientdata(client); struct v4l2_subdev *sd = i2c_get_clientdata(client);
v4l2_device_unregister_subdev(sd); v4l2_device_unregister_subdev(sd);
kfree(to_bt856(sd));
return 0; return 0;
} }

View File

@ -36,7 +36,6 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-chip-ident.h>
MODULE_DESCRIPTION("Brooktree-866 video encoder driver"); MODULE_DESCRIPTION("Brooktree-866 video encoder driver");
MODULE_AUTHOR("Mike Bernson & Dave Perks"); MODULE_AUTHOR("Mike Bernson & Dave Perks");
@ -175,26 +174,14 @@ static int bt866_s_routing(struct v4l2_subdev *sd,
bt866_write(client, 0xdc, val); bt866_write(client, 0xdc, val);
#endif #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 = { static const struct v4l2_subdev_video_ops bt866_video_ops = {
.s_std_output = bt866_s_std_output, .s_std_output = bt866_s_std_output,
.s_routing = bt866_s_routing, .s_routing = bt866_s_routing,
}; };
static const struct v4l2_subdev_ops bt866_ops = { static const struct v4l2_subdev_ops bt866_ops = {
.core = &bt866_core_ops,
.video = &bt866_video_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", v4l_info(client, "chip found @ 0x%x (%s)\n",
client->addr << 1, client->adapter->name); client->addr << 1, client->adapter->name);
encoder = kzalloc(sizeof(*encoder), GFP_KERNEL); encoder = devm_kzalloc(&client->dev, sizeof(*encoder), GFP_KERNEL);
if (encoder == NULL) if (encoder == NULL)
return -ENOMEM; return -ENOMEM;
sd = &encoder->sd; sd = &encoder->sd;
@ -220,7 +207,6 @@ static int bt866_remove(struct i2c_client *client)
struct v4l2_subdev *sd = i2c_get_clientdata(client); struct v4l2_subdev *sd = i2c_get_clientdata(client);
v4l2_device_unregister_subdev(sd); v4l2_device_unregister_subdev(sd);
kfree(to_bt866(sd));
return 0; return 0;
} }

View File

@ -24,7 +24,6 @@
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
MODULE_DESCRIPTION("i2c device driver for cs5345 Audio ADC"); 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 #ifdef CONFIG_VIDEO_ADV_DEBUG
static int cs5345_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) 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, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
reg->size = 1; reg->size = 1;
reg->val = cs5345_read(sd, reg->reg & 0x1f); reg->val = cs5345_read(sd, reg->reg & 0x1f);
return 0; 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) 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, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
cs5345_write(sd, reg->reg & 0x1f, reg->val & 0xff); cs5345_write(sd, reg->reg & 0x1f, reg->val & 0xff);
return 0; return 0;
} }
#endif #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) static int cs5345_log_status(struct v4l2_subdev *sd)
{ {
u8 v = cs5345_read(sd, 0x09) & 7; 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 = { static const struct v4l2_subdev_core_ops cs5345_core_ops = {
.log_status = cs5345_log_status, .log_status = cs5345_log_status,
.g_chip_ident = cs5345_g_chip_ident,
.g_ext_ctrls = v4l2_subdev_g_ext_ctrls, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
.try_ext_ctrls = v4l2_subdev_try_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
.s_ext_ctrls = v4l2_subdev_s_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", v4l_info(client, "chip found @ 0x%x (%s)\n",
client->addr << 1, client->adapter->name); 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) if (state == NULL)
return -ENOMEM; return -ENOMEM;
sd = &state->sd; sd = &state->sd;
@ -206,7 +185,6 @@ static int cs5345_probe(struct i2c_client *client,
int err = state->hdl.error; int err = state->hdl.error;
v4l2_ctrl_handler_free(&state->hdl); v4l2_ctrl_handler_free(&state->hdl);
kfree(state);
return err; return err;
} }
/* set volume/mute */ /* set volume/mute */
@ -227,7 +205,6 @@ static int cs5345_remove(struct i2c_client *client)
v4l2_device_unregister_subdev(sd); v4l2_device_unregister_subdev(sd);
v4l2_ctrl_handler_free(&state->hdl); v4l2_ctrl_handler_free(&state->hdl);
kfree(state);
return 0; return 0;
} }

View File

@ -28,7 +28,6 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
MODULE_DESCRIPTION("i2c device driver for cs53l32a Audio ADC"); MODULE_DESCRIPTION("i2c device driver for cs53l32a Audio ADC");
@ -104,14 +103,6 @@ static int cs53l32a_s_ctrl(struct v4l2_ctrl *ctrl)
return -EINVAL; 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) static int cs53l32a_log_status(struct v4l2_subdev *sd)
{ {
struct cs53l32a_state *state = to_state(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 = { static const struct v4l2_subdev_core_ops cs53l32a_core_ops = {
.log_status = cs53l32a_log_status, .log_status = cs53l32a_log_status,
.g_chip_ident = cs53l32a_g_chip_ident,
.g_ext_ctrls = v4l2_subdev_g_ext_ctrls, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
.try_ext_ctrls = v4l2_subdev_try_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
.s_ext_ctrls = v4l2_subdev_s_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", v4l_info(client, "chip found @ 0x%x (%s)\n",
client->addr << 1, client->adapter->name); 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) if (state == NULL)
return -ENOMEM; return -ENOMEM;
sd = &state->sd; sd = &state->sd;
@ -197,7 +187,6 @@ static int cs53l32a_probe(struct i2c_client *client,
int err = state->hdl.error; int err = state->hdl.error;
v4l2_ctrl_handler_free(&state->hdl); v4l2_ctrl_handler_free(&state->hdl);
kfree(state);
return err; return err;
} }
@ -228,7 +217,6 @@ static int cs53l32a_remove(struct i2c_client *client)
v4l2_device_unregister_subdev(sd); v4l2_device_unregister_subdev(sd);
v4l2_ctrl_handler_free(&state->hdl); v4l2_ctrl_handler_free(&state->hdl);
kfree(state);
return 0; return 0;
} }

View File

@ -45,7 +45,6 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/math64.h> #include <linux/math64.h>
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include <media/v4l2-chip-ident.h>
#include <media/cx25840.h> #include <media/cx25840.h>
#include "cx25840-core.h" #include "cx25840-core.h"
@ -498,7 +497,7 @@ static void cx23885_initialize(struct i2c_client *client)
/* Sys PLL */ /* Sys PLL */
switch (state->id) { switch (state->id) {
case V4L2_IDENT_CX23888_AV: case CX23888_AV:
/* /*
* 50.0 MHz * (0xb + 0xe8ba26/0x2000000)/4 = 5 * 28.636363 MHz * 50.0 MHz * (0xb + 0xe8ba26/0x2000000)/4 = 5 * 28.636363 MHz
* 572.73 MHz before post divide * 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, 0x42c, 0x42600000);
cx25840_write4(client, 0x44c, 0x161f1000); cx25840_write4(client, 0x44c, 0x161f1000);
break; break;
case V4L2_IDENT_CX23887_AV: case CX23887_AV:
/* /*
* 25.0 MHz * (0x16 + 0x1d1744c/0x2000000)/4 = 5 * 28.636363 MHz * 25.0 MHz * (0x16 + 0x1d1744c/0x2000000)/4 = 5 * 28.636363 MHz
* 572.73 MHz before post divide * 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, 0x11c, 0x01d1744c);
cx25840_write4(client, 0x118, 0x00000416); cx25840_write4(client, 0x118, 0x00000416);
break; break;
case V4L2_IDENT_CX23885_AV: case CX23885_AV:
default: default:
/* /*
* 28.636363 MHz * (0x14 + 0x0/0x2000000)/4 = 5 * 28.636363 MHz * 28.636363 MHz * (0x14 + 0x0/0x2000000)/4 = 5 * 28.636363 MHz
@ -546,7 +545,7 @@ static void cx23885_initialize(struct i2c_client *client)
/* HVR1850 */ /* HVR1850 */
switch (state->id) { switch (state->id) {
case V4L2_IDENT_CX23888_AV: case CX23888_AV:
/* 888/HVR1250 specific */ /* 888/HVR1250 specific */
cx25840_write4(client, 0x10c, 0x13333333); cx25840_write4(client, 0x10c, 0x13333333);
cx25840_write4(client, 0x108, 0x00000515); 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 * 48 ksps, 16 bits/sample, x16 multiplier = 12.288 MHz
*/ */
switch (state->id) { switch (state->id) {
case V4L2_IDENT_CX23888_AV: case CX23888_AV:
/* /*
* 50.0 MHz * (0x7 + 0x0bedfa4/0x2000000)/3 = 122.88 MHz * 50.0 MHz * (0x7 + 0x0bedfa4/0x2000000)/3 = 122.88 MHz
* 368.64 MHz before post divide * 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, 0x114, 0x017dbf48);
cx25840_write4(client, 0x110, 0x000a030e); cx25840_write4(client, 0x110, 0x000a030e);
break; break;
case V4L2_IDENT_CX23887_AV: case CX23887_AV:
/* /*
* 25.0 MHz * (0xe + 0x17dbf48/0x2000000)/3 = 122.88 MHz * 25.0 MHz * (0xe + 0x17dbf48/0x2000000)/3 = 122.88 MHz
* 368.64 MHz before post divide * 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, 0x114, 0x017dbf48);
cx25840_write4(client, 0x110, 0x000a030e); cx25840_write4(client, 0x110, 0x000a030e);
break; break;
case V4L2_IDENT_CX23885_AV: case CX23885_AV:
default: default:
/* /*
* 28.636363 MHz * (0xc + 0x1bf0c9e/0x2000000)/3 = 122.88 MHz * 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); struct i2c_client *client = v4l2_get_subdevdata(sd);
if (!v4l2_chip_match_i2c_client(client, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
reg->size = 1; reg->size = 1;
reg->val = cx25840_read(client, reg->reg & 0x0fff); reg->val = cx25840_read(client, reg->reg & 0x0fff);
return 0; 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); struct i2c_client *client = v4l2_get_subdevdata(sd);
if (!v4l2_chip_match_i2c_client(client, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
cx25840_write(client, reg->reg & 0x0fff, reg->val & 0xff); cx25840_write(client, reg->reg & 0x0fff, reg->val & 0xff);
return 0; return 0;
} }
@ -1938,14 +1929,6 @@ static int cx25840_reset(struct v4l2_subdev *sd, u32 val)
return 0; 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) static int cx25840_log_status(struct v4l2_subdev *sd)
{ {
struct cx25840_state *state = to_state(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 = { static const struct v4l2_subdev_core_ops cx25840_core_ops = {
.log_status = cx25840_log_status, .log_status = cx25840_log_status,
.g_chip_ident = cx25840_g_chip_ident,
.g_ctrl = v4l2_subdev_g_ctrl, .g_ctrl = v4l2_subdev_g_ctrl,
.s_ctrl = v4l2_subdev_s_ctrl, .s_ctrl = v4l2_subdev_s_ctrl,
.s_ext_ctrls = v4l2_subdev_s_ext_ctrls, .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); ret = cx25840_read4(client, 0x300);
if (((ret & 0xffff0000) >> 16) == (ret & 0xffff)) { if (((ret & 0xffff0000) >> 16) == (ret & 0xffff)) {
/* No DIF */ /* No DIF */
ret = V4L2_IDENT_CX23885_AV; ret = CX23885_AV;
} else { } else {
/* CX23887 has a broken DIF, but the registers /* CX23887 has a broken DIF, but the registers
* appear valid (but unused), good enough to detect. */ * appear valid (but unused), good enough to detect. */
ret = V4L2_IDENT_CX23887_AV; ret = CX23887_AV;
} }
} else if (cx25840_read4(client, 0x300) & 0x0fffffff) { } else if (cx25840_read4(client, 0x300) & 0x0fffffff) {
/* DIF PLL Freq Word reg exists; chip must be a CX23888 */ /* DIF PLL Freq Word reg exists; chip must be a CX23888 */
ret = V4L2_IDENT_CX23888_AV; ret = CX23888_AV;
} else { } else {
v4l_err(client, "Unable to detect h/w, assuming cx23887\n"); v4l_err(client, "Unable to detect h/w, assuming cx23887\n");
ret = V4L2_IDENT_CX23887_AV; ret = CX23887_AV;
} }
/* Back into digital power down */ /* Back into digital power down */
@ -5153,7 +5135,7 @@ static int cx25840_probe(struct i2c_client *client,
struct cx25840_state *state; struct cx25840_state *state;
struct v4l2_subdev *sd; struct v4l2_subdev *sd;
int default_volume; int default_volume;
u32 id = V4L2_IDENT_NONE; u32 id;
u16 device_id; u16 device_id;
/* Check if the adapter supports the needed features */ /* 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 /* The high byte of the device ID should be
* 0x83 for the cx2583x and 0x84 for the cx2584x */ * 0x83 for the cx2583x and 0x84 for the cx2584x */
if ((device_id & 0xff00) == 0x8300) { 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) { } 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) { } else if (device_id == 0x0000) {
id = get_cx2388x_ident(client); id = get_cx2388x_ident(client);
} else if ((device_id & 0xfff0) == 0x5A30) { } else if ((device_id & 0xfff0) == 0x5A30) {
/* The CX23100 (0x5A3C = 23100) doesn't have an A/V decoder */ /* 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)) { } else if ((device_id & 0xff) == (device_id >> 8)) {
v4l_err(client, v4l_err(client,
"likely a confused/unresponsive cx2388[578] A/V decoder" "likely a confused/unresponsive cx2388[578] A/V decoder"
@ -5190,7 +5172,7 @@ static int cx25840_probe(struct i2c_client *client,
return -ENODEV; return -ENODEV;
} }
state = kzalloc(sizeof(struct cx25840_state), GFP_KERNEL); state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
if (state == NULL) if (state == NULL)
return -ENOMEM; return -ENOMEM;
@ -5198,26 +5180,26 @@ static int cx25840_probe(struct i2c_client *client,
v4l2_i2c_subdev_init(sd, client, &cx25840_ops); v4l2_i2c_subdev_init(sd, client, &cx25840_ops);
switch (id) { switch (id) {
case V4L2_IDENT_CX23885_AV: case CX23885_AV:
v4l_info(client, "cx23885 A/V decoder found @ 0x%x (%s)\n", v4l_info(client, "cx23885 A/V decoder found @ 0x%x (%s)\n",
client->addr << 1, client->adapter->name); client->addr << 1, client->adapter->name);
break; break;
case V4L2_IDENT_CX23887_AV: case CX23887_AV:
v4l_info(client, "cx23887 A/V decoder found @ 0x%x (%s)\n", v4l_info(client, "cx23887 A/V decoder found @ 0x%x (%s)\n",
client->addr << 1, client->adapter->name); client->addr << 1, client->adapter->name);
break; break;
case V4L2_IDENT_CX23888_AV: case CX23888_AV:
v4l_info(client, "cx23888 A/V decoder found @ 0x%x (%s)\n", v4l_info(client, "cx23888 A/V decoder found @ 0x%x (%s)\n",
client->addr << 1, client->adapter->name); client->addr << 1, client->adapter->name);
break; break;
case V4L2_IDENT_CX2310X_AV: case CX2310X_AV:
v4l_info(client, "cx%d A/V decoder found @ 0x%x (%s)\n", v4l_info(client, "cx%d A/V decoder found @ 0x%x (%s)\n",
device_id, client->addr << 1, client->adapter->name); device_id, client->addr << 1, client->adapter->name);
break; break;
case V4L2_IDENT_CX25840: case CX25840:
case V4L2_IDENT_CX25841: case CX25841:
case V4L2_IDENT_CX25842: case CX25842:
case V4L2_IDENT_CX25843: case CX25843:
/* Note: revision '(device_id & 0x0f) == 2' was never built. The /* Note: revision '(device_id & 0x0f) == 2' was never built. The
marking skips from 0x1 == 22 to 0x3 == 23. */ marking skips from 0x1 == 22 to 0x3 == 23. */
v4l_info(client, "cx25%3x-2%x found @ 0x%x (%s)\n", 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), : (device_id & 0x0f),
client->addr << 1, client->adapter->name); client->addr << 1, client->adapter->name);
break; break;
case V4L2_IDENT_CX25836: case CX25836:
case V4L2_IDENT_CX25837: case CX25837:
default: default:
v4l_info(client, "cx25%3x-%x found @ 0x%x (%s)\n", v4l_info(client, "cx25%3x-%x found @ 0x%x (%s)\n",
(device_id & 0xfff0) >> 4, device_id & 0x0f, (device_id & 0xfff0) >> 4, device_id & 0x0f,
@ -5292,7 +5274,6 @@ static int cx25840_probe(struct i2c_client *client,
int err = state->hdl.error; int err = state->hdl.error;
v4l2_ctrl_handler_free(&state->hdl); v4l2_ctrl_handler_free(&state->hdl);
kfree(state);
return err; return err;
} }
if (!is_cx2583x(state)) if (!is_cx2583x(state))
@ -5317,7 +5298,6 @@ static int cx25840_remove(struct i2c_client *client)
cx25840_ir_remove(sd); cx25840_ir_remove(sd);
v4l2_device_unregister_subdev(sd); v4l2_device_unregister_subdev(sd);
v4l2_ctrl_handler_free(&state->hdl); v4l2_ctrl_handler_free(&state->hdl);
kfree(state);
return 0; return 0;
} }

View File

@ -23,12 +23,24 @@
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <linux/i2c.h> #include <linux/i2c.h>
struct cx25840_ir_state; 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 cx25840_state {
struct i2c_client *c; struct i2c_client *c;
struct v4l2_subdev sd; struct v4l2_subdev sd;
@ -46,7 +58,7 @@ struct cx25840_state {
u32 audclk_freq; u32 audclk_freq;
int audmode; int audmode;
int vbi_line_offset; int vbi_line_offset;
u32 id; enum cx25840_model id;
u32 rev; u32 rev;
int is_initialized; int is_initialized;
wait_queue_head_t fw_wait; /* wake up when the fw load is finished */ 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) static inline bool is_cx2583x(struct cx25840_state *state)
{ {
return state->id == V4L2_IDENT_CX25836 || return state->id == CX25836 ||
state->id == V4L2_IDENT_CX25837; state->id == CX25837;
} }
static inline bool is_cx231xx(struct cx25840_state *state) 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) static inline bool is_cx2388x(struct cx25840_state *state)
{ {
return state->id == V4L2_IDENT_CX23885_AV || return state->id == CX23885_AV ||
state->id == V4L2_IDENT_CX23887_AV || state->id == CX23887_AV ||
state->id == V4L2_IDENT_CX23888_AV; state->id == CX23888_AV;
} }
static inline bool is_cx23885(struct cx25840_state *state) 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) 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) static inline bool is_cx23888(struct cx25840_state *state)
{ {
return state->id == V4L2_IDENT_CX23888_AV; return state->id == CX23888_AV;
} }
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */

View File

@ -1230,16 +1230,14 @@ int cx25840_ir_probe(struct v4l2_subdev *sd)
if (!(is_cx23885(state) || is_cx23887(state))) if (!(is_cx23885(state) || is_cx23887(state)))
return 0; 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) if (ir_state == NULL)
return -ENOMEM; return -ENOMEM;
spin_lock_init(&ir_state->rx_kfifo_lock); spin_lock_init(&ir_state->rx_kfifo_lock);
if (kfifo_alloc(&ir_state->rx_kfifo, if (kfifo_alloc(&ir_state->rx_kfifo,
CX25840_IR_RX_KFIFO_SIZE, GFP_KERNEL)) { CX25840_IR_RX_KFIFO_SIZE, GFP_KERNEL))
kfree(ir_state);
return -ENOMEM; return -ENOMEM;
}
ir_state->c = state->c; ir_state->c = state->c;
state->ir_state = ir_state; state->ir_state = ir_state;
@ -1273,7 +1271,6 @@ int cx25840_ir_remove(struct v4l2_subdev *sd)
cx25840_ir_tx_shutdown(sd); cx25840_ir_tx_shutdown(sd);
kfifo_free(&ir_state->rx_kfifo); kfifo_free(&ir_state->rx_kfifo);
kfree(ir_state);
state->ir_state = NULL; state->ir_state = NULL;
return 0; return 0;
} }

View File

@ -295,7 +295,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
unsigned short addr = client->addr; unsigned short addr = client->addr;
int err; int err;
ir = kzalloc(sizeof(struct IR_i2c), GFP_KERNEL); ir = devm_kzalloc(&client->dev, sizeof(*ir), GFP_KERNEL);
if (!ir) if (!ir)
return -ENOMEM; return -ENOMEM;
@ -398,10 +398,8 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
* internally * internally
*/ */
rc = rc_allocate_device(); rc = rc_allocate_device();
if (!rc) { if (!rc)
err = -ENOMEM; return -ENOMEM;
goto err_out_free;
}
} }
ir->rc = rc; ir->rc = rc;
@ -454,7 +452,6 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
err_out_free: err_out_free:
/* Only frees rc if it were allocated internally */ /* Only frees rc if it were allocated internally */
rc_free_device(rc); rc_free_device(rc);
kfree(ir);
return err; return err;
} }
@ -470,7 +467,6 @@ static int ir_remove(struct i2c_client *client)
rc_unregister_device(ir->rc); rc_unregister_device(ir->rc);
/* free memory */ /* free memory */
kfree(ir);
return 0; return 0;
} }

View File

@ -42,7 +42,6 @@
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-chip-ident.h>
#include "ks0127.h" #include "ks0127.h"
MODULE_DESCRIPTION("KS0127 video decoder driver"); MODULE_DESCRIPTION("KS0127 video decoder driver");
@ -200,7 +199,6 @@ struct adjust {
struct ks0127 { struct ks0127 {
struct v4l2_subdev sd; struct v4l2_subdev sd;
v4l2_std_id norm; v4l2_std_id norm;
int ident;
u8 regs[256]; 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) static void ks0127_init(struct v4l2_subdev *sd)
{ {
struct ks0127 *ks = to_ks0127(sd);
u8 *table = reg_defaults; u8 *table = reg_defaults;
int i; int i;
ks->ident = V4L2_IDENT_KS0127;
v4l2_dbg(1, debug, sd, "reset\n"); v4l2_dbg(1, debug, sd, "reset\n");
msleep(1); msleep(1);
@ -397,7 +392,6 @@ static void ks0127_init(struct v4l2_subdev *sd)
if ((ks0127_read(sd, KS_STAT) & 0x80) == 0) { if ((ks0127_read(sd, KS_STAT) & 0x80) == 0) {
ks->ident = V4L2_IDENT_KS0122S;
v4l2_dbg(1, debug, sd, "ks0122s found\n"); v4l2_dbg(1, debug, sd, "ks0122s found\n");
return; return;
} }
@ -408,7 +402,6 @@ static void ks0127_init(struct v4l2_subdev *sd)
break; break;
case 9: case 9:
ks->ident = V4L2_IDENT_KS0127B;
v4l2_dbg(1, debug, sd, "ks0127B Revision A found\n"); v4l2_dbg(1, debug, sd, "ks0127B Revision A found\n");
break; 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; int stat = V4L2_IN_ST_NO_SIGNAL;
u8 status; u8 status;
v4l2_std_id std = V4L2_STD_ALL; v4l2_std_id std = pstd ? *pstd : V4L2_STD_ALL;
status = ks0127_read(sd, KS_STAT); status = ks0127_read(sd, KS_STAT);
if (!(status & 0x20)) /* NOVID not set */ if (!(status & 0x20)) /* NOVID not set */
stat = 0; stat = 0;
if (!(status & 0x01)) /* CLOCK set */ if (!(status & 0x01)) { /* CLOCK set */
stat |= V4L2_IN_ST_NO_COLOR; stat |= V4L2_IN_ST_NO_COLOR;
if ((status & 0x08)) /* PALDET set */ std = V4L2_STD_UNKNOWN;
std = V4L2_STD_PAL; } 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 else
std = V4L2_STD_NTSC; std &= V4L2_STD_625_50;
if (pstd) if (pstd)
*pstd = std; *pstd = std;
if (pstatus) if (pstatus)
@ -646,18 +646,9 @@ static int ks0127_g_input_status(struct v4l2_subdev *sd, u32 *status)
return ks0127_status(sd, status, NULL); 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 = { static const struct v4l2_subdev_core_ops ks0127_core_ops = {
.g_chip_ident = ks0127_g_chip_ident,
.s_std = ks0127_s_std, .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 == (I2C_KS0127_ADDON >> 1) ? "addon" : "on-board",
client->addr << 1, client->adapter->name); client->addr << 1, client->adapter->name);
ks = kzalloc(sizeof(*ks), GFP_KERNEL); ks = devm_kzalloc(&client->dev, sizeof(*ks), GFP_KERNEL);
if (ks == NULL) if (ks == NULL)
return -ENOMEM; return -ENOMEM;
sd = &ks->sd; sd = &ks->sd;
@ -708,7 +699,6 @@ static int ks0127_remove(struct i2c_client *client)
v4l2_device_unregister_subdev(sd); v4l2_device_unregister_subdev(sd);
ks0127_write(sd, KS_OFMTA, 0x20); /* tristate */ ks0127_write(sd, KS_OFMTA, 0x20); /* tristate */
ks0127_write(sd, KS_CMDA, 0x2c | 0x80); /* power down */ ks0127_write(sd, KS_CMDA, 0x2c | 0x80); /* power down */
kfree(to_ks0127(sd));
return 0; return 0;
} }

View File

@ -29,7 +29,6 @@
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <media/m52790.h> #include <media/m52790.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-chip-ident.h>
MODULE_DESCRIPTION("i2c device driver for m52790 A/V switch"); MODULE_DESCRIPTION("i2c device driver for m52790 A/V switch");
MODULE_AUTHOR("Hans Verkuil"); 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) static int m52790_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
{ {
struct m52790_state *state = to_state(sd); struct m52790_state *state = to_state(sd);
struct i2c_client *client = v4l2_get_subdevdata(sd);
if (!v4l2_chip_match_i2c_client(client, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (reg->reg != 0) if (reg->reg != 0)
return -EINVAL; return -EINVAL;
reg->size = 1; 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) static int m52790_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
{ {
struct m52790_state *state = to_state(sd); struct m52790_state *state = to_state(sd);
struct i2c_client *client = v4l2_get_subdevdata(sd);
if (!v4l2_chip_match_i2c_client(client, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (reg->reg != 0) if (reg->reg != 0)
return -EINVAL; return -EINVAL;
state->input = reg->val & 0x0303; state->input = reg->val & 0x0303;
@ -114,13 +103,6 @@ static int m52790_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_regis
} }
#endif #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) static int m52790_log_status(struct v4l2_subdev *sd)
{ {
struct m52790_state *state = to_state(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 = { static const struct v4l2_subdev_core_ops m52790_core_ops = {
.log_status = m52790_log_status, .log_status = m52790_log_status,
.g_chip_ident = m52790_g_chip_ident,
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
.g_register = m52790_g_register, .g_register = m52790_g_register,
.s_register = m52790_s_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", v4l_info(client, "chip found @ 0x%x (%s)\n",
client->addr << 1, client->adapter->name); 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) if (state == NULL)
return -ENOMEM; return -ENOMEM;
@ -191,7 +172,6 @@ static int m52790_remove(struct i2c_client *client)
struct v4l2_subdev *sd = i2c_get_clientdata(client); struct v4l2_subdev *sd = i2c_get_clientdata(client);
v4l2_device_unregister_subdev(sd); v4l2_device_unregister_subdev(sd);
kfree(to_state(sd));
return 0; return 0;
} }

View File

@ -930,6 +930,7 @@ static int m5mols_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
const struct m5mols_platform_data *pdata = client->dev.platform_data; const struct m5mols_platform_data *pdata = client->dev.platform_data;
unsigned long gpio_flags;
struct m5mols_info *info; struct m5mols_info *info;
struct v4l2_subdev *sd; struct v4l2_subdev *sd;
int ret; int ret;
@ -949,24 +950,27 @@ static int m5mols_probe(struct i2c_client *client,
return -EINVAL; return -EINVAL;
} }
info = kzalloc(sizeof(struct m5mols_info), GFP_KERNEL); info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);
if (!info) if (!info)
return -ENOMEM; return -ENOMEM;
info->pdata = pdata; info->pdata = pdata;
info->set_power = pdata->set_power; 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) { if (ret) {
dev_err(&client->dev, "Failed to request gpio: %d\n", 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) { if (ret) {
dev_err(&client->dev, "Failed to get regulators: %d\n", ret); dev_err(&client->dev, "Failed to get regulators: %d\n", ret);
goto out_gpio; return ret;
} }
sd = &info->sd; sd = &info->sd;
@ -978,17 +982,17 @@ static int m5mols_probe(struct i2c_client *client,
info->pad.flags = MEDIA_PAD_FL_SOURCE; info->pad.flags = MEDIA_PAD_FL_SOURCE;
ret = media_entity_init(&sd->entity, 1, &info->pad, 0); ret = media_entity_init(&sd->entity, 1, &info->pad, 0);
if (ret < 0) if (ret < 0)
goto out_reg; return ret;
sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR; sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;
init_waitqueue_head(&info->irq_waitq); init_waitqueue_head(&info->irq_waitq);
mutex_init(&info->lock); mutex_init(&info->lock);
ret = request_irq(client->irq, m5mols_irq_handler, ret = devm_request_irq(&client->dev, client->irq, m5mols_irq_handler,
IRQF_TRIGGER_RISING, MODULE_NAME, sd); IRQF_TRIGGER_RISING, MODULE_NAME, sd);
if (ret) { if (ret) {
dev_err(&client->dev, "Interrupt request failed: %d\n", ret); dev_err(&client->dev, "Interrupt request failed: %d\n", ret);
goto out_me; goto error;
} }
info->res_type = M5MOLS_RESTYPE_MONITOR; info->res_type = M5MOLS_RESTYPE_MONITOR;
info->ffmt[0] = m5mols_default_ffmt[0]; 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); ret = m5mols_sensor_power(info, true);
if (ret) if (ret)
goto out_irq; goto error;
ret = m5mols_fw_start(sd); ret = m5mols_fw_start(sd);
if (!ret) if (!ret)
@ -1005,32 +1009,19 @@ static int m5mols_probe(struct i2c_client *client,
ret = m5mols_sensor_power(info, false); ret = m5mols_sensor_power(info, false);
if (!ret) if (!ret)
return 0; return 0;
out_irq: error:
free_irq(client->irq, sd);
out_me:
media_entity_cleanup(&sd->entity); 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; return ret;
} }
static int m5mols_remove(struct i2c_client *client) static int m5mols_remove(struct i2c_client *client)
{ {
struct v4l2_subdev *sd = i2c_get_clientdata(client); struct v4l2_subdev *sd = i2c_get_clientdata(client);
struct m5mols_info *info = to_m5mols(sd);
v4l2_device_unregister_subdev(sd); v4l2_device_unregister_subdev(sd);
v4l2_ctrl_handler_free(sd->ctrl_handler); 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); media_entity_cleanup(&sd->entity);
kfree(info);
return 0; return 0;
} }

View File

@ -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");

View File

@ -570,15 +570,6 @@ static int msp_s_i2s_clock_freq(struct v4l2_subdev *sd, u32 freq)
return 0; 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) static int msp_log_status(struct v4l2_subdev *sd)
{ {
struct msp_state *state = to_state(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 = { static const struct v4l2_subdev_core_ops msp_core_ops = {
.log_status = msp_log_status, .log_status = msp_log_status,
.g_chip_ident = msp_g_chip_ident,
.g_ext_ctrls = v4l2_subdev_g_ext_ctrls, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
.try_ext_ctrls = v4l2_subdev_try_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
.s_ext_ctrls = v4l2_subdev_s_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; return -ENODEV;
} }
state = kzalloc(sizeof(*state), GFP_KERNEL); state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
if (!state) if (!state)
return -ENOMEM; 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)) { if (state->rev1 == -1 || (state->rev1 == 0 && state->rev2 == 0)) {
v4l_dbg(1, msp_debug, client, v4l_dbg(1, msp_debug, client,
"not an msp3400 (cannot read chip version)\n"); "not an msp3400 (cannot read chip version)\n");
kfree(state);
return -ENODEV; return -ENODEV;
} }
@ -827,7 +816,6 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id)
int err = hdl->error; int err = hdl->error;
v4l2_ctrl_handler_free(hdl); v4l2_ctrl_handler_free(hdl);
kfree(state);
return err; return err;
} }
@ -889,7 +877,6 @@ static int msp_remove(struct i2c_client *client)
msp_reset(client); msp_reset(client);
v4l2_ctrl_handler_free(&state->hdl); v4l2_ctrl_handler_free(&state->hdl);
kfree(state);
return 0; return 0;
} }

View File

@ -554,10 +554,8 @@ static int mt9m032_g_register(struct v4l2_subdev *sd,
struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
int val; int val;
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) if (reg->reg > 0xff)
return -EINVAL; return -EINVAL;
if (reg->match.addr != client->addr)
return -ENODEV;
val = mt9m032_read(client, reg->reg); val = mt9m032_read(client, reg->reg);
if (val < 0) if (val < 0)
@ -575,12 +573,9 @@ static int mt9m032_s_register(struct v4l2_subdev *sd,
struct mt9m032 *sensor = to_mt9m032(sd); struct mt9m032 *sensor = to_mt9m032(sd);
struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev); 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; return -EINVAL;
if (reg->match.addr != client->addr)
return -ENODEV;
return mt9m032_write(client, reg->reg, reg->val); return mt9m032_write(client, reg->reg, reg->val);
} }
#endif #endif
@ -730,7 +725,7 @@ static int mt9m032_probe(struct i2c_client *client,
if (!client->dev.platform_data) if (!client->dev.platform_data)
return -ENODEV; return -ENODEV;
sensor = kzalloc(sizeof(*sensor), GFP_KERNEL); sensor = devm_kzalloc(&client->dev, sizeof(*sensor), GFP_KERNEL);
if (sensor == NULL) if (sensor == NULL)
return -ENOMEM; return -ENOMEM;
@ -860,7 +855,6 @@ error_ctrl:
v4l2_ctrl_handler_free(&sensor->ctrls); v4l2_ctrl_handler_free(&sensor->ctrls);
error_sensor: error_sensor:
mutex_destroy(&sensor->lock); mutex_destroy(&sensor->lock);
kfree(sensor);
return ret; return ret;
} }
@ -873,7 +867,6 @@ static int mt9m032_remove(struct i2c_client *client)
v4l2_ctrl_handler_free(&sensor->ctrls); v4l2_ctrl_handler_free(&sensor->ctrls);
media_entity_cleanup(&subdev->entity); media_entity_cleanup(&subdev->entity);
mutex_destroy(&sensor->lock); mutex_destroy(&sensor->lock);
kfree(sensor);
return 0; return 0;
} }

View File

@ -16,18 +16,19 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/module.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/log2.h> #include <linux/log2.h>
#include <linux/module.h>
#include <linux/of_gpio.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <media/mt9p031.h> #include <media/mt9p031.h>
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-of.h>
#include <media/v4l2-subdev.h> #include <media/v4l2-subdev.h>
#include "aptina-pll.h" #include "aptina-pll.h"
@ -124,9 +125,7 @@ struct mt9p031 {
int power_count; int power_count;
struct clk *clk; struct clk *clk;
struct regulator *vaa; struct regulator_bulk_data regulators[3];
struct regulator *vdd;
struct regulator *vdd_io;
enum mt9p031_model model; enum mt9p031_model model;
struct aptina_pll pll; 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) static int mt9p031_power_on(struct mt9p031 *mt9p031)
{ {
int ret;
/* Ensure RESET_BAR is low */ /* Ensure RESET_BAR is low */
if (mt9p031->reset != -1) { if (gpio_is_valid(mt9p031->reset)) {
gpio_set_value(mt9p031->reset, 0); gpio_set_value(mt9p031->reset, 0);
usleep_range(1000, 2000); usleep_range(1000, 2000);
} }
/* Bring up the supplies */ /* Bring up the supplies */
regulator_enable(mt9p031->vdd); ret = regulator_bulk_enable(ARRAY_SIZE(mt9p031->regulators),
regulator_enable(mt9p031->vdd_io); mt9p031->regulators);
regulator_enable(mt9p031->vaa); if (ret < 0)
return ret;
/* Emable clock */ /* Emable clock */
if (mt9p031->clk) if (mt9p031->clk)
clk_prepare_enable(mt9p031->clk); clk_prepare_enable(mt9p031->clk);
/* Now RESET_BAR must be high */ /* Now RESET_BAR must be high */
if (mt9p031->reset != -1) { if (gpio_is_valid(mt9p031->reset)) {
gpio_set_value(mt9p031->reset, 1); gpio_set_value(mt9p031->reset, 1);
usleep_range(1000, 2000); usleep_range(1000, 2000);
} }
@ -297,14 +299,13 @@ static int mt9p031_power_on(struct mt9p031 *mt9p031)
static void mt9p031_power_off(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); gpio_set_value(mt9p031->reset, 0);
usleep_range(1000, 2000); usleep_range(1000, 2000);
} }
regulator_disable(mt9p031->vaa); regulator_bulk_disable(ARRAY_SIZE(mt9p031->regulators),
regulator_disable(mt9p031->vdd_io); mt9p031->regulators);
regulator_disable(mt9p031->vdd);
if (mt9p031->clk) if (mt9p031->clk)
clk_disable_unprepare(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 */ /* Read out the chip version register */
data = mt9p031_read(client, MT9P031_CHIP_VERSION); data = mt9p031_read(client, MT9P031_CHIP_VERSION);
mt9p031_power_off(mt9p031);
if (data != MT9P031_CHIP_VERSION_VALUE) { if (data != MT9P031_CHIP_VERSION_VALUE) {
dev_err(&client->dev, "MT9P031 not detected, wrong version " dev_err(&client->dev, "MT9P031 not detected, wrong version "
"0x%04x\n", data); "0x%04x\n", data);
return -ENODEV; return -ENODEV;
} }
mt9p031_power_off(mt9p031);
dev_info(&client->dev, "MT9P031 detected at address 0x%02x\n", dev_info(&client->dev, "MT9P031 detected at address 0x%02x\n",
client->addr); client->addr);
return ret; return 0;
} }
static int mt9p031_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh) 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 * 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, static int mt9p031_probe(struct i2c_client *client,
const struct i2c_device_id *did) 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 i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
struct mt9p031 *mt9p031; struct mt9p031 *mt9p031;
unsigned int i; unsigned int i;
@ -958,14 +985,14 @@ static int mt9p031_probe(struct i2c_client *client,
mt9p031->model = did->driver_data; mt9p031->model = did->driver_data;
mt9p031->reset = -1; mt9p031->reset = -1;
mt9p031->vaa = devm_regulator_get(&client->dev, "vaa"); mt9p031->regulators[0].supply = "vdd";
mt9p031->vdd = devm_regulator_get(&client->dev, "vdd"); mt9p031->regulators[1].supply = "vdd_io";
mt9p031->vdd_io = devm_regulator_get(&client->dev, "vdd_io"); mt9p031->regulators[2].supply = "vaa";
if (IS_ERR(mt9p031->vaa) || IS_ERR(mt9p031->vdd) || ret = devm_regulator_bulk_get(&client->dev, 3, mt9p031->regulators);
IS_ERR(mt9p031->vdd_io)) { if (ret < 0) {
dev_err(&client->dev, "Unable to get regulators\n"); dev_err(&client->dev, "Unable to get regulators\n");
return -ENODEV; return ret;
} }
v4l2_ctrl_handler_init(&mt9p031->ctrls, ARRAY_SIZE(mt9p031_ctrls) + 6); 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.field = V4L2_FIELD_NONE;
mt9p031->format.colorspace = V4L2_COLORSPACE_SRGB; 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, ret = devm_gpio_request_one(&client->dev, pdata->reset,
GPIOF_OUT_INIT_LOW, "mt9p031_rst"); GPIOF_OUT_INIT_LOW, "mt9p031_rst");
if (ret < 0) if (ret < 0)
@ -1070,8 +1097,18 @@ static const struct i2c_device_id mt9p031_id[] = {
}; };
MODULE_DEVICE_TABLE(i2c, 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 = { static struct i2c_driver mt9p031_i2c_driver = {
.driver = { .driver = {
.of_match_table = of_match_ptr(mt9p031_of_match),
.name = "mt9p031", .name = "mt9p031",
}, },
.probe = mt9p031_probe, .probe = mt9p031_probe,

View File

@ -740,7 +740,7 @@ static int mt9t001_probe(struct i2c_client *client,
if (ret < 0) if (ret < 0)
return ret; return ret;
mt9t001 = kzalloc(sizeof(*mt9t001), GFP_KERNEL); mt9t001 = devm_kzalloc(&client->dev, sizeof(*mt9t001), GFP_KERNEL);
if (!mt9t001) if (!mt9t001)
return -ENOMEM; return -ENOMEM;
@ -801,7 +801,6 @@ done:
if (ret < 0) { if (ret < 0) {
v4l2_ctrl_handler_free(&mt9t001->ctrls); v4l2_ctrl_handler_free(&mt9t001->ctrls);
media_entity_cleanup(&mt9t001->subdev.entity); media_entity_cleanup(&mt9t001->subdev.entity);
kfree(mt9t001);
} }
return ret; return ret;
@ -815,7 +814,6 @@ static int mt9t001_remove(struct i2c_client *client)
v4l2_ctrl_handler_free(&mt9t001->ctrls); v4l2_ctrl_handler_free(&mt9t001->ctrls);
v4l2_device_unregister_subdev(subdev); v4l2_device_unregister_subdev(subdev);
media_entity_cleanup(&subdev->entity); media_entity_cleanup(&subdev->entity);
kfree(mt9t001);
return 0; return 0;
} }

View File

@ -12,7 +12,6 @@
#include <linux/module.h> #include <linux/module.h>
#include <asm/div64.h> #include <asm/div64.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/mt9v011.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, static int mt9v011_g_register(struct v4l2_subdev *sd,
struct v4l2_dbg_register *reg) struct v4l2_dbg_register *reg)
{ {
struct i2c_client *client = v4l2_get_subdevdata(sd);
if (!v4l2_chip_match_i2c_client(client, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
reg->val = mt9v011_read(sd, reg->reg & 0xff); reg->val = mt9v011_read(sd, reg->reg & 0xff);
reg->size = 2; 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, static int mt9v011_s_register(struct v4l2_subdev *sd,
const struct v4l2_dbg_register *reg) const struct v4l2_dbg_register *reg)
{ {
struct i2c_client *client = v4l2_get_subdevdata(sd);
if (!v4l2_chip_match_i2c_client(client, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
mt9v011_write(sd, reg->reg & 0xff, reg->val & 0xffff); mt9v011_write(sd, reg->reg & 0xff, reg->val & 0xffff);
return 0; return 0;
} }
#endif #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) static int mt9v011_s_ctrl(struct v4l2_ctrl *ctrl)
{ {
struct mt9v011 *core = 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 = { static const struct v4l2_subdev_core_ops mt9v011_core_ops = {
.reset = mt9v011_reset, .reset = mt9v011_reset,
.g_chip_ident = mt9v011_g_chip_ident,
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
.g_register = mt9v011_g_register, .g_register = mt9v011_g_register,
.s_register = mt9v011_s_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)) I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
return -EIO; return -EIO;
core = kzalloc(sizeof(struct mt9v011), GFP_KERNEL); core = devm_kzalloc(&c->dev, sizeof(struct mt9v011), GFP_KERNEL);
if (!core) if (!core)
return -ENOMEM; return -ENOMEM;
@ -539,7 +511,6 @@ static int mt9v011_probe(struct i2c_client *c,
(version != MT9V011_REV_B_VERSION)) { (version != MT9V011_REV_B_VERSION)) {
v4l2_info(sd, "*** unknown micron chip detected (0x%04x).\n", v4l2_info(sd, "*** unknown micron chip detected (0x%04x).\n",
version); version);
kfree(core);
return -EINVAL; return -EINVAL;
} }
@ -562,7 +533,6 @@ static int mt9v011_probe(struct i2c_client *c,
v4l2_err(sd, "control initialization error %d\n", ret); v4l2_err(sd, "control initialization error %d\n", ret);
v4l2_ctrl_handler_free(&core->ctrls); v4l2_ctrl_handler_free(&core->ctrls);
kfree(core);
return ret; return ret;
} }
core->sd.ctrl_handler = &core->ctrls; core->sd.ctrl_handler = &core->ctrls;
@ -598,7 +568,7 @@ static int mt9v011_remove(struct i2c_client *c)
v4l2_device_unregister_subdev(sd); v4l2_device_unregister_subdev(sd);
v4l2_ctrl_handler_free(&core->ctrls); v4l2_ctrl_handler_free(&core->ctrls);
kfree(to_mt9v011(sd));
return 0; return 0;
} }

View File

@ -744,7 +744,7 @@ static int mt9v032_probe(struct i2c_client *client,
return -EIO; return -EIO;
} }
mt9v032 = kzalloc(sizeof(*mt9v032), GFP_KERNEL); mt9v032 = devm_kzalloc(&client->dev, sizeof(*mt9v032), GFP_KERNEL);
if (!mt9v032) if (!mt9v032)
return -ENOMEM; return -ENOMEM;
@ -830,8 +830,9 @@ static int mt9v032_probe(struct i2c_client *client,
mt9v032->pad.flags = MEDIA_PAD_FL_SOURCE; mt9v032->pad.flags = MEDIA_PAD_FL_SOURCE;
ret = media_entity_init(&mt9v032->subdev.entity, 1, &mt9v032->pad, 0); ret = media_entity_init(&mt9v032->subdev.entity, 1, &mt9v032->pad, 0);
if (ret < 0) if (ret < 0)
kfree(mt9v032); v4l2_ctrl_handler_free(&mt9v032->ctrls);
return ret; return ret;
} }
@ -841,9 +842,10 @@ static int mt9v032_remove(struct i2c_client *client)
struct v4l2_subdev *subdev = i2c_get_clientdata(client); struct v4l2_subdev *subdev = i2c_get_clientdata(client);
struct mt9v032 *mt9v032 = to_mt9v032(subdev); struct mt9v032 *mt9v032 = to_mt9v032(subdev);
v4l2_ctrl_handler_free(&mt9v032->ctrls);
v4l2_device_unregister_subdev(subdev); v4l2_device_unregister_subdev(subdev);
media_entity_cleanup(&subdev->entity); media_entity_cleanup(&subdev->entity);
kfree(mt9v032);
return 0; return 0;
} }

View File

@ -19,7 +19,6 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <media/noon010pc30.h> #include <media/noon010pc30.h>
#include <media/v4l2-chip-ident.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <linux/module.h> #include <linux/module.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
@ -712,7 +711,7 @@ static int noon010_probe(struct i2c_client *client,
return -EIO; return -EIO;
} }
info = kzalloc(sizeof(*info), GFP_KERNEL); info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);
if (!info) if (!info)
return -ENOMEM; return -ENOMEM;
@ -746,57 +745,50 @@ static int noon010_probe(struct i2c_client *client,
info->curr_win = &noon010_sizes[0]; info->curr_win = &noon010_sizes[0];
if (gpio_is_valid(pdata->gpio_nreset)) { 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) { if (ret) {
dev_err(&client->dev, "GPIO request error: %d\n", ret); dev_err(&client->dev, "GPIO request error: %d\n", ret);
goto np_err; goto np_err;
} }
info->gpio_nreset = pdata->gpio_nreset; info->gpio_nreset = pdata->gpio_nreset;
gpio_direction_output(info->gpio_nreset, 0);
gpio_export(info->gpio_nreset, 0); gpio_export(info->gpio_nreset, 0);
} }
if (gpio_is_valid(pdata->gpio_nstby)) { 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) { if (ret) {
dev_err(&client->dev, "GPIO request error: %d\n", ret); dev_err(&client->dev, "GPIO request error: %d\n", ret);
goto np_gpio_err; goto np_err;
} }
info->gpio_nstby = pdata->gpio_nstby; info->gpio_nstby = pdata->gpio_nstby;
gpio_direction_output(info->gpio_nstby, 0);
gpio_export(info->gpio_nstby, 0); gpio_export(info->gpio_nstby, 0);
} }
for (i = 0; i < NOON010_NUM_SUPPLIES; i++) for (i = 0; i < NOON010_NUM_SUPPLIES; i++)
info->supply[i].supply = noon010_supply_name[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); info->supply);
if (ret) if (ret)
goto np_reg_err; goto np_err;
info->pad.flags = MEDIA_PAD_FL_SOURCE; info->pad.flags = MEDIA_PAD_FL_SOURCE;
sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR; sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;
ret = media_entity_init(&sd->entity, 1, &info->pad, 0); ret = media_entity_init(&sd->entity, 1, &info->pad, 0);
if (ret < 0) if (ret < 0)
goto np_me_err; goto np_err;
ret = noon010_detect(client, info); ret = noon010_detect(client, info);
if (!ret) if (!ret)
return 0; 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: np_err:
v4l2_ctrl_handler_free(&info->hdl); v4l2_ctrl_handler_free(&info->hdl);
v4l2_device_unregister_subdev(sd); v4l2_device_unregister_subdev(sd);
kfree(info);
return ret; return ret;
} }
@ -807,17 +799,8 @@ static int noon010_remove(struct i2c_client *client)
v4l2_device_unregister_subdev(sd); v4l2_device_unregister_subdev(sd);
v4l2_ctrl_handler_free(&info->hdl); 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); media_entity_cleanup(&sd->entity);
kfree(info);
return 0; return 0;
} }

View File

@ -20,7 +20,6 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-chip-ident.h>
#include <linux/slab.h> #include <linux/slab.h>
MODULE_DESCRIPTION("OmniVision ov7640 sensor driver"); 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)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV; return -ENODEV;
sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); sd = devm_kzalloc(&client->dev, sizeof(*sd), GFP_KERNEL);
if (sd == NULL) if (sd == NULL)
return -ENOMEM; return -ENOMEM;
v4l2_i2c_subdev_init(sd, client, &ov7640_ops); 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) { if (write_regs(client, initial_registers) < 0) {
v4l_err(client, "error initializing OV7640\n"); v4l_err(client, "error initializing OV7640\n");
kfree(sd);
return -ENODEV; return -ENODEV;
} }
@ -84,7 +82,7 @@ static int ov7640_remove(struct i2c_client *client)
struct v4l2_subdev *sd = i2c_get_clientdata(client); struct v4l2_subdev *sd = i2c_get_clientdata(client);
v4l2_device_unregister_subdev(sd); v4l2_device_unregister_subdev(sd);
kfree(sd);
return 0; return 0;
} }

View File

@ -17,7 +17,6 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-mediabus.h> #include <media/v4l2-mediabus.h>
#include <media/ov7670.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, .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 #ifdef CONFIG_VIDEO_ADV_DEBUG
static int ov7670_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) 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; unsigned char val = 0;
int ret; int ret;
if (!v4l2_chip_match_i2c_client(client, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
ret = ov7670_read(sd, reg->reg & 0xff, &val); ret = ov7670_read(sd, reg->reg & 0xff, &val);
reg->val = val; reg->val = val;
reg->size = 1; 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) 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, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
ov7670_write(sd, reg->reg & 0xff, reg->val & 0xff); ov7670_write(sd, reg->reg & 0xff, reg->val & 0xff);
return 0; 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 = { static const struct v4l2_subdev_core_ops ov7670_core_ops = {
.g_chip_ident = ov7670_g_chip_ident,
.reset = ov7670_reset, .reset = ov7670_reset,
.init = ov7670_init, .init = ov7670_init,
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
@ -1552,7 +1531,7 @@ static int ov7670_probe(struct i2c_client *client,
struct ov7670_info *info; struct ov7670_info *info;
int ret; int ret;
info = kzalloc(sizeof(struct ov7670_info), GFP_KERNEL); info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);
if (info == NULL) if (info == NULL)
return -ENOMEM; return -ENOMEM;
sd = &info->sd; sd = &info->sd;
@ -1590,7 +1569,6 @@ static int ov7670_probe(struct i2c_client *client,
v4l_dbg(1, debug, client, v4l_dbg(1, debug, client,
"chip found @ 0x%x (%s) is not an ov7670 chip.\n", "chip found @ 0x%x (%s) is not an ov7670 chip.\n",
client->addr << 1, client->adapter->name); client->addr << 1, client->adapter->name);
kfree(info);
return ret; return ret;
} }
v4l_info(client, "chip found @ 0x%02x (%s)\n", 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; int err = info->hdl.error;
v4l2_ctrl_handler_free(&info->hdl); v4l2_ctrl_handler_free(&info->hdl);
kfree(info);
return err; return err;
} }
/* /*
@ -1659,7 +1636,6 @@ static int ov7670_remove(struct i2c_client *client)
v4l2_device_unregister_subdev(sd); v4l2_device_unregister_subdev(sd);
v4l2_ctrl_handler_free(&info->hdl); v4l2_ctrl_handler_free(&info->hdl);
kfree(info);
return 0; return 0;
} }

View File

@ -1385,9 +1385,12 @@ static int __s5c73m3_power_off(struct s5c73m3 *state)
} }
return 0; return 0;
err: err:
for (++i; i < S5C73M3_MAX_SUPPLIES; i++) for (++i; i < S5C73M3_MAX_SUPPLIES; i++) {
regulator_enable(state->supplies[i].consumer); 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; return ret;
} }
@ -1511,59 +1514,40 @@ static const struct v4l2_subdev_ops oif_subdev_ops = {
.video = &s5c73m3_oif_video_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, static int s5c73m3_configure_gpios(struct s5c73m3 *state,
const struct s5c73m3_platform_data *pdata) 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; int ret;
state->gpio[STBY].gpio = -EINVAL; state->gpio[STBY].gpio = -EINVAL;
state->gpio[RST].gpio = -EINVAL; state->gpio[RST].gpio = -EINVAL;
ret = s5c73m3_configure_gpio(gpio->gpio, gpio->level, "S5C73M3_STBY"); gpio = &pdata->gpio_stby;
if (ret) { if (gpio_is_valid(gpio->gpio)) {
s5c73m3_free_gpios(state); flags = (gpio->level ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW)
return ret; | 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; gpio = &pdata->gpio_reset;
ret = s5c73m3_configure_gpio(gpio->gpio, gpio->level, "S5C73M3_RST"); if (gpio_is_valid(gpio->gpio)) {
if (ret) { flags = (gpio->level ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW)
s5c73m3_free_gpios(state); | GPIOF_EXPORT;
return ret; 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; return 0;
} }
@ -1626,10 +1610,11 @@ static int s5c73m3_probe(struct i2c_client *client,
state->mclk_frequency = pdata->mclk_frequency; state->mclk_frequency = pdata->mclk_frequency;
state->bus_type = pdata->bus_type; state->bus_type = pdata->bus_type;
state->i2c_client = client;
ret = s5c73m3_configure_gpios(state, pdata); ret = s5c73m3_configure_gpios(state, pdata);
if (ret) if (ret)
goto out_err1; goto out_err;
for (i = 0; i < S5C73M3_MAX_SUPPLIES; i++) for (i = 0; i < S5C73M3_MAX_SUPPLIES; i++)
state->supplies[i].supply = s5c73m3_supply_names[i]; state->supplies[i].supply = s5c73m3_supply_names[i];
@ -1638,12 +1623,12 @@ static int s5c73m3_probe(struct i2c_client *client,
state->supplies); state->supplies);
if (ret) { if (ret) {
dev_err(dev, "failed to get regulators\n"); dev_err(dev, "failed to get regulators\n");
goto out_err2; goto out_err;
} }
ret = s5c73m3_init_controls(state); ret = s5c73m3_init_controls(state);
if (ret) if (ret)
goto out_err2; goto out_err;
state->sensor_pix_size[RES_ISP] = &s5c73m3_isp_resolutions[1]; state->sensor_pix_size[RES_ISP] = &s5c73m3_isp_resolutions[1];
state->sensor_pix_size[RES_JPEG] = &s5c73m3_jpeg_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); ret = s5c73m3_register_spi_driver(state);
if (ret < 0) if (ret < 0)
goto out_err2; goto out_err;
state->i2c_client = client;
v4l2_info(sd, "%s: completed succesfully\n", __func__); v4l2_info(sd, "%s: completed succesfully\n", __func__);
return 0; return 0;
out_err2: out_err:
s5c73m3_free_gpios(state);
out_err1:
media_entity_cleanup(&sd->entity); media_entity_cleanup(&sd->entity);
return ret; return ret;
} }
@ -1688,7 +1669,6 @@ static int s5c73m3_remove(struct i2c_client *client)
media_entity_cleanup(&sensor_sd->entity); media_entity_cleanup(&sensor_sd->entity);
s5c73m3_unregister_spi_driver(state); s5c73m3_unregister_spi_driver(state);
s5c73m3_free_gpios(state);
return 0; return 0;
} }

View File

@ -73,7 +73,7 @@ int s5c73m3_spi_write(struct s5c73m3 *state, const void *addr,
memset(padding, 0, sizeof(padding)); 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); r = spi_xmit(spi_dev, (void *)addr + j, tx_size, SPI_DIR_TX);
if (r < 0) if (r < 0)
return r; return r;
@ -98,7 +98,7 @@ int s5c73m3_spi_read(struct s5c73m3 *state, void *addr,
unsigned int i, j = 0; unsigned int i, j = 0;
int r = 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); r = spi_xmit(spi_dev, addr + j, tx_size, SPI_DIR_RX);
if (r < 0) if (r < 0)
return r; return r;

View File

@ -1491,58 +1491,41 @@ static const struct v4l2_subdev_ops s5k6aa_subdev_ops = {
/* /*
* GPIO setup * 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, static int s5k6aa_configure_gpios(struct s5k6aa *s5k6aa,
const struct s5k6aa_platform_data *pdata) 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; int ret;
s5k6aa->gpio[STBY].gpio = -EINVAL; s5k6aa->gpio[STBY].gpio = -EINVAL;
s5k6aa->gpio[RST].gpio = -EINVAL; s5k6aa->gpio[RST].gpio = -EINVAL;
ret = s5k6aa_configure_gpio(gpio->gpio, gpio->level, "S5K6AA_STBY"); gpio = &pdata->gpio_stby;
if (ret) { if (gpio_is_valid(gpio->gpio)) {
s5k6aa_free_gpios(s5k6aa); flags = (gpio->level ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW)
return ret; | 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; gpio = &pdata->gpio_reset;
ret = s5k6aa_configure_gpio(gpio->gpio, gpio->level, "S5K6AA_RST"); if (gpio_is_valid(gpio->gpio)) {
if (ret) { flags = (gpio->level ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW)
s5k6aa_free_gpios(s5k6aa); | GPIOF_EXPORT;
return ret; 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; return 0;
} }
@ -1593,7 +1576,7 @@ static int s5k6aa_probe(struct i2c_client *client,
ret = s5k6aa_configure_gpios(s5k6aa, pdata); ret = s5k6aa_configure_gpios(s5k6aa, pdata);
if (ret) if (ret)
goto out_err2; goto out_err;
for (i = 0; i < S5K6AA_NUM_SUPPLIES; i++) for (i = 0; i < S5K6AA_NUM_SUPPLIES; i++)
s5k6aa->supplies[i].supply = s5k6aa_supply_names[i]; s5k6aa->supplies[i].supply = s5k6aa_supply_names[i];
@ -1602,12 +1585,12 @@ static int s5k6aa_probe(struct i2c_client *client,
s5k6aa->supplies); s5k6aa->supplies);
if (ret) { if (ret) {
dev_err(&client->dev, "Failed to get regulators\n"); dev_err(&client->dev, "Failed to get regulators\n");
goto out_err3; goto out_err;
} }
ret = s5k6aa_initialize_ctrls(s5k6aa); ret = s5k6aa_initialize_ctrls(s5k6aa);
if (ret) if (ret)
goto out_err3; goto out_err;
s5k6aa_presets_data_init(s5k6aa); s5k6aa_presets_data_init(s5k6aa);
@ -1618,9 +1601,7 @@ static int s5k6aa_probe(struct i2c_client *client,
return 0; return 0;
out_err3: out_err:
s5k6aa_free_gpios(s5k6aa);
out_err2:
media_entity_cleanup(&s5k6aa->sd.entity); media_entity_cleanup(&s5k6aa->sd.entity);
return ret; return ret;
} }
@ -1628,12 +1609,10 @@ out_err2:
static int s5k6aa_remove(struct i2c_client *client) static int s5k6aa_remove(struct i2c_client *client)
{ {
struct v4l2_subdev *sd = i2c_get_clientdata(client); struct v4l2_subdev *sd = i2c_get_clientdata(client);
struct s5k6aa *s5k6aa = to_s5k6aa(sd);
v4l2_device_unregister_subdev(sd); v4l2_device_unregister_subdev(sd);
v4l2_ctrl_handler_free(sd->ctrl_handler); v4l2_ctrl_handler_free(sd->ctrl_handler);
media_entity_cleanup(&sd->entity); media_entity_cleanup(&sd->entity);
s5k6aa_free_gpios(s5k6aa);
return 0; return 0;
} }

View File

@ -33,7 +33,6 @@
#include <media/saa6588.h> #include <media/saa6588.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-chip-ident.h>
/* insmod options */ /* insmod options */
@ -443,17 +442,9 @@ static int saa6588_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt)
return 0; 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 = { static const struct v4l2_subdev_core_ops saa6588_core_ops = {
.g_chip_ident = saa6588_g_chip_ident,
.ioctl = saa6588_ioctl, .ioctl = saa6588_ioctl,
}; };
@ -478,17 +469,15 @@ static int saa6588_probe(struct i2c_client *client,
v4l_info(client, "saa6588 found @ 0x%x (%s)\n", v4l_info(client, "saa6588 found @ 0x%x (%s)\n",
client->addr << 1, client->adapter->name); client->addr << 1, client->adapter->name);
s = kzalloc(sizeof(*s), GFP_KERNEL); s = devm_kzalloc(&client->dev, sizeof(*s), GFP_KERNEL);
if (s == NULL) if (s == NULL)
return -ENOMEM; return -ENOMEM;
s->buf_size = bufblocks * 3; s->buf_size = bufblocks * 3;
s->buffer = kmalloc(s->buf_size, GFP_KERNEL); s->buffer = devm_kzalloc(&client->dev, s->buf_size, GFP_KERNEL);
if (s->buffer == NULL) { if (s->buffer == NULL)
kfree(s);
return -ENOMEM; return -ENOMEM;
}
sd = &s->sd; sd = &s->sd;
v4l2_i2c_subdev_init(sd, client, &saa6588_ops); v4l2_i2c_subdev_init(sd, client, &saa6588_ops);
spin_lock_init(&s->lock); spin_lock_init(&s->lock);
@ -516,8 +505,6 @@ static int saa6588_remove(struct i2c_client *client)
cancel_delayed_work_sync(&s->work); cancel_delayed_work_sync(&s->work);
kfree(s->buffer);
kfree(s);
return 0; return 0;
} }

View File

@ -35,7 +35,6 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
MODULE_DESCRIPTION("Philips SAA7110 video decoder driver"); 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); status = saa7110_read(sd);
if (status & 0x40) { if (status & 0x40) {
v4l2_dbg(1, debug, sd, "status=0x%02x (no signal)\n", status); 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) { if ((status & 3) == 0) {
saa7110_write(sd, 0x06, 0x83); 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) 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; return 0;
} }
@ -352,13 +351,6 @@ static int saa7110_s_ctrl(struct v4l2_ctrl *ctrl)
return 0; 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 = { 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 = { 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, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
.try_ext_ctrls = v4l2_subdev_try_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
.s_ext_ctrls = v4l2_subdev_s_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", v4l_info(client, "chip found @ 0x%x (%s)\n",
client->addr << 1, client->adapter->name); client->addr << 1, client->adapter->name);
decoder = kzalloc(sizeof(struct saa7110), GFP_KERNEL); decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL);
if (!decoder) if (!decoder)
return -ENOMEM; return -ENOMEM;
sd = &decoder->sd; sd = &decoder->sd;
@ -428,7 +419,6 @@ static int saa7110_probe(struct i2c_client *client,
int err = decoder->hdl.error; int err = decoder->hdl.error;
v4l2_ctrl_handler_free(&decoder->hdl); v4l2_ctrl_handler_free(&decoder->hdl);
kfree(decoder);
return err; return err;
} }
v4l2_ctrl_handler_setup(&decoder->hdl); v4l2_ctrl_handler_setup(&decoder->hdl);
@ -469,7 +459,6 @@ static int saa7110_remove(struct i2c_client *client)
v4l2_device_unregister_subdev(sd); v4l2_device_unregister_subdev(sd);
v4l2_ctrl_handler_free(&decoder->hdl); v4l2_ctrl_handler_free(&decoder->hdl);
kfree(decoder);
return 0; return 0;
} }

View File

@ -46,7 +46,6 @@
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-chip-ident.h>
#include <media/saa7115.h> #include <media/saa7115.h>
#include <asm/div64.h> #include <asm/div64.h>
@ -63,6 +62,16 @@ module_param(debug, bool, 0644);
MODULE_PARM_DESC(debug, "Debug level (0-1)"); MODULE_PARM_DESC(debug, "Debug level (0-1)");
enum saa711x_model {
SAA7111A,
SAA7111,
SAA7113,
GM7113C,
SAA7114,
SAA7115,
SAA7118,
};
struct saa711x_state { struct saa711x_state {
struct v4l2_subdev sd; struct v4l2_subdev sd;
struct v4l2_ctrl_handler hdl; struct v4l2_ctrl_handler hdl;
@ -80,7 +89,7 @@ struct saa711x_state {
int radio; int radio;
int width; int width;
int height; int height;
u32 ident; enum saa711x_model ident;
u32 audclk_freq; u32 audclk_freq;
u32 crystal_freq; u32 crystal_freq;
bool ucgc; 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 */ /* Sanity routine to check if a register is present */
static int saa711x_has_reg(const int id, const u8 reg) 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 && return reg < 0x20 && reg != 0x01 && reg != 0x0f &&
(reg < 0x13 || reg > 0x19) && reg != 0x1d && reg != 0x1e; (reg < 0x13 || reg > 0x19) && reg != 0x1d && reg != 0x1e;
if (id == V4L2_IDENT_SAA7111A) if (id == SAA7111A)
return reg < 0x20 && reg != 0x01 && reg != 0x0f && return reg < 0x20 && reg != 0x01 && reg != 0x0f &&
reg != 0x14 && reg != 0x18 && reg != 0x19 && reg != 0x14 && reg != 0x18 && reg != 0x19 &&
reg != 0x1d && reg != 0x1e; reg != 0x1d && reg != 0x1e;
@ -127,16 +136,18 @@ static int saa711x_has_reg(const int id, const u8 reg)
return 0; return 0;
switch (id) { 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) && return reg != 0x14 && (reg < 0x18 || reg > 0x1e) && (reg < 0x20 || reg > 0x3f) &&
reg != 0x5d && reg < 0x63; reg != 0x5d && reg < 0x63;
case V4L2_IDENT_SAA7114: case SAA7114:
return (reg < 0x1a || reg > 0x1e) && (reg < 0x20 || reg > 0x2f) && return (reg < 0x1a || reg > 0x1e) && (reg < 0x20 || reg > 0x2f) &&
(reg < 0x63 || reg > 0x7f) && reg != 0x33 && reg != 0x37 && (reg < 0x63 || reg > 0x7f) && reg != 0x33 && reg != 0x37 &&
reg != 0x81 && reg < 0xf0; reg != 0x81 && reg < 0xf0;
case V4L2_IDENT_SAA7115: case SAA7115:
return (reg < 0x20 || reg > 0x2f) && reg != 0x65 && (reg < 0xfc || reg > 0xfe); 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) && return (reg < 0x1a || reg > 0x1d) && (reg < 0x20 || reg > 0x22) &&
(reg < 0x26 || reg > 0x28) && reg != 0x33 && reg != 0x37 && (reg < 0x26 || reg > 0x28) && reg != 0x33 && reg != 0x37 &&
(reg < 0x63 || reg > 0x7f) && reg != 0x81 && reg < 0xf0; (reg < 0x63 || reg > 0x7f) && reg != 0x81 && reg < 0xf0;
@ -214,7 +225,10 @@ static const unsigned char saa7111_init[] = {
0x00, 0x00 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[] = { static const unsigned char saa7113_init[] = {
R_01_INC_DELAY, 0x08, R_01_INC_DELAY, 0x08,
R_02_INPUT_CNTL_1, 0xc2, R_02_INPUT_CNTL_1, 0xc2,
@ -448,6 +462,24 @@ static const unsigned char saa7115_cfg_50hz_video[] = {
/* ============== SAA7715 VIDEO templates (end) ======= */ /* ============== 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[] = { static const unsigned char saa7115_cfg_vbi_on[] = {
R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */ R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */ 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. // This works for NTSC-M, SECAM-L and the 50Hz PAL variants.
if (std & V4L2_STD_525_60) { if (std & V4L2_STD_525_60) {
v4l2_dbg(1, debug, sd, "decoder set standard 60 Hz\n"); 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); saa711x_set_size(sd, 720, 480);
} else { } else {
v4l2_dbg(1, debug, sd, "decoder set standard 50 Hz\n"); 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); 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) 011 NTSC N (3.58MHz) PAL M (3.58MHz)
100 reserved NTSC-Japan (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; u8 reg = saa711x_read(sd, R_0E_CHROMA_CNTL_1) & 0x8f;
if (std == V4L2_STD_PAL_M) { 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 */ /* restart task B if needed */
int taskb = saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10; 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); saa711x_writeregs(sd, saa7115_cfg_vbi_on);
}
/* switch audio mode too! */ /* switch audio mode too! */
saa711x_s_clock_freq(sd, state->audclk_freq); 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 #else
/* SAA7113 and SAA7118 also should support VBI - Need testing */ /* SAA7113 and SAA7118 also should support VBI - Need testing */
if (state->ident != V4L2_IDENT_SAA7115) if (state->ident != SAA7115)
return; return;
#endif #endif
@ -1214,13 +1252,14 @@ static int saa711x_s_routing(struct v4l2_subdev *sd,
u32 input, u32 output, u32 config) u32 input, u32 output, u32 config)
{ {
struct saa711x_state *state = to_state(sd); 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", v4l2_dbg(1, debug, sd, "decoder set input %d output %d\n",
input, output); input, output);
/* saa7111/3 does not have these inputs */ /* 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_COMPOSITE4 ||
input == SAA7115_COMPOSITE5)) { input == SAA7115_COMPOSITE5)) {
return -EINVAL; return -EINVAL;
@ -1235,7 +1274,7 @@ static int saa711x_s_routing(struct v4l2_subdev *sd,
state->input = input; state->input = input;
/* saa7111 has slightly different input numbering */ /* saa7111 has slightly different input numbering */
if (state->ident <= V4L2_IDENT_SAA7111A) { if (state->ident <= SAA7111A) {
if (input >= SAA7115_COMPOSITE4) if (input >= SAA7115_COMPOSITE4)
input -= 2; input -= 2;
/* saa7111 specific */ /* saa7111 specific */
@ -1258,13 +1297,13 @@ static int saa711x_s_routing(struct v4l2_subdev *sd,
(state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0)); (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0));
state->output = output; state->output = output;
if (state->ident == V4L2_IDENT_SAA7114 || if (state->ident == SAA7114 ||
state->ident == V4L2_IDENT_SAA7115) { state->ident == SAA7115) {
saa711x_write(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK, 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) | (saa711x_read(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK) & 0xfe) |
(state->output & 0x01)); (state->output & 0x01));
} }
if (state->ident > V4L2_IDENT_SAA7111A) { if (state->ident > SAA7111A) {
if (config & SAA7115_IDQ_IS_DEFAULT) if (config & SAA7115_IDQ_IS_DEFAULT)
saa711x_write(sd, R_85_I_PORT_SIGNAL_POLAR, 0x20); saa711x_write(sd, R_85_I_PORT_SIGNAL_POLAR, 0x20);
else else
@ -1277,7 +1316,7 @@ static int saa711x_s_gpio(struct v4l2_subdev *sd, u32 val)
{ {
struct saa711x_state *state = to_state(sd); struct saa711x_state *state = to_state(sd);
if (state->ident > V4L2_IDENT_SAA7111A) if (state->ident > SAA7111A)
return -EINVAL; return -EINVAL;
saa711x_write(sd, 0x11, (saa711x_read(sd, 0x11) & 0x7f) | saa711x_write(sd, 0x11, (saa711x_read(sd, 0x11) & 0x7f) |
(val ? 0x80 : 0)); (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); 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); reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
v4l2_dbg(1, debug, sd, "Status byte 1 (0x1e)=0x%02x\n", reg1e); 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; *std &= V4L2_STD_SECAM;
break; break;
default: default:
*std = V4L2_STD_UNKNOWN;
/* Can't detect anything */ /* Can't detect anything */
break; 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); v4l2_dbg(1, debug, sd, "Status byte 2 (0x1f)=0x%02x\n", reg1f);
/* horizontal/vertical not locked */ /* horizontal/vertical not locked */
if (reg1f & 0x40) if (reg1f & 0x40) {
*std = V4L2_STD_UNKNOWN;
goto ret; goto ret;
}
if (reg1f & 0x20) if (reg1f & 0x20)
*std &= V4L2_STD_525_60; *std &= V4L2_STD_525_60;
@ -1418,7 +1460,7 @@ static int saa711x_g_input_status(struct v4l2_subdev *sd, u32 *status)
int reg1f; int reg1f;
*status = V4L2_IN_ST_NO_SIGNAL; *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); reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC); reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
if ((reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80) 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 #ifdef CONFIG_VIDEO_ADV_DEBUG
static int saa711x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) 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, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
reg->val = saa711x_read(sd, reg->reg & 0xff); reg->val = saa711x_read(sd, reg->reg & 0xff);
reg->size = 1; reg->size = 1;
return 0; 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) 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, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
saa711x_write(sd, reg->reg & 0xff, reg->val & 0xff); saa711x_write(sd, reg->reg & 0xff, reg->val & 0xff);
return 0; return 0;
} }
#endif #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) static int saa711x_log_status(struct v4l2_subdev *sd)
{ {
struct saa711x_state *state = to_state(sd); struct saa711x_state *state = to_state(sd);
@ -1469,7 +1491,7 @@ static int saa711x_log_status(struct v4l2_subdev *sd)
int vcr; int vcr;
v4l2_info(sd, "Audio frequency: %d Hz\n", state->audclk_freq); 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 */ /* status for the saa7114 */
reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC); reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
signalOk = (reg1f & 0xc1) == 0x81; 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 = { static const struct v4l2_subdev_core_ops saa711x_core_ops = {
.log_status = saa711x_log_status, .log_status = saa711x_log_status,
.g_chip_ident = saa711x_g_chip_ident,
.g_ext_ctrls = v4l2_subdev_g_ext_ctrls, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
.try_ext_ctrls = v4l2_subdev_try_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
.s_ext_ctrls = v4l2_subdev_s_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, .vbi = &saa711x_vbi_ops,
}; };
#define CHIP_VER_SIZE 16
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
/**
* 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)
{
char chip_ver[CHIP_VER_SIZE];
char chip_id;
int i;
int autodetect;
autodetect = !id || id->driver_data == 1;
/* Read the chip version register */
for (i = 0; i < CHIP_VER_SIZE; i++) {
i2c_smbus_write_byte_data(client, 0, i);
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';
/* 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);
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;
}
}
/* 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;
}
/* 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, static int saa711x_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct saa711x_state *state; struct saa711x_state *state;
struct v4l2_subdev *sd; struct v4l2_subdev *sd;
struct v4l2_ctrl_handler *hdl; struct v4l2_ctrl_handler *hdl;
int i; int ident;
char name[17]; char name[CHIP_VER_SIZE + 1];
char chip_id;
int autodetect = !id || id->driver_data == 1;
/* Check if the adapter supports the needed features */ /* Check if the adapter supports the needed features */
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -EIO; return -EIO;
for (i = 0; i < 0x0f; i++) { ident = saa711x_detect_chip(client, id, name);
i2c_smbus_write_byte_data(client, 0, i); if (ident == -EINVAL) {
name[i] = (i2c_smbus_read_byte_data(client, 0) & 0x0f) + '0'; /* Chip exists, but doesn't match */
if (name[i] > '9') v4l_warn(client, "found %s while %s was expected\n",
name[i] += 'a' - '9' - 1; name, id->name);
}
name[i] = '\0';
chip_id = name[5];
/* 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; return -ENODEV;
} }
if (ident < 0)
return ident;
/* Safety check */ strlcpy(client->name, name, sizeof(client->name));
if (!autodetect && id->name[6] != chip_id) {
v4l_warn(client, "found saa711%c while %s was expected\n",
chip_id, id->name);
}
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); state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
if (state == NULL) if (state == NULL)
return -ENOMEM; return -ENOMEM;
sd = &state->sd; sd = &state->sd;
v4l2_i2c_subdev_init(sd, client, &saa711x_ops); 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; hdl = &state->hdl;
v4l2_ctrl_handler_init(hdl, 6); v4l2_ctrl_handler_init(hdl, 6);
/* add in ascending ID order */ /* add in ascending ID order */
@ -1640,7 +1751,6 @@ static int saa711x_probe(struct i2c_client *client,
int err = hdl->error; int err = hdl->error;
v4l2_ctrl_handler_free(hdl); v4l2_ctrl_handler_free(hdl);
kfree(state);
return err; return err;
} }
v4l2_ctrl_auto_cluster(2, &state->agc, 0, true); 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->output = SAA7115_IPORT_ON;
state->enable = 1; state->enable = 1;
state->radio = 0; state->radio = 0;
switch (chip_id) { state->ident = ident;
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->audclk_freq = 48000; state->audclk_freq = 48000;
@ -1682,18 +1768,19 @@ static int saa711x_probe(struct i2c_client *client,
/* init to 60hz/48khz */ /* init to 60hz/48khz */
state->crystal_freq = SAA7115_FREQ_24_576_MHZ; state->crystal_freq = SAA7115_FREQ_24_576_MHZ;
switch (state->ident) { switch (state->ident) {
case V4L2_IDENT_SAA7111: case SAA7111:
case V4L2_IDENT_SAA7111A: case SAA7111A:
saa711x_writeregs(sd, saa7111_init); saa711x_writeregs(sd, saa7111_init);
break; break;
case V4L2_IDENT_SAA7113: case GM7113C:
case SAA7113:
saa711x_writeregs(sd, saa7113_init); saa711x_writeregs(sd, saa7113_init);
break; break;
default: default:
state->crystal_freq = SAA7115_FREQ_32_11_MHZ; state->crystal_freq = SAA7115_FREQ_32_11_MHZ;
saa711x_writeregs(sd, saa7115_init_auto_input); saa711x_writeregs(sd, saa7115_init_auto_input);
} }
if (state->ident > V4L2_IDENT_SAA7111A) if (state->ident > SAA7111A)
saa711x_writeregs(sd, saa7115_init_misc); saa711x_writeregs(sd, saa7115_init_misc);
saa711x_set_v4lstd(sd, V4L2_STD_NTSC); saa711x_set_v4lstd(sd, V4L2_STD_NTSC);
v4l2_ctrl_handler_setup(hdl); v4l2_ctrl_handler_setup(hdl);
@ -1712,7 +1799,6 @@ static int saa711x_remove(struct i2c_client *client)
v4l2_device_unregister_subdev(sd); v4l2_device_unregister_subdev(sd);
v4l2_ctrl_handler_free(sd->ctrl_handler); v4l2_ctrl_handler_free(sd->ctrl_handler);
kfree(to_state(sd));
return 0; return 0;
} }
@ -1723,6 +1809,7 @@ static const struct i2c_device_id saa711x_id[] = {
{ "saa7114", 0 }, { "saa7114", 0 },
{ "saa7115", 0 }, { "saa7115", 0 },
{ "saa7118", 0 }, { "saa7118", 0 },
{ "gm7113c", 0 },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, saa711x_id); MODULE_DEVICE_TABLE(i2c, saa711x_id);

View File

@ -54,7 +54,6 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-chip-ident.h>
#include <media/saa7127.h> #include <media/saa7127.h>
static int debug; 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 saa7127_state {
struct v4l2_subdev sd; struct v4l2_subdev sd;
v4l2_std_id std; v4l2_std_id std;
u32 ident; enum saa712x_model ident;
enum saa7127_input_type input_type; enum saa7127_input_type input_type;
enum saa7127_output_type output_type; enum saa7127_output_type output_type;
int video_enable; 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; inittab = saa7127_init_config_60hz;
state->reg_61 = SAA7127_60HZ_DAC_CONTROL; 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_SECAM) &&
!(std & (V4L2_STD_625_50 & ~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; break;
case SAA7127_OUTPUT_TYPE_COMPOSITE: case SAA7127_OUTPUT_TYPE_COMPOSITE:
if (state->ident == V4L2_IDENT_SAA7129) if (state->ident == SAA7129)
state->reg_2d = 0x20; /* CVBS only */ state->reg_2d = 0x20; /* CVBS only */
else else
state->reg_2d = 0x08; /* 00001000 CVBS only, RGB DAC's off (high impedance mode) */ 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; break;
case SAA7127_OUTPUT_TYPE_SVIDEO: case SAA7127_OUTPUT_TYPE_SVIDEO:
if (state->ident == V4L2_IDENT_SAA7129) if (state->ident == SAA7129)
state->reg_2d = 0x18; /* Y + C */ state->reg_2d = 0x18; /* Y + C */
else else
state->reg_2d = 0xff; /*11111111 croma -> R, luma -> CVBS + G + B */ 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; break;
case SAA7127_OUTPUT_TYPE_BOTH: case SAA7127_OUTPUT_TYPE_BOTH:
if (state->ident == V4L2_IDENT_SAA7129) if (state->ident == SAA7129)
state->reg_2d = 0x38; state->reg_2d = 0x38;
else else
state->reg_2d = 0xbf; 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 #ifdef CONFIG_VIDEO_ADV_DEBUG
static int saa7127_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) 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, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
reg->val = saa7127_read(sd, reg->reg & 0xff); reg->val = saa7127_read(sd, reg->reg & 0xff);
reg->size = 1; reg->size = 1;
return 0; 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) 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, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
saa7127_write(sd, reg->reg & 0xff, reg->val & 0xff); saa7127_write(sd, reg->reg & 0xff, reg->val & 0xff);
return 0; return 0;
} }
#endif #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) static int saa7127_log_status(struct v4l2_subdev *sd)
{ {
struct saa7127_state *state = to_state(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 = { static const struct v4l2_subdev_core_ops saa7127_core_ops = {
.log_status = saa7127_log_status, .log_status = saa7127_log_status,
.g_chip_ident = saa7127_g_chip_ident,
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
.g_register = saa7127_g_register, .g_register = saa7127_g_register,
.s_register = saa7127_s_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", v4l_dbg(1, debug, client, "detecting saa7127 client on address 0x%x\n",
client->addr << 1); client->addr << 1);
state = kzalloc(sizeof(struct saa7127_state), GFP_KERNEL); state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
if (state == NULL) if (state == NULL)
return -ENOMEM; return -ENOMEM;
@ -767,7 +750,6 @@ static int saa7127_probe(struct i2c_client *client,
if ((saa7127_read(sd, 0) & 0xe4) != 0 || if ((saa7127_read(sd, 0) & 0xe4) != 0 ||
(saa7127_read(sd, 0x29) & 0x3f) != 0x1d) { (saa7127_read(sd, 0x29) & 0x3f) != 0x1d) {
v4l2_dbg(1, debug, sd, "saa7127 not found\n"); v4l2_dbg(1, debug, sd, "saa7127 not found\n");
kfree(state);
return -ENODEV; return -ENODEV;
} }
@ -782,10 +764,10 @@ static int saa7127_probe(struct i2c_client *client,
if (saa7127_read(sd, SAA7129_REG_FADE_KEY_COL2) == 0xaa) { if (saa7127_read(sd, SAA7129_REG_FADE_KEY_COL2) == 0xaa) {
saa7127_write(sd, SAA7129_REG_FADE_KEY_COL2, saa7127_write(sd, SAA7129_REG_FADE_KEY_COL2,
read_result); read_result);
state->ident = V4L2_IDENT_SAA7129; state->ident = SAA7129;
strlcpy(client->name, "saa7129", I2C_NAME_SIZE); strlcpy(client->name, "saa7129", I2C_NAME_SIZE);
} else { } else {
state->ident = V4L2_IDENT_SAA7127; state->ident = SAA7127;
strlcpy(client->name, "saa7127", I2C_NAME_SIZE); 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_input_type(sd, SAA7127_INPUT_TYPE_NORMAL);
saa7127_set_video_enable(sd, 1); saa7127_set_video_enable(sd, 1);
if (state->ident == V4L2_IDENT_SAA7129) if (state->ident == SAA7129)
saa7127_write_inittab(sd, saa7129_init_config_extra); saa7127_write_inittab(sd, saa7129_init_config_extra);
return 0; return 0;
} }
@ -823,7 +805,6 @@ static int saa7127_remove(struct i2c_client *client)
v4l2_device_unregister_subdev(sd); v4l2_device_unregister_subdev(sd);
/* Turn off TV output */ /* Turn off TV output */
saa7127_set_video_enable(sd, 0); saa7127_set_video_enable(sd, 0);
kfree(to_state(sd));
return 0; return 0;
} }
@ -831,10 +812,10 @@ static int saa7127_remove(struct i2c_client *client)
static struct i2c_device_id saa7127_id[] = { static struct i2c_device_id saa7127_id[] = {
{ "saa7127_auto", 0 }, /* auto-detection */ { "saa7127_auto", 0 }, /* auto-detection */
{ "saa7126", V4L2_IDENT_SAA7127 }, { "saa7126", SAA7127 },
{ "saa7127", V4L2_IDENT_SAA7127 }, { "saa7127", SAA7127 },
{ "saa7128", V4L2_IDENT_SAA7129 }, { "saa7128", SAA7129 },
{ "saa7129", V4L2_IDENT_SAA7129 }, { "saa7129", SAA7129 },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, saa7127_id); MODULE_DEVICE_TABLE(i2c, saa7127_id);

View File

@ -977,12 +977,6 @@ static int saa717x_s_video_routing(struct v4l2_subdev *sd,
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
static int saa717x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) 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, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
reg->val = saa717x_read(sd, reg->reg); reg->val = saa717x_read(sd, reg->reg);
reg->size = 1; reg->size = 1;
return 0; 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) 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; u16 addr = reg->reg & 0xffff;
u8 val = reg->val & 0xff; u8 val = reg->val & 0xff;
if (!v4l2_chip_match_i2c_client(client, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
saa717x_write(sd, addr, val); saa717x_write(sd, addr, val);
return 0; 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)) if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -EIO; return -EIO;
decoder = kzalloc(sizeof(struct saa717x_state), GFP_KERNEL); decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL);
if (decoder == NULL) if (decoder == NULL)
return -ENOMEM; return -ENOMEM;
@ -1276,7 +1265,6 @@ static int saa717x_probe(struct i2c_client *client,
id = saa717x_read(sd, 0x5a0); id = saa717x_read(sd, 0x5a0);
if (id != 0xc2 && id != 0x32 && id != 0xf2 && id != 0x6c) { if (id != 0xc2 && id != 0x32 && id != 0xf2 && id != 0x6c) {
v4l2_dbg(1, debug, sd, "saa717x not found (id=%02x)\n", id); v4l2_dbg(1, debug, sd, "saa717x not found (id=%02x)\n", id);
kfree(decoder);
return -ENODEV; return -ENODEV;
} }
if (id == 0xc2) if (id == 0xc2)
@ -1316,7 +1304,6 @@ static int saa717x_probe(struct i2c_client *client,
int err = hdl->error; int err = hdl->error;
v4l2_ctrl_handler_free(hdl); v4l2_ctrl_handler_free(hdl);
kfree(decoder);
return err; return err;
} }
@ -1353,7 +1340,6 @@ static int saa717x_remove(struct i2c_client *client)
v4l2_device_unregister_subdev(sd); v4l2_device_unregister_subdev(sd);
v4l2_ctrl_handler_free(sd->ctrl_handler); v4l2_ctrl_handler_free(sd->ctrl_handler);
kfree(to_state(sd));
return 0; return 0;
} }

View File

@ -32,7 +32,6 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-chip-ident.h>
MODULE_DESCRIPTION("Philips SAA7185 video encoder driver"); MODULE_DESCRIPTION("Philips SAA7185 video encoder driver");
MODULE_AUTHOR("Dave Perks"); MODULE_AUTHOR("Dave Perks");
@ -285,17 +284,9 @@ static int saa7185_s_routing(struct v4l2_subdev *sd,
return 0; 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 = { static const struct v4l2_subdev_core_ops saa7185_core_ops = {
.g_chip_ident = saa7185_g_chip_ident,
.init = saa7185_init, .init = saa7185_init,
}; };
@ -326,7 +317,7 @@ static int saa7185_probe(struct i2c_client *client,
v4l_info(client, "chip found @ 0x%x (%s)\n", v4l_info(client, "chip found @ 0x%x (%s)\n",
client->addr << 1, client->adapter->name); 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) if (encoder == NULL)
return -ENOMEM; return -ENOMEM;
encoder->norm = V4L2_STD_NTSC; encoder->norm = V4L2_STD_NTSC;
@ -352,7 +343,6 @@ static int saa7185_remove(struct i2c_client *client)
v4l2_device_unregister_subdev(sd); v4l2_device_unregister_subdev(sd);
/* SW: output off is active */ /* SW: output off is active */
saa7185_write(sd, 0x61, (encoder->reg[0x61]) | 0x40); saa7185_write(sd, 0x61, (encoder->reg[0x61]) | 0x40);
kfree(encoder);
return 0; return 0;
} }

View File

@ -22,7 +22,6 @@
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-chip-ident.h>
#include "saa7191.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"); 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; stdc &= ~SAA7191_STDC_SECS;
ctl3 &= ~(SAA7191_CTL3_FSEL); 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) { if (status & SAA7191_STATUS_FIDT) {
/* 60Hz signal -> NTSC */ /* 60Hz signal -> NTSC */
dprintk("60Hz signal: NTSC\n"); dprintk("60Hz signal: NTSC\n");
*norm = V4L2_STD_NTSC; *norm &= V4L2_STD_NTSC;
return 0; return 0;
} }
@ -325,12 +324,13 @@ static int saa7191_querystd(struct v4l2_subdev *sd, v4l2_std_id *norm)
if (status & SAA7191_STATUS_FIDT) { if (status & SAA7191_STATUS_FIDT) {
dprintk("No 50Hz signal\n"); dprintk("No 50Hz signal\n");
saa7191_s_std(sd, old_norm); saa7191_s_std(sd, old_norm);
return -EAGAIN; *norm = V4L2_STD_UNKNOWN;
return 0;
} }
if (status & SAA7191_STATUS_CODE) { if (status & SAA7191_STATUS_CODE) {
dprintk("PAL\n"); dprintk("PAL\n");
*norm = V4L2_STD_PAL; *norm &= V4L2_STD_PAL;
return saa7191_s_std(sd, old_norm); 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 ? */ /* not 50Hz ? */
if (status & SAA7191_STATUS_FIDT) { if (status & SAA7191_STATUS_FIDT) {
dprintk("No 50Hz signal\n"); dprintk("No 50Hz signal\n");
err = -EAGAIN; *norm = V4L2_STD_UNKNOWN;
goto out; goto out;
} }
if (status & SAA7191_STATUS_CODE) { if (status & SAA7191_STATUS_CODE) {
/* Color detected -> SECAM */ /* Color detected -> SECAM */
dprintk("SECAM\n"); dprintk("SECAM\n");
*norm = V4L2_STD_SECAM; *norm &= V4L2_STD_SECAM;
return saa7191_s_std(sd, old_norm); return saa7191_s_std(sd, old_norm);
} }
dprintk("No color detected with SECAM - Going back to PAL.\n"); dprintk("No color detected with SECAM - Going back to PAL.\n");
*norm = V4L2_STD_UNKNOWN;
out: out:
return saa7191_s_std(sd, old_norm); 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 = { static const struct v4l2_subdev_core_ops saa7191_core_ops = {
.g_chip_ident = saa7191_g_chip_ident,
.g_ctrl = saa7191_g_ctrl, .g_ctrl = saa7191_g_ctrl,
.s_ctrl = saa7191_s_ctrl, .s_ctrl = saa7191_s_ctrl,
.s_std = saa7191_s_std, .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", v4l_info(client, "chip found @ 0x%x (%s)\n",
client->addr << 1, client->adapter->name); client->addr << 1, client->adapter->name);
decoder = kzalloc(sizeof(*decoder), GFP_KERNEL); decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL);
if (!decoder) if (!decoder)
return -ENOMEM; return -ENOMEM;
@ -615,7 +607,6 @@ static int saa7191_probe(struct i2c_client *client,
err = saa7191_write_block(sd, sizeof(initseq), initseq); err = saa7191_write_block(sd, sizeof(initseq), initseq);
if (err) { if (err) {
printk(KERN_ERR "SAA7191 initialization failed\n"); printk(KERN_ERR "SAA7191 initialization failed\n");
kfree(decoder);
return err; return err;
} }
@ -636,7 +627,6 @@ static int saa7191_remove(struct i2c_client *client)
struct v4l2_subdev *sd = i2c_get_clientdata(client); struct v4l2_subdev *sd = i2c_get_clientdata(client);
v4l2_device_unregister_subdev(sd); v4l2_device_unregister_subdev(sd);
kfree(to_saa7191(sd));
return 0; return 0;
} }

View File

@ -2383,8 +2383,9 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
} }
if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN) { if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN) {
if (gpio_request_one(sensor->platform_data->xshutdown, 0, if (devm_gpio_request_one(&client->dev,
"SMIA++ xshutdown") != 0) { sensor->platform_data->xshutdown, 0,
"SMIA++ xshutdown") != 0) {
dev_err(&client->dev, dev_err(&client->dev,
"unable to acquire reset gpio %d\n", "unable to acquire reset gpio %d\n",
sensor->platform_data->xshutdown); sensor->platform_data->xshutdown);
@ -2393,10 +2394,8 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
} }
rval = smiapp_power_on(sensor); rval = smiapp_power_on(sensor);
if (rval) { if (rval)
rval = -ENODEV; return -ENODEV;
goto out_smiapp_power_on;
}
rval = smiapp_identify_module(subdev); rval = smiapp_identify_module(subdev);
if (rval) { if (rval) {
@ -2656,11 +2655,6 @@ out_ident_release:
out_power_off: out_power_off:
smiapp_power_off(sensor); smiapp_power_off(sensor);
out_smiapp_power_on:
if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN)
gpio_free(sensor->platform_data->xshutdown);
return rval; return rval;
} }
@ -2854,12 +2848,10 @@ static int smiapp_remove(struct i2c_client *client)
device_remove_file(&client->dev, &dev_attr_nvm); device_remove_file(&client->dev, &dev_attr_nvm);
for (i = 0; i < sensor->ssds_used; i++) { for (i = 0; i < sensor->ssds_used; i++) {
media_entity_cleanup(&sensor->ssds[i].sd.entity);
v4l2_device_unregister_subdev(&sensor->ssds[i].sd); v4l2_device_unregister_subdev(&sensor->ssds[i].sd);
media_entity_cleanup(&sensor->ssds[i].sd.entity);
} }
smiapp_free_controls(sensor); smiapp_free_controls(sensor);
if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN)
gpio_free(sensor->platform_data->xshutdown);
return 0; return 0;
} }

View File

@ -18,8 +18,9 @@
#include <linux/module.h> #include <linux/module.h>
#include <media/soc_camera.h> #include <media/soc_camera.h>
#include <media/v4l2-async.h>
#include <media/v4l2-clk.h>
#include <media/v4l2-subdev.h> #include <media/v4l2-subdev.h>
#include <media/v4l2-chip-ident.h>
/* IMX074 registers */ /* IMX074 registers */
@ -77,6 +78,7 @@ struct imx074_datafmt {
struct imx074 { struct imx074 {
struct v4l2_subdev subdev; struct v4l2_subdev subdev;
const struct imx074_datafmt *fmt; const struct imx074_datafmt *fmt;
struct v4l2_clk *clk;
}; };
static const struct imx074_datafmt imx074_colour_fmts[] = { 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); 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) static int imx074_s_power(struct v4l2_subdev *sd, int on)
{ {
struct i2c_client *client = v4l2_get_subdevdata(sd); struct i2c_client *client = v4l2_get_subdevdata(sd);
struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); 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, 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 = { static struct v4l2_subdev_core_ops imx074_subdev_core_ops = {
.g_chip_ident = imx074_g_chip_ident,
.s_power = imx074_s_power, .s_power = imx074_s_power,
}; };
@ -431,6 +416,7 @@ static int imx074_probe(struct i2c_client *client,
struct imx074 *priv; struct imx074 *priv;
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
int ret;
if (!ssdd) { if (!ssdd) {
dev_err(&client->dev, "IMX074: missing platform data!\n"); 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]; 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) static int imx074_remove(struct i2c_client *client)
{ {
struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(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) if (ssdd->free_bus)
ssdd->free_bus(ssdd); ssdd->free_bus(ssdd);

View File

@ -16,8 +16,8 @@
#include <media/soc_camera.h> #include <media/soc_camera.h>
#include <media/soc_mediabus.h> #include <media/soc_mediabus.h>
#include <media/v4l2-clk.h>
#include <media/v4l2-subdev.h> #include <media/v4l2-subdev.h>
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
/* /*
@ -94,10 +94,10 @@ struct mt9m001 {
struct v4l2_ctrl *exposure; struct v4l2_ctrl *exposure;
}; };
struct v4l2_rect rect; /* Sensor window */ struct v4l2_rect rect; /* Sensor window */
struct v4l2_clk *clk;
const struct mt9m001_datafmt *fmt; const struct mt9m001_datafmt *fmt;
const struct mt9m001_datafmt *fmts; const struct mt9m001_datafmt *fmts;
int num_fmts; int num_fmts;
int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */
unsigned int total_h; unsigned int total_h;
unsigned short y_skip_top; /* Lines to skip at the top */ 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; 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 #ifdef CONFIG_VIDEO_ADV_DEBUG
static int mt9m001_g_register(struct v4l2_subdev *sd, static int mt9m001_g_register(struct v4l2_subdev *sd,
struct v4l2_dbg_register *reg) struct v4l2_dbg_register *reg)
{ {
struct i2c_client *client = v4l2_get_subdevdata(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; return -EINVAL;
if (reg->match.addr != client->addr)
return -ENODEV;
reg->size = 2; reg->size = 2;
reg->val = reg_read(client, reg->reg); 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); 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; return -EINVAL;
if (reg->match.addr != client->addr)
return -ENODEV;
if (reg_write(client, reg->reg, reg->val) < 0) if (reg_write(client, reg->reg, reg->val) < 0)
return -EIO; 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 i2c_client *client = v4l2_get_subdevdata(sd);
struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); 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) 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) { switch (data) {
case 0x8411: case 0x8411:
case 0x8421: case 0x8421:
mt9m001->model = V4L2_IDENT_MT9M001C12ST;
mt9m001->fmts = mt9m001_colour_fmts; mt9m001->fmts = mt9m001_colour_fmts;
break; break;
case 0x8431: case 0x8431:
mt9m001->model = V4L2_IDENT_MT9M001C12STM;
mt9m001->fmts = mt9m001_monochrome_fmts; mt9m001->fmts = mt9m001_monochrome_fmts;
break; break;
default: default:
@ -580,7 +555,6 @@ static const struct v4l2_ctrl_ops mt9m001_ctrl_ops = {
}; };
static struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = { static struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = {
.g_chip_ident = mt9m001_g_chip_ident,
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
.g_register = mt9m001_g_register, .g_register = mt9m001_g_register,
.s_register = mt9m001_s_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.width = MT9M001_MAX_WIDTH;
mt9m001->rect.height = MT9M001_MAX_HEIGHT; 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); ret = mt9m001_video_probe(ssdd, client);
if (ret) if (ret) {
v4l2_clk_put(mt9m001->clk);
eclkget:
v4l2_ctrl_handler_free(&mt9m001->hdl); v4l2_ctrl_handler_free(&mt9m001->hdl);
}
return ret; return ret;
} }
@ -722,6 +705,7 @@ static int mt9m001_remove(struct i2c_client *client)
struct mt9m001 *mt9m001 = to_mt9m001(client); struct mt9m001 *mt9m001 = to_mt9m001(client);
struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(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_device_unregister_subdev(&mt9m001->subdev);
v4l2_ctrl_handler_free(&mt9m001->hdl); v4l2_ctrl_handler_free(&mt9m001->hdl);
mt9m001_video_remove(ssdd); mt9m001_video_remove(ssdd);

View File

@ -17,9 +17,9 @@
#include <linux/module.h> #include <linux/module.h>
#include <media/soc_camera.h> #include <media/soc_camera.h>
#include <media/v4l2-clk.h>
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-chip-ident.h>
/* /*
* MT9M111, MT9M112 and MT9M131: * MT9M111, MT9M112 and MT9M131:
@ -205,10 +205,9 @@ struct mt9m111 {
struct v4l2_subdev subdev; struct v4l2_subdev subdev;
struct v4l2_ctrl_handler hdl; struct v4l2_ctrl_handler hdl;
struct v4l2_ctrl *gain; struct v4l2_ctrl *gain;
int model; /* V4L2_IDENT_MT9M111 or V4L2_IDENT_MT9M112 code
* from v4l2-chip-ident.h */
struct mt9m111_context *ctx; struct mt9m111_context *ctx;
struct v4l2_rect rect; /* cropping rectangle */ struct v4l2_rect rect; /* cropping rectangle */
struct v4l2_clk *clk;
int width; /* output */ int width; /* output */
int height; /* sizes */ int height; /* sizes */
struct mutex power_lock; /* lock to protect power_count */ struct mutex power_lock; /* lock to protect power_count */
@ -600,24 +599,6 @@ static int mt9m111_s_fmt(struct v4l2_subdev *sd,
return ret; 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 #ifdef CONFIG_VIDEO_ADV_DEBUG
static int mt9m111_g_register(struct v4l2_subdev *sd, static int mt9m111_g_register(struct v4l2_subdev *sd,
struct v4l2_dbg_register *reg) 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); struct i2c_client *client = v4l2_get_subdevdata(sd);
int val; int val;
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff) if (reg->reg > 0x2ff)
return -EINVAL; return -EINVAL;
if (reg->match.addr != client->addr)
return -ENODEV;
val = mt9m111_reg_read(client, reg->reg); val = mt9m111_reg_read(client, reg->reg);
reg->size = 2; reg->size = 2;
@ -645,12 +624,9 @@ static int mt9m111_s_register(struct v4l2_subdev *sd,
{ {
struct i2c_client *client = v4l2_get_subdevdata(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; return -EINVAL;
if (reg->match.addr != client->addr)
return -ENODEV;
if (mt9m111_reg_write(client, reg->reg, reg->val) < 0) if (mt9m111_reg_write(client, reg->reg, reg->val) < 0)
return -EIO; 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); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
int ret; int ret;
ret = soc_camera_power_on(&client->dev, ssdd); ret = soc_camera_power_on(&client->dev, ssdd, mt9m111->clk);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = mt9m111_resume(mt9m111); ret = mt9m111_resume(mt9m111);
if (ret < 0) { if (ret < 0) {
dev_err(&client->dev, "Failed to resume the sensor: %d\n", ret); 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; 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); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
mt9m111_suspend(mt9m111); 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) 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 = { static struct v4l2_subdev_core_ops mt9m111_subdev_core_ops = {
.g_chip_ident = mt9m111_g_chip_ident,
.s_power = mt9m111_s_power, .s_power = mt9m111_s_power,
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
.g_register = mt9m111_g_register, .g_register = mt9m111_g_register,
@ -923,12 +898,10 @@ static int mt9m111_video_probe(struct i2c_client *client)
switch (data) { switch (data) {
case 0x143a: /* MT9M111 or MT9M131 */ case 0x143a: /* MT9M111 or MT9M131 */
mt9m111->model = V4L2_IDENT_MT9M111;
dev_info(&client->dev, dev_info(&client->dev,
"Detected a MT9M111/MT9M131 chip ID %x\n", data); "Detected a MT9M111/MT9M131 chip ID %x\n", data);
break; break;
case 0x148c: /* MT9M112 */ case 0x148c: /* MT9M112 */
mt9m111->model = V4L2_IDENT_MT9M112;
dev_info(&client->dev, "Detected a MT9M112 chip ID %x\n", data); dev_info(&client->dev, "Detected a MT9M112 chip ID %x\n", data);
break; break;
default: default:
@ -1002,9 +975,18 @@ static int mt9m111_probe(struct i2c_client *client,
mt9m111->lastpage = -1; mt9m111->lastpage = -1;
mutex_init(&mt9m111->power_lock); 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); ret = mt9m111_video_probe(client);
if (ret) if (ret) {
v4l2_clk_put(mt9m111->clk);
eclkget:
v4l2_ctrl_handler_free(&mt9m111->hdl); v4l2_ctrl_handler_free(&mt9m111->hdl);
}
return ret; return ret;
} }
@ -1013,6 +995,7 @@ static int mt9m111_remove(struct i2c_client *client)
{ {
struct mt9m111 *mt9m111 = to_mt9m111(client); struct mt9m111 *mt9m111 = to_mt9m111(client);
v4l2_clk_put(mt9m111->clk);
v4l2_device_unregister_subdev(&mt9m111->subdev); v4l2_device_unregister_subdev(&mt9m111->subdev);
v4l2_ctrl_handler_free(&mt9m111->hdl); v4l2_ctrl_handler_free(&mt9m111->hdl);

View File

@ -18,7 +18,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <media/soc_camera.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-subdev.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
@ -76,7 +76,7 @@ struct mt9t031 {
struct v4l2_ctrl *exposure; struct v4l2_ctrl *exposure;
}; };
struct v4l2_rect rect; /* Sensor window */ struct v4l2_rect rect; /* Sensor window */
int model; /* V4L2_IDENT_MT9T031* codes from v4l2-chip-ident.h */ struct v4l2_clk *clk;
u16 xskip; u16 xskip;
u16 yskip; u16 yskip;
unsigned int total_h; unsigned int total_h;
@ -391,36 +391,16 @@ static int mt9t031_try_fmt(struct v4l2_subdev *sd,
return 0; 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 #ifdef CONFIG_VIDEO_ADV_DEBUG
static int mt9t031_g_register(struct v4l2_subdev *sd, static int mt9t031_g_register(struct v4l2_subdev *sd,
struct v4l2_dbg_register *reg) struct v4l2_dbg_register *reg)
{ {
struct i2c_client *client = v4l2_get_subdevdata(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; return -EINVAL;
if (reg->match.addr != client->addr) reg->size = 1;
return -ENODEV;
reg->val = reg_read(client, reg->reg); reg->val = reg_read(client, reg->reg);
if (reg->val > 0xffff) 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); 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; return -EINVAL;
if (reg->match.addr != client->addr)
return -ENODEV;
if (reg_write(client, reg->reg, reg->val) < 0) if (reg_write(client, reg->reg, reg->val) < 0)
return -EIO; return -EIO;
@ -595,7 +572,7 @@ static int mt9t031_runtime_resume(struct device *dev)
return 0; 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_suspend = mt9t031_runtime_suspend,
.runtime_resume = mt9t031_runtime_resume, .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 i2c_client *client = v4l2_get_subdevdata(sd);
struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
struct video_device *vdev = soc_camera_i2c_to_vdev(client); struct video_device *vdev = soc_camera_i2c_to_vdev(client);
struct mt9t031 *mt9t031 = to_mt9t031(client);
int ret; int ret;
if (on) { if (on) {
ret = soc_camera_power_on(&client->dev, ssdd); ret = soc_camera_power_on(&client->dev, ssdd, mt9t031->clk);
if (ret < 0) if (ret < 0)
return ret; return ret;
vdev->dev.type = &mt9t031_dev_type; vdev->dev.type = &mt9t031_dev_type;
} else { } else {
vdev->dev.type = NULL; vdev->dev.type = NULL;
soc_camera_power_off(&client->dev, ssdd); soc_camera_power_off(&client->dev, ssdd, mt9t031->clk);
} }
return 0; return 0;
@ -650,7 +628,6 @@ static int mt9t031_video_probe(struct i2c_client *client)
switch (data) { switch (data) {
case 0x1621: case 0x1621:
mt9t031->model = V4L2_IDENT_MT9T031;
break; break;
default: default:
dev_err(&client->dev, 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 = { static struct v4l2_subdev_core_ops mt9t031_subdev_core_ops = {
.g_chip_ident = mt9t031_g_chip_ident,
.s_power = mt9t031_s_power, .s_power = mt9t031_s_power,
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
.g_register = mt9t031_g_register, .g_register = mt9t031_g_register,
@ -812,9 +788,18 @@ static int mt9t031_probe(struct i2c_client *client,
mt9t031->xskip = 1; mt9t031->xskip = 1;
mt9t031->yskip = 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); ret = mt9t031_video_probe(client);
if (ret) if (ret) {
v4l2_clk_put(mt9t031->clk);
eclkget:
v4l2_ctrl_handler_free(&mt9t031->hdl); v4l2_ctrl_handler_free(&mt9t031->hdl);
}
return ret; return ret;
} }
@ -823,6 +808,7 @@ static int mt9t031_remove(struct i2c_client *client)
{ {
struct mt9t031 *mt9t031 = to_mt9t031(client); struct mt9t031 *mt9t031 = to_mt9t031(client);
v4l2_clk_put(mt9t031->clk);
v4l2_device_unregister_subdev(&mt9t031->subdev); v4l2_device_unregister_subdev(&mt9t031->subdev);
v4l2_ctrl_handler_free(&mt9t031->hdl); v4l2_ctrl_handler_free(&mt9t031->hdl);

View File

@ -27,7 +27,7 @@
#include <media/mt9t112.h> #include <media/mt9t112.h>
#include <media/soc_camera.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-common.h>
/* you can check PLL/clock info */ /* you can check PLL/clock info */
@ -90,8 +90,8 @@ struct mt9t112_priv {
struct mt9t112_camera_info *info; struct mt9t112_camera_info *info;
struct i2c_client *client; struct i2c_client *client;
struct v4l2_rect frame; struct v4l2_rect frame;
struct v4l2_clk *clk;
const struct mt9t112_format *format; const struct mt9t112_format *format;
int model;
int num_formats; int num_formats;
u32 flags; u32 flags;
/* for flags */ /* for flags */
@ -738,17 +738,6 @@ static int mt9t112_init_camera(const struct i2c_client *client)
/************************************************************************ /************************************************************************
v4l2_subdev_core_ops 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 #ifdef CONFIG_VIDEO_ADV_DEBUG
static int mt9t112_g_register(struct v4l2_subdev *sd, 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 i2c_client *client = v4l2_get_subdevdata(sd);
struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); 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 = { static struct v4l2_subdev_core_ops mt9t112_subdev_core_ops = {
.g_chip_ident = mt9t112_g_chip_ident,
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
.g_register = mt9t112_g_register, .g_register = mt9t112_g_register,
.s_register = mt9t112_s_register, .s_register = mt9t112_s_register,
@ -1061,12 +1050,10 @@ static int mt9t112_camera_probe(struct i2c_client *client)
switch (chipid) { switch (chipid) {
case 0x2680: case 0x2680:
devname = "mt9t111"; devname = "mt9t111";
priv->model = V4L2_IDENT_MT9T111;
priv->num_formats = 1; priv->num_formats = 1;
break; break;
case 0x2682: case 0x2682:
devname = "mt9t112"; devname = "mt9t112";
priv->model = V4L2_IDENT_MT9T112;
priv->num_formats = ARRAY_SIZE(mt9t112_cfmts); priv->num_formats = ARRAY_SIZE(mt9t112_cfmts);
break; break;
default: default:
@ -1108,18 +1095,26 @@ static int mt9t112_probe(struct i2c_client *client,
v4l2_i2c_subdev_init(&priv->subdev, client, &mt9t112_subdev_ops); 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); ret = mt9t112_camera_probe(client);
if (ret)
return ret;
/* Cannot fail: using the default supported pixel code */ /* 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; return ret;
} }
static int mt9t112_remove(struct i2c_client *client) static int mt9t112_remove(struct i2c_client *client)
{ {
struct mt9t112_priv *priv = to_mt9t112(client);
v4l2_clk_put(priv->clk);
return 0; return 0;
} }

View File

@ -19,7 +19,7 @@
#include <media/soc_camera.h> #include <media/soc_camera.h>
#include <media/soc_mediabus.h> #include <media/soc_mediabus.h>
#include <media/v4l2-subdev.h> #include <media/v4l2-subdev.h>
#include <media/v4l2-chip-ident.h> #include <media/v4l2-clk.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
/* /*
@ -133,6 +133,11 @@ static const struct mt9v02x_register mt9v024_register = {
.pixclk_fv_lv = MT9V024_PIXCLK_FV_LV, .pixclk_fv_lv = MT9V024_PIXCLK_FV_LV,
}; };
enum mt9v022_model {
MT9V022IX7ATM,
MT9V022IX7ATC,
};
struct mt9v022 { struct mt9v022 {
struct v4l2_subdev subdev; struct v4l2_subdev subdev;
struct v4l2_ctrl_handler hdl; struct v4l2_ctrl_handler hdl;
@ -149,11 +154,12 @@ struct mt9v022 {
struct v4l2_ctrl *hblank; struct v4l2_ctrl *hblank;
struct v4l2_ctrl *vblank; struct v4l2_ctrl *vblank;
struct v4l2_rect rect; /* Sensor window */ struct v4l2_rect rect; /* Sensor window */
struct v4l2_clk *clk;
const struct mt9v022_datafmt *fmt; const struct mt9v022_datafmt *fmt;
const struct mt9v022_datafmt *fmts; const struct mt9v022_datafmt *fmts;
const struct mt9v02x_register *reg; const struct mt9v02x_register *reg;
int num_fmts; int num_fmts;
int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */ enum mt9v022_model model;
u16 chip_control; u16 chip_control;
u16 chip_version; u16 chip_version;
unsigned short y_skip_top; /* Lines to skip at the top */ 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) { switch (mf->code) {
case V4L2_MBUS_FMT_Y8_1X8: case V4L2_MBUS_FMT_Y8_1X8:
case V4L2_MBUS_FMT_Y10_1X10: case V4L2_MBUS_FMT_Y10_1X10:
if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATM) if (mt9v022->model != MT9V022IX7ATM)
return -EINVAL; return -EINVAL;
break; break;
case V4L2_MBUS_FMT_SBGGR8_1X8: case V4L2_MBUS_FMT_SBGGR8_1X8:
case V4L2_MBUS_FMT_SBGGR10_1X10: case V4L2_MBUS_FMT_SBGGR10_1X10:
if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATC) if (mt9v022->model != MT9V022IX7ATC)
return -EINVAL; return -EINVAL;
break; break;
default: default:
@ -457,36 +463,15 @@ static int mt9v022_try_fmt(struct v4l2_subdev *sd,
return 0; 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 #ifdef CONFIG_VIDEO_ADV_DEBUG
static int mt9v022_g_register(struct v4l2_subdev *sd, static int mt9v022_g_register(struct v4l2_subdev *sd,
struct v4l2_dbg_register *reg) struct v4l2_dbg_register *reg)
{ {
struct i2c_client *client = v4l2_get_subdevdata(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; return -EINVAL;
if (reg->match.addr != client->addr)
return -ENODEV;
reg->size = 2; reg->size = 2;
reg->val = reg_read(client, reg->reg); 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); 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; return -EINVAL;
if (reg->match.addr != client->addr)
return -ENODEV;
if (reg_write(client, reg->reg, reg->val) < 0) if (reg_write(client, reg->reg, reg->val) < 0)
return -EIO; 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 i2c_client *client = v4l2_get_subdevdata(sd);
struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); 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) 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) || if (sensor_type && (!strcmp("colour", sensor_type) ||
!strcmp("color", sensor_type))) { !strcmp("color", sensor_type))) {
ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11); ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11);
mt9v022->model = V4L2_IDENT_MT9V022IX7ATC; mt9v022->model = MT9V022IX7ATC;
mt9v022->fmts = mt9v022_colour_fmts; mt9v022->fmts = mt9v022_colour_fmts;
} else { } else {
ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 0x11); ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 0x11);
mt9v022->model = V4L2_IDENT_MT9V022IX7ATM; mt9v022->model = MT9V022IX7ATM;
mt9v022->fmts = mt9v022_monochrome_fmts; mt9v022->fmts = mt9v022_monochrome_fmts;
} }
@ -740,7 +723,7 @@ static int mt9v022_video_probe(struct i2c_client *client)
mt9v022->fmt = &mt9v022->fmts[0]; mt9v022->fmt = &mt9v022->fmts[0];
dev_info(&client->dev, "Detected a MT9V022 chip ID %x, %s sensor\n", 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"); "monochrome" : "colour");
ret = mt9v022_init(client); 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 = { static struct v4l2_subdev_core_ops mt9v022_subdev_core_ops = {
.g_chip_ident = mt9v022_g_chip_ident,
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
.g_register = mt9v022_g_register, .g_register = mt9v022_g_register,
.s_register = mt9v022_s_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.width = MT9V022_MAX_WIDTH;
mt9v022->rect.height = MT9V022_MAX_HEIGHT; 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); ret = mt9v022_video_probe(client);
if (ret) if (ret) {
v4l2_clk_put(mt9v022->clk);
eclkget:
v4l2_ctrl_handler_free(&mt9v022->hdl); v4l2_ctrl_handler_free(&mt9v022->hdl);
}
return ret; return ret;
} }
@ -969,6 +960,7 @@ static int mt9v022_remove(struct i2c_client *client)
struct mt9v022 *mt9v022 = to_mt9v022(client); struct mt9v022 *mt9v022 = to_mt9v022(client);
struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
v4l2_clk_put(mt9v022->clk);
v4l2_device_unregister_subdev(&mt9v022->subdev); v4l2_device_unregister_subdev(&mt9v022->subdev);
if (ssdd->free_bus) if (ssdd->free_bus)
ssdd->free_bus(ssdd); ssdd->free_bus(ssdd);

View File

@ -22,7 +22,7 @@
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <media/soc_camera.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-subdev.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
@ -303,8 +303,8 @@ struct ov2640_priv {
struct v4l2_subdev subdev; struct v4l2_subdev subdev;
struct v4l2_ctrl_handler hdl; struct v4l2_ctrl_handler hdl;
enum v4l2_mbus_pixelcode cfmt_code; enum v4l2_mbus_pixelcode cfmt_code;
struct v4l2_clk *clk;
const struct ov2640_win_size *win; const struct ov2640_win_size *win;
int model;
}; };
/* /*
@ -723,18 +723,6 @@ static int ov2640_s_ctrl(struct v4l2_ctrl *ctrl)
return -EINVAL; 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 #ifdef CONFIG_VIDEO_ADV_DEBUG
static int ov2640_g_register(struct v4l2_subdev *sd, static int ov2640_g_register(struct v4l2_subdev *sd,
struct v4l2_dbg_register *reg) 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 i2c_client *client = v4l2_get_subdevdata(sd);
struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); 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 */ /* Select the nearest higher resolution for capture */
@ -1009,7 +998,6 @@ static int ov2640_video_probe(struct i2c_client *client)
switch (VERSION(pid, ver)) { switch (VERSION(pid, ver)) {
case PID_OV2640: case PID_OV2640:
devname = "ov2640"; devname = "ov2640";
priv->model = V4L2_IDENT_OV2640;
break; break;
default: default:
dev_err(&client->dev, 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 = { static struct v4l2_subdev_core_ops ov2640_subdev_core_ops = {
.g_chip_ident = ov2640_g_chip_ident,
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
.g_register = ov2640_g_register, .g_register = ov2640_g_register,
.s_register = ov2640_s_register, .s_register = ov2640_s_register,
@ -1113,11 +1100,20 @@ static int ov2640_probe(struct i2c_client *client,
if (priv->hdl.error) if (priv->hdl.error)
return 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); ret = ov2640_video_probe(client);
if (ret) if (ret) {
v4l2_clk_put(priv->clk);
eclkget:
v4l2_ctrl_handler_free(&priv->hdl); v4l2_ctrl_handler_free(&priv->hdl);
else } else {
dev_info(&adapter->dev, "OV2640 Probed\n"); dev_info(&adapter->dev, "OV2640 Probed\n");
}
return ret; return ret;
} }
@ -1126,6 +1122,7 @@ static int ov2640_remove(struct i2c_client *client)
{ {
struct ov2640_priv *priv = to_ov2640(client); struct ov2640_priv *priv = to_ov2640(client);
v4l2_clk_put(priv->clk);
v4l2_device_unregister_subdev(&priv->subdev); v4l2_device_unregister_subdev(&priv->subdev);
v4l2_ctrl_handler_free(&priv->hdl); v4l2_ctrl_handler_free(&priv->hdl);
return 0; return 0;

View File

@ -24,7 +24,7 @@
#include <linux/v4l2-mediabus.h> #include <linux/v4l2-mediabus.h>
#include <media/soc_camera.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-subdev.h>
/* OV5642 registers */ /* OV5642 registers */
@ -610,6 +610,7 @@ struct ov5642 {
struct v4l2_subdev subdev; struct v4l2_subdev subdev;
const struct ov5642_datafmt *fmt; const struct ov5642_datafmt *fmt;
struct v4l2_rect crop_rect; struct v4l2_rect crop_rect;
struct v4l2_clk *clk;
/* blanking information */ /* blanking information */
int total_width; int total_width;
@ -848,23 +849,6 @@ static int ov5642_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
return 0; 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) static int ov5642_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
{ {
struct i2c_client *client = v4l2_get_subdevdata(sd); 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 i2c_client *client = v4l2_get_subdevdata(sd);
struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
struct ov5642 *priv = to_ov5642(client);
int ret; int ret;
if (!on) 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) if (ret < 0)
return ret; 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 = { static struct v4l2_subdev_core_ops ov5642_subdev_core_ops = {
.s_power = ov5642_s_power, .s_power = ov5642_s_power,
.g_chip_ident = ov5642_g_chip_ident,
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
.g_register = ov5642_get_register, .g_register = ov5642_get_register,
.s_register = ov5642_set_register, .s_register = ov5642_set_register,
@ -1021,6 +1005,7 @@ static int ov5642_probe(struct i2c_client *client,
{ {
struct ov5642 *priv; struct ov5642 *priv;
struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
int ret;
if (!ssdd) { if (!ssdd) {
dev_err(&client->dev, "OV5642: missing platform data!\n"); 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_width = OV5642_DEFAULT_WIDTH + BLANKING_EXTRA_WIDTH;
priv->total_height = BLANKING_MIN_HEIGHT; 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) static int ov5642_remove(struct i2c_client *client)
{ {
struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(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) if (ssdd->free_bus)
ssdd->free_bus(ssdd); ssdd->free_bus(ssdd);

View File

@ -32,7 +32,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <media/soc_camera.h> #include <media/soc_camera.h>
#include <media/v4l2-chip-ident.h> #include <media/v4l2-clk.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
/* Register definitions */ /* Register definitions */
@ -196,6 +196,7 @@ struct ov6650 {
struct v4l2_ctrl *blue; struct v4l2_ctrl *blue;
struct v4l2_ctrl *red; struct v4l2_ctrl *red;
}; };
struct v4l2_clk *clk;
bool half_scale; /* scale down output by 2 */ bool half_scale; /* scale down output by 2 */
struct v4l2_rect rect; /* sensor cropping window */ struct v4l2_rect rect; /* sensor cropping window */
unsigned long pclk_limit; /* from host */ unsigned long pclk_limit; /* from host */
@ -390,16 +391,6 @@ static int ov6550_s_ctrl(struct v4l2_ctrl *ctrl)
return -EINVAL; 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 #ifdef CONFIG_VIDEO_ADV_DEBUG
static int ov6650_get_register(struct v4l2_subdev *sd, static int ov6650_get_register(struct v4l2_subdev *sd,
struct v4l2_dbg_register *reg) 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 i2c_client *client = v4l2_get_subdevdata(sd);
struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); 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) 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 = { static struct v4l2_subdev_core_ops ov6650_core_ops = {
.g_chip_ident = ov6650_g_chip_ident,
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
.g_register = ov6650_get_register, .g_register = ov6650_get_register,
.s_register = ov6650_set_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->code = V4L2_MBUS_FMT_YUYV8_2X8;
priv->colorspace = V4L2_COLORSPACE_JPEG; 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); ret = ov6650_video_probe(client);
if (ret) if (ret) {
v4l2_clk_put(priv->clk);
eclkget:
v4l2_ctrl_handler_free(&priv->hdl); v4l2_ctrl_handler_free(&priv->hdl);
}
return ret; return ret;
} }
@ -1036,6 +1036,7 @@ static int ov6650_remove(struct i2c_client *client)
{ {
struct ov6650 *priv = to_ov6650(client); struct ov6650 *priv = to_ov6650(client);
v4l2_clk_put(priv->clk);
v4l2_device_unregister_subdev(&priv->subdev); v4l2_device_unregister_subdev(&priv->subdev);
v4l2_ctrl_handler_free(&priv->hdl); v4l2_ctrl_handler_free(&priv->hdl);
return 0; return 0;

View File

@ -26,8 +26,8 @@
#include <media/ov772x.h> #include <media/ov772x.h>
#include <media/soc_camera.h> #include <media/soc_camera.h>
#include <media/v4l2-clk.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-subdev.h> #include <media/v4l2-subdev.h>
/* /*
@ -396,10 +396,10 @@ struct ov772x_win_size {
struct ov772x_priv { struct ov772x_priv {
struct v4l2_subdev subdev; struct v4l2_subdev subdev;
struct v4l2_ctrl_handler hdl; struct v4l2_ctrl_handler hdl;
struct v4l2_clk *clk;
struct ov772x_camera_info *info; struct ov772x_camera_info *info;
const struct ov772x_color_format *cfmt; const struct ov772x_color_format *cfmt;
const struct ov772x_win_size *win; const struct ov772x_win_size *win;
int model;
unsigned short flag_vflip:1; unsigned short flag_vflip:1;
unsigned short flag_hflip:1; unsigned short flag_hflip:1;
/* band_filter = COM8[5] ? 256 - BDBASE : 0 */ /* band_filter = COM8[5] ? 256 - BDBASE : 0 */
@ -620,17 +620,6 @@ static int ov772x_s_ctrl(struct v4l2_ctrl *ctrl)
return -EINVAL; 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 #ifdef CONFIG_VIDEO_ADV_DEBUG
static int ov772x_g_register(struct v4l2_subdev *sd, static int ov772x_g_register(struct v4l2_subdev *sd,
struct v4l2_dbg_register *reg) 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 i2c_client *client = v4l2_get_subdevdata(sd);
struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); 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) 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)) { switch (VERSION(pid, ver)) {
case OV7720: case OV7720:
devname = "ov7720"; devname = "ov7720";
priv->model = V4L2_IDENT_OV7720;
break; break;
case OV7725: case OV7725:
devname = "ov7725"; devname = "ov7725";
priv->model = V4L2_IDENT_OV7725;
break; break;
default: default:
dev_err(&client->dev, 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 = { static struct v4l2_subdev_core_ops ov772x_subdev_core_ops = {
.g_chip_ident = ov772x_g_chip_ident,
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
.g_register = ov772x_g_register, .g_register = ov772x_g_register,
.s_register = ov772x_s_register, .s_register = ov772x_s_register,
@ -1088,13 +1075,22 @@ static int ov772x_probe(struct i2c_client *client,
if (priv->hdl.error) if (priv->hdl.error)
return 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); ret = ov772x_video_probe(priv);
if (ret < 0) { if (ret < 0) {
v4l2_clk_put(priv->clk);
eclkget:
v4l2_ctrl_handler_free(&priv->hdl); v4l2_ctrl_handler_free(&priv->hdl);
} else { } else {
priv->cfmt = &ov772x_cfmts[0]; priv->cfmt = &ov772x_cfmts[0];
priv->win = &ov772x_win_sizes[0]; priv->win = &ov772x_win_sizes[0];
} }
return ret; return ret;
} }
@ -1102,6 +1098,7 @@ static int ov772x_remove(struct i2c_client *client)
{ {
struct ov772x_priv *priv = to_ov772x(i2c_get_clientdata(client)); struct ov772x_priv *priv = to_ov772x(i2c_get_clientdata(client));
v4l2_clk_put(priv->clk);
v4l2_device_unregister_subdev(&priv->subdev); v4l2_device_unregister_subdev(&priv->subdev);
v4l2_ctrl_handler_free(&priv->hdl); v4l2_ctrl_handler_free(&priv->hdl);
return 0; return 0;

View File

@ -28,7 +28,7 @@
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <media/soc_camera.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-common.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
@ -61,7 +61,7 @@ static const struct ov9640_reg ov9640_regs_dflt[] = {
/* Configurations /* Configurations
* NOTE: for YUV, alter the following registers: * NOTE: for YUV, alter the following registers:
* COM12 |= OV9640_COM12_YUV_AVG * COM12 |= OV9640_COM12_YUV_AVG
* *
* for RGB, alter the following registers: * for RGB, alter the following registers:
* COM7 |= OV9640_COM7_RGB * COM7 |= OV9640_COM7_RGB
@ -287,18 +287,6 @@ static int ov9640_s_ctrl(struct v4l2_ctrl *ctrl)
return -EINVAL; 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 #ifdef CONFIG_VIDEO_ADV_DEBUG
static int ov9640_get_register(struct v4l2_subdev *sd, static int ov9640_get_register(struct v4l2_subdev *sd,
struct v4l2_dbg_register *reg) 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 i2c_client *client = v4l2_get_subdevdata(sd);
struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); 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 */ /* select nearest higher resolution for capture */
@ -615,12 +604,10 @@ static int ov9640_video_probe(struct i2c_client *client)
switch (VERSION(pid, ver)) { switch (VERSION(pid, ver)) {
case OV9640_V2: case OV9640_V2:
devname = "ov9640"; devname = "ov9640";
priv->model = V4L2_IDENT_OV9640;
priv->revision = 2; priv->revision = 2;
break; break;
case OV9640_V3: case OV9640_V3:
devname = "ov9640"; devname = "ov9640";
priv->model = V4L2_IDENT_OV9640;
priv->revision = 3; priv->revision = 3;
break; break;
default: default:
@ -644,7 +631,6 @@ static const struct v4l2_ctrl_ops ov9640_ctrl_ops = {
}; };
static struct v4l2_subdev_core_ops ov9640_core_ops = { static struct v4l2_subdev_core_ops ov9640_core_ops = {
.g_chip_ident = ov9640_g_chip_ident,
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
.g_register = ov9640_get_register, .g_register = ov9640_get_register,
.s_register = ov9640_set_register, .s_register = ov9640_set_register,
@ -716,10 +702,18 @@ static int ov9640_probe(struct i2c_client *client,
if (priv->hdl.error) if (priv->hdl.error)
return 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); v4l2_ctrl_handler_free(&priv->hdl);
}
return ret; return ret;
} }
@ -729,6 +723,7 @@ static int ov9640_remove(struct i2c_client *client)
struct v4l2_subdev *sd = i2c_get_clientdata(client); struct v4l2_subdev *sd = i2c_get_clientdata(client);
struct ov9640_priv *priv = to_ov9640_sensor(sd); struct ov9640_priv *priv = to_ov9640_sensor(sd);
v4l2_clk_put(priv->clk);
v4l2_device_unregister_subdev(&priv->subdev); v4l2_device_unregister_subdev(&priv->subdev);
v4l2_ctrl_handler_free(&priv->hdl); v4l2_ctrl_handler_free(&priv->hdl);
return 0; return 0;

View File

@ -199,6 +199,7 @@ struct ov9640_reg {
struct ov9640_priv { struct ov9640_priv {
struct v4l2_subdev subdev; struct v4l2_subdev subdev;
struct v4l2_ctrl_handler hdl; struct v4l2_ctrl_handler hdl;
struct v4l2_clk *clk;
int model; int model;
int revision; int revision;

View File

@ -17,7 +17,7 @@
#include <linux/v4l2-mediabus.h> #include <linux/v4l2-mediabus.h>
#include <media/soc_camera.h> #include <media/soc_camera.h>
#include <media/v4l2-chip-ident.h> #include <media/v4l2-clk.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#define to_ov9740(sd) container_of(sd, struct ov9740_priv, subdev) #define to_ov9740(sd) container_of(sd, struct ov9740_priv, subdev)
@ -196,8 +196,8 @@ struct ov9740_reg {
struct ov9740_priv { struct ov9740_priv {
struct v4l2_subdev subdev; struct v4l2_subdev subdev;
struct v4l2_ctrl_handler hdl; struct v4l2_ctrl_handler hdl;
struct v4l2_clk *clk;
int ident;
u16 model; u16 model;
u8 revision; u8 revision;
u8 manid; u8 manid;
@ -772,18 +772,6 @@ static int ov9740_s_ctrl(struct v4l2_ctrl *ctrl)
return 0; 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) static int ov9740_s_power(struct v4l2_subdev *sd, int on)
{ {
struct i2c_client *client = v4l2_get_subdevdata(sd); 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; int ret;
if (on) { if (on) {
ret = soc_camera_power_on(&client->dev, ssdd); ret = soc_camera_power_on(&client->dev, ssdd, priv->clk);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -806,7 +794,7 @@ static int ov9740_s_power(struct v4l2_subdev *sd, int on)
priv->current_enable = true; priv->current_enable = true;
} }
soc_camera_power_off(&client->dev, ssdd); soc_camera_power_off(&client->dev, ssdd, priv->clk);
} }
return 0; return 0;
@ -887,8 +875,6 @@ static int ov9740_video_probe(struct i2c_client *client)
goto done; goto done;
} }
priv->ident = V4L2_IDENT_OV9740;
dev_info(&client->dev, "ov9740 Model ID 0x%04x, Revision 0x%02x, " dev_info(&client->dev, "ov9740 Model ID 0x%04x, Revision 0x%02x, "
"Manufacturer 0x%02x, SMIA Version 0x%02x\n", "Manufacturer 0x%02x, SMIA Version 0x%02x\n",
priv->model, priv->revision, priv->manid, priv->smiaver); 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 = { static struct v4l2_subdev_core_ops ov9740_core_ops = {
.g_chip_ident = ov9740_g_chip_ident,
.s_power = ov9740_s_power, .s_power = ov9740_s_power,
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
.g_register = ov9740_get_register, .g_register = ov9740_get_register,
@ -975,9 +960,18 @@ static int ov9740_probe(struct i2c_client *client,
if (priv->hdl.error) if (priv->hdl.error)
return 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); ret = ov9740_video_probe(client);
if (ret < 0) if (ret < 0) {
v4l2_clk_put(priv->clk);
eclkget:
v4l2_ctrl_handler_free(&priv->hdl); v4l2_ctrl_handler_free(&priv->hdl);
}
return ret; return ret;
} }
@ -986,6 +980,7 @@ static int ov9740_remove(struct i2c_client *client)
{ {
struct ov9740_priv *priv = i2c_get_clientdata(client); struct ov9740_priv *priv = i2c_get_clientdata(client);
v4l2_clk_put(priv->clk);
v4l2_device_unregister_subdev(&priv->subdev); v4l2_device_unregister_subdev(&priv->subdev);
v4l2_ctrl_handler_free(&priv->hdl); v4l2_ctrl_handler_free(&priv->hdl);
return 0; return 0;

View File

@ -17,8 +17,8 @@
#include <media/rj54n1cb0c.h> #include <media/rj54n1cb0c.h>
#include <media/soc_camera.h> #include <media/soc_camera.h>
#include <media/v4l2-clk.h>
#include <media/v4l2-subdev.h> #include <media/v4l2-subdev.h>
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#define RJ54N1_DEV_CODE 0x0400 #define RJ54N1_DEV_CODE 0x0400
@ -151,6 +151,7 @@ struct rj54n1_clock_div {
struct rj54n1 { struct rj54n1 {
struct v4l2_subdev subdev; struct v4l2_subdev subdev;
struct v4l2_ctrl_handler hdl; struct v4l2_ctrl_handler hdl;
struct v4l2_clk *clk;
struct rj54n1_clock_div clk_div; struct rj54n1_clock_div clk_div;
const struct rj54n1_datafmt *fmt; const struct rj54n1_datafmt *fmt;
struct v4l2_rect rect; /* Sensor window */ struct v4l2_rect rect; /* Sensor window */
@ -1120,37 +1121,16 @@ static int rj54n1_s_fmt(struct v4l2_subdev *sd,
return 0; 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 #ifdef CONFIG_VIDEO_ADV_DEBUG
static int rj54n1_g_register(struct v4l2_subdev *sd, static int rj54n1_g_register(struct v4l2_subdev *sd,
struct v4l2_dbg_register *reg) struct v4l2_dbg_register *reg)
{ {
struct i2c_client *client = v4l2_get_subdevdata(sd); struct i2c_client *client = v4l2_get_subdevdata(sd);
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || if (reg->reg < 0x400 || reg->reg > 0x1fff)
reg->reg < 0x400 || reg->reg > 0x1fff)
/* Registers > 0x0800 are only available from Sharp support */ /* Registers > 0x0800 are only available from Sharp support */
return -EINVAL; return -EINVAL;
if (reg->match.addr != client->addr)
return -ENODEV;
reg->size = 1; reg->size = 1;
reg->val = reg_read(client, reg->reg); 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); struct i2c_client *client = v4l2_get_subdevdata(sd);
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || if (reg->reg < 0x400 || reg->reg > 0x1fff)
reg->reg < 0x400 || reg->reg > 0x1fff)
/* Registers >= 0x0800 are only available from Sharp support */ /* Registers >= 0x0800 are only available from Sharp support */
return -EINVAL; return -EINVAL;
if (reg->match.addr != client->addr)
return -ENODEV;
if (reg_write(client, reg->reg, reg->val) < 0) if (reg_write(client, reg->reg, reg->val) < 0)
return -EIO; 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 i2c_client *client = v4l2_get_subdevdata(sd);
struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); 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) 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 = { static struct v4l2_subdev_core_ops rj54n1_subdev_core_ops = {
.g_chip_ident = rj54n1_g_chip_ident,
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
.g_register = rj54n1_g_register, .g_register = rj54n1_g_register,
.s_register = rj54n1_s_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) / rj54n1->tgclk_mhz = (rj54n1_priv->mclk_freq / PLL_L * PLL_N) /
(clk_div.ratio_tg + 1) / (clk_div.ratio_t + 1); (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); 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); v4l2_ctrl_handler_free(&rj54n1->hdl);
}
return ret; return ret;
} }
@ -1394,6 +1379,7 @@ static int rj54n1_remove(struct i2c_client *client)
struct rj54n1 *rj54n1 = to_rj54n1(client); struct rj54n1 *rj54n1 = to_rj54n1(client);
struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
v4l2_clk_put(rj54n1->clk);
v4l2_device_unregister_subdev(&rj54n1->subdev); v4l2_device_unregister_subdev(&rj54n1->subdev);
if (ssdd->free_bus) if (ssdd->free_bus)
ssdd->free_bus(ssdd); ssdd->free_bus(ssdd);

View File

@ -27,7 +27,7 @@
#include <media/soc_camera.h> #include <media/soc_camera.h>
#include <media/tw9910.h> #include <media/tw9910.h>
#include <media/v4l2-chip-ident.h> #include <media/v4l2-clk.h>
#include <media/v4l2-subdev.h> #include <media/v4l2-subdev.h>
#define GET_ID(val) ((val & 0xF8) >> 3) #define GET_ID(val) ((val & 0xF8) >> 3)
@ -228,6 +228,7 @@ struct tw9910_scale_ctrl {
struct tw9910_priv { struct tw9910_priv {
struct v4l2_subdev subdev; struct v4l2_subdev subdev;
struct v4l2_clk *clk;
struct tw9910_video_info *info; struct tw9910_video_info *info;
const struct tw9910_scale_ctrl *scale; const struct tw9910_scale_ctrl *scale;
v4l2_std_id norm; v4l2_std_id norm;
@ -518,18 +519,6 @@ static int tw9910_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
return 0; 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 #ifdef CONFIG_VIDEO_ADV_DEBUG
static int tw9910_g_register(struct v4l2_subdev *sd, static int tw9910_g_register(struct v4l2_subdev *sd,
struct v4l2_dbg_register *reg) struct v4l2_dbg_register *reg)
@ -540,6 +529,7 @@ static int tw9910_g_register(struct v4l2_subdev *sd,
if (reg->reg > 0xff) if (reg->reg > 0xff)
return -EINVAL; return -EINVAL;
reg->size = 1;
ret = i2c_smbus_read_byte_data(client, reg->reg); ret = i2c_smbus_read_byte_data(client, reg->reg);
if (ret < 0) if (ret < 0)
return ret; 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 i2c_client *client = v4l2_get_subdevdata(sd);
struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); 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) 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 = { static struct v4l2_subdev_core_ops tw9910_subdev_core_ops = {
.g_chip_ident = tw9910_g_chip_ident,
.s_std = tw9910_s_std, .s_std = tw9910_s_std,
.g_std = tw9910_g_std, .g_std = tw9910_g_std,
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
@ -912,6 +902,7 @@ static int tw9910_probe(struct i2c_client *client,
struct i2c_adapter *adapter = struct i2c_adapter *adapter =
to_i2c_adapter(client->dev.parent); to_i2c_adapter(client->dev.parent);
struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
int ret;
if (!ssdd || !ssdd->drv_priv) { if (!ssdd || !ssdd->drv_priv) {
dev_err(&client->dev, "TW9910: missing platform data!\n"); 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); 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) static int tw9910_remove(struct i2c_client *client)
{ {
struct tw9910_priv *priv = to_tw9910(client);
v4l2_clk_put(priv->clk);
return 0; return 0;
} }

View File

@ -30,7 +30,7 @@ MODULE_LICENSE("GPL v2");
static int debug; static int debug;
module_param(debug, int, 0644); 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 */ /* #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", v4l_info(client, "chip found @ 0x%x (%s)\n",
client->addr << 1, client->adapter->name); 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) if (t == NULL)
return -ENOMEM; return -ENOMEM;
@ -374,7 +374,6 @@ static int sony_btf_mpx_remove(struct i2c_client *client)
struct v4l2_subdev *sd = i2c_get_clientdata(client); struct v4l2_subdev *sd = i2c_get_clientdata(client);
v4l2_device_unregister_subdev(sd); v4l2_device_unregister_subdev(sd);
kfree(to_state(sd));
return 0; return 0;
} }

View File

@ -23,6 +23,7 @@
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-subdev.h> #include <media/v4l2-subdev.h>
#include <media/v4l2-mediabus.h> #include <media/v4l2-mediabus.h>
#include <media/v4l2-ctrls.h>
#include <media/sr030pc30.h> #include <media/sr030pc30.h>
static int debug; static int debug;
@ -142,17 +143,24 @@ module_param(debug, int, 0644);
struct sr030pc30_info { struct sr030pc30_info {
struct v4l2_subdev sd; struct v4l2_subdev sd;
struct v4l2_ctrl_handler hdl;
const struct sr030pc30_platform_data *pdata; const struct sr030pc30_platform_data *pdata;
const struct sr030pc30_format *curr_fmt; const struct sr030pc30_format *curr_fmt;
const struct sr030pc30_frmsize *curr_win; const struct sr030pc30_frmsize *curr_win;
unsigned int auto_wb:1;
unsigned int auto_exp:1;
unsigned int hflip:1; unsigned int hflip:1;
unsigned int vflip:1; unsigned int vflip:1;
unsigned int sleep:1; unsigned int sleep:1;
unsigned int exposure; struct {
u8 blue_balance; /* auto whitebalance control cluster */
u8 red_balance; 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; u8 i2c_reg_page;
}; };
@ -173,52 +181,6 @@ struct i2c_regval {
u16 val; 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 */ /* supported resolutions */
static const struct sr030pc30_frmsize sr030pc30_sizes[] = { static const struct sr030pc30_frmsize sr030pc30_sizes[] = {
{ {
@ -394,48 +356,6 @@ static int sr030pc30_pwr_ctrl(struct v4l2_subdev *sd,
return ret; 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) static int sr030pc30_set_flip(struct v4l2_subdev *sd)
{ {
struct sr030pc30_info *info = to_sr030pc30(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; return -EINVAL;
} }
static int sr030pc30_queryctrl(struct v4l2_subdev *sd, static int sr030pc30_s_ctrl(struct v4l2_ctrl *ctrl)
struct v4l2_queryctrl *qc)
{ {
int i; struct sr030pc30_info *info =
container_of(ctrl->handler, struct sr030pc30_info, hdl);
for (i = 0; i < ARRAY_SIZE(sr030pc30_ctrl); i++) struct v4l2_subdev *sd = &info->sd;
if (qc->id == sr030pc30_ctrl[i].id) { int ret = 0;
*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)
{
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;
v4l2_dbg(1, debug, sd, "%s: ctrl_id: %d, value: %d\n", 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) { switch (ctrl->id) {
case V4L2_CID_AUTO_WHITE_BALANCE: case V4L2_CID_AUTO_WHITE_BALANCE:
sr030pc30_enable_autowhitebalance(sd, ctrl->value); if (ctrl->is_new) {
break; ret = cam_i2c_write(sd, AWB_CTL2_REG,
case V4L2_CID_BLUE_BALANCE: ctrl->val ? 0x2E : 0x2F);
ret = sr030pc30_set_bluebalance(sd, ctrl->value); if (!ret)
break; ret = cam_i2c_write(sd, AWB_CTL1_REG,
case V4L2_CID_RED_BALANCE: ctrl->val ? 0xFB : 0x7B);
ret = sr030pc30_set_redbalance(sd, ctrl->value); }
break; 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;
case V4L2_CID_EXPOSURE_AUTO: case V4L2_CID_EXPOSURE_AUTO:
sr030pc30_enable_autoexposure(sd, /* auto anti-flicker is also enabled here */
ctrl->value == V4L2_EXPOSURE_AUTO); if (ctrl->is_new)
break; ret = cam_i2c_write(sd, AE_CTL1_REG,
case V4L2_CID_EXPOSURE: ctrl->val == V4L2_EXPOSURE_AUTO ? 0xDC : 0x0C);
ret = sr030pc30_set_exposure(sd, ctrl->value); if (info->exp->is_new) {
break; 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: default:
return -EINVAL; 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);
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;
default:
return -EINVAL;
}
return 0; return 0;
} }
@ -752,11 +621,19 @@ static int sr030pc30_s_power(struct v4l2_subdev *sd, int on)
return ret; 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 = { static const struct v4l2_subdev_core_ops sr030pc30_core_ops = {
.s_power = sr030pc30_s_power, .s_power = sr030pc30_s_power,
.queryctrl = sr030pc30_queryctrl, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
.s_ctrl = sr030pc30_s_ctrl, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
.g_ctrl = sr030pc30_g_ctrl, .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 = { 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 sr030pc30_info *info;
struct v4l2_subdev *sd; struct v4l2_subdev *sd;
struct v4l2_ctrl_handler *hdl;
const struct sr030pc30_platform_data *pdata const struct sr030pc30_platform_data *pdata
= client->dev.platform_data; = client->dev.platform_data;
int ret; int ret;
@ -820,7 +698,7 @@ static int sr030pc30_probe(struct i2c_client *client,
if (ret) if (ret)
return ret; return ret;
info = kzalloc(sizeof(*info), GFP_KERNEL); info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);
if (!info) if (!info)
return -ENOMEM; return -ENOMEM;
@ -830,10 +708,31 @@ static int sr030pc30_probe(struct i2c_client *client,
v4l2_i2c_subdev_init(sd, client, &sr030pc30_ops); 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->i2c_reg_page = -1;
info->hflip = 1; info->hflip = 1;
info->auto_exp = 1;
info->exposure = 30;
return 0; return 0;
} }
@ -841,10 +740,9 @@ static int sr030pc30_probe(struct i2c_client *client,
static int sr030pc30_remove(struct i2c_client *client) static int sr030pc30_remove(struct i2c_client *client)
{ {
struct v4l2_subdev *sd = i2c_get_clientdata(client); struct v4l2_subdev *sd = i2c_get_clientdata(client);
struct sr030pc30_info *info = to_sr030pc30(sd);
v4l2_device_unregister_subdev(sd); v4l2_device_unregister_subdev(sd);
kfree(info); v4l2_ctrl_handler_free(sd->ctrl_handler);
return 0; return 0;
} }

Some files were not shown because too many files have changed in this diff Show More