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:
commit
858655116b
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -1,271 +0,0 @@
|
|||||||
<refentry id="vidioc-dbg-g-chip-ident">
|
|
||||||
<refmeta>
|
|
||||||
<refentrytitle>ioctl VIDIOC_DBG_G_CHIP_IDENT</refentrytitle>
|
|
||||||
&manvol;
|
|
||||||
</refmeta>
|
|
||||||
|
|
||||||
<refnamediv>
|
|
||||||
<refname>VIDIOC_DBG_G_CHIP_IDENT</refname>
|
|
||||||
<refpurpose>Identify the chips on a TV card</refpurpose>
|
|
||||||
</refnamediv>
|
|
||||||
|
|
||||||
<refsynopsisdiv>
|
|
||||||
<funcsynopsis>
|
|
||||||
<funcprototype>
|
|
||||||
<funcdef>int <function>ioctl</function></funcdef>
|
|
||||||
<paramdef>int <parameter>fd</parameter></paramdef>
|
|
||||||
<paramdef>int <parameter>request</parameter></paramdef>
|
|
||||||
<paramdef>struct v4l2_dbg_chip_ident
|
|
||||||
*<parameter>argp</parameter></paramdef>
|
|
||||||
</funcprototype>
|
|
||||||
</funcsynopsis>
|
|
||||||
</refsynopsisdiv>
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>Arguments</title>
|
|
||||||
|
|
||||||
<variablelist>
|
|
||||||
<varlistentry>
|
|
||||||
<term><parameter>fd</parameter></term>
|
|
||||||
<listitem>
|
|
||||||
<para>&fd;</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term><parameter>request</parameter></term>
|
|
||||||
<listitem>
|
|
||||||
<para>VIDIOC_DBG_G_CHIP_IDENT</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term><parameter>argp</parameter></term>
|
|
||||||
<listitem>
|
|
||||||
<para></para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>Description</title>
|
|
||||||
|
|
||||||
<note>
|
|
||||||
<title>Experimental</title>
|
|
||||||
|
|
||||||
<para>This is an <link
|
|
||||||
linkend="experimental">experimental</link> interface and may change in
|
|
||||||
the future.</para>
|
|
||||||
</note>
|
|
||||||
|
|
||||||
<para>For driver debugging purposes this ioctl allows test
|
|
||||||
applications to query the driver about the chips present on the TV
|
|
||||||
card. Regular applications must not use it. When you found a chip
|
|
||||||
specific bug, please contact the linux-media mailing list (&v4l-ml;)
|
|
||||||
so it can be fixed.</para>
|
|
||||||
|
|
||||||
<para>To query the driver applications must initialize the
|
|
||||||
<structfield>match.type</structfield> and
|
|
||||||
<structfield>match.addr</structfield> or <structfield>match.name</structfield>
|
|
||||||
fields of a &v4l2-dbg-chip-ident;
|
|
||||||
and call <constant>VIDIOC_DBG_G_CHIP_IDENT</constant> with a pointer to
|
|
||||||
this structure. On success the driver stores information about the
|
|
||||||
selected chip in the <structfield>ident</structfield> and
|
|
||||||
<structfield>revision</structfield> fields. On failure the structure
|
|
||||||
remains unchanged.</para>
|
|
||||||
|
|
||||||
<para>When <structfield>match.type</structfield> is
|
|
||||||
<constant>V4L2_CHIP_MATCH_HOST</constant>,
|
|
||||||
<structfield>match.addr</structfield> selects the nth non-&i2c; chip
|
|
||||||
on the TV card. You can enumerate all chips by starting at zero and
|
|
||||||
incrementing <structfield>match.addr</structfield> by one until
|
|
||||||
<constant>VIDIOC_DBG_G_CHIP_IDENT</constant> fails with an &EINVAL;.
|
|
||||||
The number zero always selects the host chip, ⪚ the chip connected
|
|
||||||
to the PCI or USB bus.</para>
|
|
||||||
|
|
||||||
<para>When <structfield>match.type</structfield> is
|
|
||||||
<constant>V4L2_CHIP_MATCH_I2C_DRIVER</constant>,
|
|
||||||
<structfield>match.name</structfield> contains the I2C driver name.
|
|
||||||
For instance
|
|
||||||
<constant>"saa7127"</constant> will match any chip
|
|
||||||
supported by the saa7127 driver, regardless of its &i2c; bus address.
|
|
||||||
When multiple chips supported by the same driver are present, the
|
|
||||||
ioctl will return <constant>V4L2_IDENT_AMBIGUOUS</constant> in the
|
|
||||||
<structfield>ident</structfield> field.</para>
|
|
||||||
|
|
||||||
<para>When <structfield>match.type</structfield> is
|
|
||||||
<constant>V4L2_CHIP_MATCH_I2C_ADDR</constant>,
|
|
||||||
<structfield>match.addr</structfield> selects a chip by its 7 bit
|
|
||||||
&i2c; bus address.</para>
|
|
||||||
|
|
||||||
<para>When <structfield>match.type</structfield> is
|
|
||||||
<constant>V4L2_CHIP_MATCH_AC97</constant>,
|
|
||||||
<structfield>match.addr</structfield> selects the nth AC97 chip
|
|
||||||
on the TV card. You can enumerate all chips by starting at zero and
|
|
||||||
incrementing <structfield>match.addr</structfield> by one until
|
|
||||||
<constant>VIDIOC_DBG_G_CHIP_IDENT</constant> fails with an &EINVAL;.</para>
|
|
||||||
|
|
||||||
<para>On success, the <structfield>ident</structfield> field will
|
|
||||||
contain a chip ID from the Linux
|
|
||||||
<filename>media/v4l2-chip-ident.h</filename> header file, and the
|
|
||||||
<structfield>revision</structfield> field will contain a driver
|
|
||||||
specific value, or zero if no particular revision is associated with
|
|
||||||
this chip.</para>
|
|
||||||
|
|
||||||
<para>When the driver could not identify the selected chip,
|
|
||||||
<structfield>ident</structfield> will contain
|
|
||||||
<constant>V4L2_IDENT_UNKNOWN</constant>. When no chip matched
|
|
||||||
the ioctl will succeed but the
|
|
||||||
<structfield>ident</structfield> field will contain
|
|
||||||
<constant>V4L2_IDENT_NONE</constant>. If multiple chips matched,
|
|
||||||
<structfield>ident</structfield> will contain
|
|
||||||
<constant>V4L2_IDENT_AMBIGUOUS</constant>. In all these cases the
|
|
||||||
<structfield>revision</structfield> field remains unchanged.</para>
|
|
||||||
|
|
||||||
<para>This ioctl is optional, not all drivers may support it. It
|
|
||||||
was introduced in Linux 2.6.21, but the API was changed to the
|
|
||||||
one described here in 2.6.29.</para>
|
|
||||||
|
|
||||||
<para>We recommended the <application>v4l2-dbg</application>
|
|
||||||
utility over calling this ioctl directly. It is available from the
|
|
||||||
LinuxTV v4l-dvb repository; see <ulink
|
|
||||||
url="http://linuxtv.org/repo/">http://linuxtv.org/repo/</ulink> for
|
|
||||||
access instructions.</para>
|
|
||||||
|
|
||||||
<!-- Note for convenience vidioc-dbg-g-register.sgml
|
|
||||||
contains a duplicate of this table. -->
|
|
||||||
<table pgwide="1" frame="none" id="ident-v4l2-dbg-match">
|
|
||||||
<title>struct <structname>v4l2_dbg_match</structname></title>
|
|
||||||
<tgroup cols="4">
|
|
||||||
&cs-ustr;
|
|
||||||
<tbody valign="top">
|
|
||||||
<row>
|
|
||||||
<entry>__u32</entry>
|
|
||||||
<entry><structfield>type</structfield></entry>
|
|
||||||
<entry>See <xref linkend="ident-chip-match-types" /> for a list of
|
|
||||||
possible types.</entry>
|
|
||||||
</row>
|
|
||||||
<row>
|
|
||||||
<entry>union</entry>
|
|
||||||
<entry>(anonymous)</entry>
|
|
||||||
</row>
|
|
||||||
<row>
|
|
||||||
<entry></entry>
|
|
||||||
<entry>__u32</entry>
|
|
||||||
<entry><structfield>addr</structfield></entry>
|
|
||||||
<entry>Match a chip by this number, interpreted according
|
|
||||||
to the <structfield>type</structfield> field.</entry>
|
|
||||||
</row>
|
|
||||||
<row>
|
|
||||||
<entry></entry>
|
|
||||||
<entry>char</entry>
|
|
||||||
<entry><structfield>name[32]</structfield></entry>
|
|
||||||
<entry>Match a chip by this name, interpreted according
|
|
||||||
to the <structfield>type</structfield> field.</entry>
|
|
||||||
</row>
|
|
||||||
</tbody>
|
|
||||||
</tgroup>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<table pgwide="1" frame="none" id="v4l2-dbg-chip-ident">
|
|
||||||
<title>struct <structname>v4l2_dbg_chip_ident</structname></title>
|
|
||||||
<tgroup cols="3">
|
|
||||||
&cs-str;
|
|
||||||
<tbody valign="top">
|
|
||||||
<row>
|
|
||||||
<entry>struct v4l2_dbg_match</entry>
|
|
||||||
<entry><structfield>match</structfield></entry>
|
|
||||||
<entry>How to match the chip, see <xref linkend="ident-v4l2-dbg-match" />.</entry>
|
|
||||||
</row>
|
|
||||||
<row>
|
|
||||||
<entry>__u32</entry>
|
|
||||||
<entry><structfield>ident</structfield></entry>
|
|
||||||
<entry>A chip identifier as defined in the Linux
|
|
||||||
<filename>media/v4l2-chip-ident.h</filename> header file, or one of
|
|
||||||
the values from <xref linkend="chip-ids" />.</entry>
|
|
||||||
</row>
|
|
||||||
<row>
|
|
||||||
<entry>__u32</entry>
|
|
||||||
<entry><structfield>revision</structfield></entry>
|
|
||||||
<entry>A chip revision, chip and driver specific.</entry>
|
|
||||||
</row>
|
|
||||||
</tbody>
|
|
||||||
</tgroup>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<!-- Note for convenience vidioc-dbg-g-register.sgml
|
|
||||||
contains a duplicate of this table. -->
|
|
||||||
<table pgwide="1" frame="none" id="ident-chip-match-types">
|
|
||||||
<title>Chip Match Types</title>
|
|
||||||
<tgroup cols="3">
|
|
||||||
&cs-def;
|
|
||||||
<tbody valign="top">
|
|
||||||
<row>
|
|
||||||
<entry><constant>V4L2_CHIP_MATCH_BRIDGE</constant></entry>
|
|
||||||
<entry>0</entry>
|
|
||||||
<entry>Match the nth chip on the card, zero for the
|
|
||||||
bridge chip. Does not match sub-devices.</entry>
|
|
||||||
</row>
|
|
||||||
<row>
|
|
||||||
<entry><constant>V4L2_CHIP_MATCH_I2C_DRIVER</constant></entry>
|
|
||||||
<entry>1</entry>
|
|
||||||
<entry>Match an &i2c; chip by its driver name.</entry>
|
|
||||||
</row>
|
|
||||||
<row>
|
|
||||||
<entry><constant>V4L2_CHIP_MATCH_I2C_ADDR</constant></entry>
|
|
||||||
<entry>2</entry>
|
|
||||||
<entry>Match a chip by its 7 bit &i2c; bus address.</entry>
|
|
||||||
</row>
|
|
||||||
<row>
|
|
||||||
<entry><constant>V4L2_CHIP_MATCH_AC97</constant></entry>
|
|
||||||
<entry>3</entry>
|
|
||||||
<entry>Match the nth anciliary AC97 chip.</entry>
|
|
||||||
</row>
|
|
||||||
<row>
|
|
||||||
<entry><constant>V4L2_CHIP_MATCH_SUBDEV</constant></entry>
|
|
||||||
<entry>4</entry>
|
|
||||||
<entry>Match the nth sub-device. Can't be used with this ioctl.</entry>
|
|
||||||
</row>
|
|
||||||
</tbody>
|
|
||||||
</tgroup>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<!-- This is an anonymous enum in media/v4l2-chip-ident.h. -->
|
|
||||||
<table pgwide="1" frame="none" id="chip-ids">
|
|
||||||
<title>Chip Identifiers</title>
|
|
||||||
<tgroup cols="3">
|
|
||||||
&cs-def;
|
|
||||||
<tbody valign="top">
|
|
||||||
<row>
|
|
||||||
<entry><constant>V4L2_IDENT_NONE</constant></entry>
|
|
||||||
<entry>0</entry>
|
|
||||||
<entry>No chip matched.</entry>
|
|
||||||
</row>
|
|
||||||
<row>
|
|
||||||
<entry><constant>V4L2_IDENT_AMBIGUOUS</constant></entry>
|
|
||||||
<entry>1</entry>
|
|
||||||
<entry>Multiple chips matched.</entry>
|
|
||||||
</row>
|
|
||||||
<row>
|
|
||||||
<entry><constant>V4L2_IDENT_UNKNOWN</constant></entry>
|
|
||||||
<entry>2</entry>
|
|
||||||
<entry>A chip is present at this address, but the driver
|
|
||||||
could not identify it.</entry>
|
|
||||||
</row>
|
|
||||||
</tbody>
|
|
||||||
</tgroup>
|
|
||||||
</table>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
&return-value;
|
|
||||||
|
|
||||||
<variablelist>
|
|
||||||
<varlistentry>
|
|
||||||
<term><errorcode>EINVAL</errorcode></term>
|
|
||||||
<listitem>
|
|
||||||
<para>The <structfield>match_type</structfield> is invalid.</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</refsect1>
|
|
||||||
</refentry>
|
|
@ -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>
|
||||||
|
@ -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, ⪚ 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>
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
40
Documentation/devicetree/bindings/media/i2c/mt9p031.txt
Normal file
40
Documentation/devicetree/bindings/media/i2c/mt9p031.txt
Normal 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>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
...
|
||||||
|
};
|
44
Documentation/devicetree/bindings/media/i2c/tvp514x.txt
Normal file
44
Documentation/devicetree/bindings/media/i2c/tvp514x.txt
Normal 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>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
...
|
||||||
|
};
|
@ -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>;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
|
18
Documentation/devicetree/bindings/media/sh_mobile_ceu.txt
Normal file
18
Documentation/devicetree/bindings/media/sh_mobile_ceu.txt
Normal 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>;
|
||||||
|
};
|
@ -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.
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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]
|
||||||
|
@ -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
|
||||||
|
@ -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 \
|
||||||
|
@ -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.
|
||||||
|
@ -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。
|
||||||
|
50
MAINTAINERS
50
MAINTAINERS
@ -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
|
||||||
|
@ -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 = {
|
||||||
|
@ -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)
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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, ®->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, ®->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,
|
||||||
|
@ -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)
|
||||||
|
@ -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
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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) {
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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, ®->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, ®->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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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, ®->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, ®->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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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, ®->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, ®->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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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, ®->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, ®->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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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, ®->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, ®->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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------- */
|
/* ----------------------------------------------------------------------- */
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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, ®->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, ®->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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
431
drivers/media/i2c/ml86v7667.c
Normal file
431
drivers/media/i2c/ml86v7667.c
Normal 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");
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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, ®->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, ®->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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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, ®->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, ®->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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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, ®->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, ®->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);
|
||||||
|
@ -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, ®->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, ®->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);
|
||||||
|
@ -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, ®->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, ®->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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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
Loading…
Reference in New Issue
Block a user