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 is the first part of the media patches for v3.6. This patch series contain: - new DVB frontend: rtl2832 - new video drivers: adv7393 - some unused files got removed - a selection API cleanup between V4L2 and V4L2 subdev API's - a major redesign at v4l-ioctl2, in order to clean it up - several driver fixes and improvements." * 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (174 commits) v4l: Export v4l2-common.h in include/linux/Kbuild media: Revert "[media] Terratec Cinergy S2 USB HD Rev.2" [media] media: Use pr_info not homegrown pr_reg macro [media] Terratec Cinergy S2 USB HD Rev.2 [media] v4l: Correct conflicting V4L2 subdev selection API documentation [media] Feature removal: V4L2 selections API target and flag definitions [media] v4l: Unify selection flags documentation [media] v4l: Unify selection flags [media] v4l: Common documentation for selection targets [media] v4l: Unify selection targets across V4L2 and V4L2 subdev interfaces [media] v4l: Remove "_ACTUAL" from subdev selection API target definition names [media] V4L: Remove "_ACTIVE" from the selection target name definitions [media] media: dvb-usb: print mac address via native %pM [media] s5p-tv: Use module_i2c_driver in sii9234_drv.c file [media] media: gpio-ir-recv: add allowed_protos for platform data [media] s5p-jpeg: Use module_platform_driver in jpeg-core.c file [media] saa7134: fix spelling of detach in label [media] cx88-blackbird: replace ioctl by unlocked_ioctl [media] cx88: don't use current_norm [media] cx88: fix a number of v4l2-compliance violations ...
This commit is contained in:
commit
6df419e45d
|
@ -194,7 +194,7 @@ in the frequency range from 87,5 to 108,0 MHz</title>
|
||||||
<corpauthor>National Radio Systems Committee
|
<corpauthor>National Radio Systems Committee
|
||||||
(<ulink url="http://www.nrscstandards.org">http://www.nrscstandards.org</ulink>)</corpauthor>
|
(<ulink url="http://www.nrscstandards.org">http://www.nrscstandards.org</ulink>)</corpauthor>
|
||||||
</authorgroup>
|
</authorgroup>
|
||||||
<title>NTSC-4: United States RBDS Standard</title>
|
<title>NRSC-4: United States RBDS Standard</title>
|
||||||
</biblioentry>
|
</biblioentry>
|
||||||
|
|
||||||
<biblioentry id="iso12232">
|
<biblioentry id="iso12232">
|
||||||
|
|
|
@ -464,14 +464,14 @@ The <structfield>type</structfield> field of the respective
|
||||||
<structfield>tuner</structfield> field contains the index number of
|
<structfield>tuner</structfield> field contains the index number of
|
||||||
the tuner.</para>
|
the tuner.</para>
|
||||||
|
|
||||||
<para>Radio devices have exactly one tuner with index zero, no
|
<para>Radio input devices have exactly one tuner with index zero, no
|
||||||
video inputs.</para>
|
video inputs.</para>
|
||||||
|
|
||||||
<para>To query and change tuner properties applications use the
|
<para>To query and change tuner properties applications use the
|
||||||
&VIDIOC-G-TUNER; and &VIDIOC-S-TUNER; ioctl, respectively. The
|
&VIDIOC-G-TUNER; and &VIDIOC-S-TUNER; ioctl, respectively. The
|
||||||
&v4l2-tuner; returned by <constant>VIDIOC_G_TUNER</constant> also
|
&v4l2-tuner; returned by <constant>VIDIOC_G_TUNER</constant> also
|
||||||
contains signal status information applicable when the tuner of the
|
contains signal status information applicable when the tuner of the
|
||||||
current video input, or a radio tuner is queried. Note that
|
current video or radio input is queried. Note that
|
||||||
<constant>VIDIOC_S_TUNER</constant> does not switch the current tuner,
|
<constant>VIDIOC_S_TUNER</constant> does not switch the current tuner,
|
||||||
when there is more than one at all. The tuner is solely determined by
|
when there is more than one at all. The tuner is solely determined by
|
||||||
the current video input. Drivers must support both ioctls and set the
|
the current video input. Drivers must support both ioctls and set the
|
||||||
|
@ -491,8 +491,17 @@ the modulator. The <structfield>type</structfield> field of the
|
||||||
respective &v4l2-output; returned by the &VIDIOC-ENUMOUTPUT; ioctl is
|
respective &v4l2-output; returned by the &VIDIOC-ENUMOUTPUT; ioctl is
|
||||||
set to <constant>V4L2_OUTPUT_TYPE_MODULATOR</constant> and its
|
set to <constant>V4L2_OUTPUT_TYPE_MODULATOR</constant> and its
|
||||||
<structfield>modulator</structfield> field contains the index number
|
<structfield>modulator</structfield> field contains the index number
|
||||||
of the modulator. This specification does not define radio output
|
of the modulator.</para>
|
||||||
devices.</para>
|
|
||||||
|
<para>Radio output devices have exactly one modulator with index
|
||||||
|
zero, no video outputs.</para>
|
||||||
|
|
||||||
|
<para>A video or radio device cannot support both a tuner and a
|
||||||
|
modulator. Two separate device nodes will have to be used for such
|
||||||
|
hardware, one that supports the tuner functionality and one that supports
|
||||||
|
the modulator functionality. The reason is a limitation with the
|
||||||
|
&VIDIOC-S-FREQUENCY; ioctl where you cannot specify whether the frequency
|
||||||
|
is for a tuner or a modulator.</para>
|
||||||
|
|
||||||
<para>To query and change modulator properties applications use
|
<para>To query and change modulator properties applications use
|
||||||
the &VIDIOC-G-MODULATOR; and &VIDIOC-S-MODULATOR; ioctl. Note that
|
the &VIDIOC-G-MODULATOR; and &VIDIOC-S-MODULATOR; ioctl. Note that
|
||||||
|
|
|
@ -2377,10 +2377,11 @@ that used it. It was originally scheduled for removal in 2.6.35.
|
||||||
<para>V4L2_CTRL_FLAG_VOLATILE was added to signal volatile controls to userspace.</para>
|
<para>V4L2_CTRL_FLAG_VOLATILE was added to signal volatile controls to userspace.</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>Add selection API for extended control over cropping and
|
<para>Add selection API for extended control over cropping
|
||||||
composing. Does not affect the compatibility of current drivers and
|
and composing. Does not affect the compatibility of current
|
||||||
applications. See <link linkend="selection-api"> selection API </link> for
|
drivers and applications. See <link
|
||||||
details.</para>
|
linkend="selection-api"> selection API </link> for
|
||||||
|
details.</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</orderedlist>
|
</orderedlist>
|
||||||
</section>
|
</section>
|
||||||
|
@ -2458,6 +2459,18 @@ details.</para>
|
||||||
</orderedlist>
|
</orderedlist>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<title>V4L2 in Linux 3.5</title>
|
||||||
|
<orderedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>Replaced <structfield>input</structfield> in
|
||||||
|
<structname>v4l2_buffer</structname> by
|
||||||
|
<structfield>reserved2</structfield> and removed
|
||||||
|
<constant>V4L2_BUF_FLAG_INPUT</constant>.</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>
|
||||||
|
|
||||||
|
|
|
@ -276,7 +276,7 @@
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section id="v4l2-subdev-selections">
|
||||||
<title>Selections: cropping, scaling and composition</title>
|
<title>Selections: cropping, scaling and composition</title>
|
||||||
|
|
||||||
<para>Many sub-devices support cropping frames on their input or output
|
<para>Many sub-devices support cropping frames on their input or output
|
||||||
|
@ -290,8 +290,8 @@
|
||||||
size. Both the coordinates and sizes are expressed in pixels.</para>
|
size. Both the coordinates and sizes are expressed in pixels.</para>
|
||||||
|
|
||||||
<para>As for pad formats, drivers store try and active
|
<para>As for pad formats, drivers store try and active
|
||||||
rectangles for the selection targets of ACTUAL type <xref
|
rectangles for the selection targets <xref
|
||||||
linkend="v4l2-subdev-selection-targets">.</xref></para>
|
linkend="v4l2-selections-common" />.</para>
|
||||||
|
|
||||||
<para>On sink pads, cropping is applied relative to the
|
<para>On sink pads, cropping is applied relative to the
|
||||||
current pad format. The pad format represents the image size as
|
current pad format. The pad format represents the image size as
|
||||||
|
@ -308,7 +308,7 @@
|
||||||
<para>Scaling support is optional. When supported by a subdev,
|
<para>Scaling support is optional. When supported by a subdev,
|
||||||
the crop rectangle on the subdev's sink pad is scaled to the
|
the crop rectangle on the subdev's sink pad is scaled to the
|
||||||
size configured using the &VIDIOC-SUBDEV-S-SELECTION; IOCTL
|
size configured using the &VIDIOC-SUBDEV-S-SELECTION; IOCTL
|
||||||
using <constant>V4L2_SUBDEV_SEL_COMPOSE_ACTUAL</constant>
|
using <constant>V4L2_SEL_TGT_COMPOSE</constant>
|
||||||
selection target on the same pad. If the subdev supports scaling
|
selection target on the same pad. If the subdev supports scaling
|
||||||
but not composing, the top and left values are not used and must
|
but not composing, the top and left values are not used and must
|
||||||
always be set to zero.</para>
|
always be set to zero.</para>
|
||||||
|
@ -323,32 +323,32 @@
|
||||||
<para>The drivers should always use the closest possible
|
<para>The drivers should always use the closest possible
|
||||||
rectangle the user requests on all selection targets, unless
|
rectangle the user requests on all selection targets, unless
|
||||||
specifically told otherwise.
|
specifically told otherwise.
|
||||||
<constant>V4L2_SUBDEV_SEL_FLAG_SIZE_GE</constant> and
|
<constant>V4L2_SEL_FLAG_GE</constant> and
|
||||||
<constant>V4L2_SUBDEV_SEL_FLAG_SIZE_LE</constant> flags may be
|
<constant>V4L2_SEL_FLAG_LE</constant> flags may be
|
||||||
used to round the image size either up or down. <xref
|
used to round the image size either up or down. <xref
|
||||||
linkend="v4l2-subdev-selection-flags"></xref></para>
|
linkend="v4l2-selection-flags" /></para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<title>Types of selection targets</title>
|
<title>Types of selection targets</title>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<title>ACTUAL targets</title>
|
<title>Actual targets</title>
|
||||||
|
|
||||||
<para>ACTUAL targets reflect the actual hardware configuration
|
<para>Actual targets (without a postfix) reflect the actual
|
||||||
at any point of time. There is a BOUNDS target
|
hardware configuration at any point of time. There is a BOUNDS
|
||||||
corresponding to every ACTUAL.</para>
|
target corresponding to every actual target.</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<title>BOUNDS targets</title>
|
<title>BOUNDS targets</title>
|
||||||
|
|
||||||
<para>BOUNDS targets is the smallest rectangle that contains
|
<para>BOUNDS targets is the smallest rectangle that contains all
|
||||||
all valid ACTUAL rectangles. It may not be possible to set the
|
valid actual rectangles. It may not be possible to set the actual
|
||||||
ACTUAL rectangle as large as the BOUNDS rectangle, however.
|
rectangle as large as the BOUNDS rectangle, however. This may be
|
||||||
This may be because e.g. a sensor's pixel array is not
|
because e.g. a sensor's pixel array is not rectangular but
|
||||||
rectangular but cross-shaped or round. The maximum size may
|
cross-shaped or round. The maximum size may also be smaller than the
|
||||||
also be smaller than the BOUNDS rectangle.</para>
|
BOUNDS rectangle.</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
@ -362,7 +362,7 @@
|
||||||
performed by the user: the changes made will be propagated to
|
performed by the user: the changes made will be propagated to
|
||||||
any subsequent stages. If this behaviour is not desired, the
|
any subsequent stages. If this behaviour is not desired, the
|
||||||
user must set
|
user must set
|
||||||
<constant>V4L2_SUBDEV_SEL_FLAG_KEEP_CONFIG</constant> flag. This
|
<constant>V4L2_SEL_FLAG_KEEP_CONFIG</constant> flag. This
|
||||||
flag causes no propagation of the changes are allowed in any
|
flag causes no propagation of the changes are allowed in any
|
||||||
circumstances. This may also cause the accessed rectangle to be
|
circumstances. This may also cause the accessed rectangle to be
|
||||||
adjusted by the driver, depending on the properties of the
|
adjusted by the driver, depending on the properties of the
|
||||||
|
|
|
@ -683,14 +683,12 @@ memory, set by the application. See <xref linkend="userp" /> for details.
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry>__u32</entry>
|
<entry>__u32</entry>
|
||||||
<entry><structfield>input</structfield></entry>
|
<entry><structfield>reserved2</structfield></entry>
|
||||||
<entry></entry>
|
<entry></entry>
|
||||||
<entry>Some video capture drivers support rapid and
|
<entry>A place holder for future extensions and custom
|
||||||
synchronous video input changes, a function useful for example in
|
(driver defined) buffer types
|
||||||
video surveillance applications. For this purpose applications set the
|
<constant>V4L2_BUF_TYPE_PRIVATE</constant> and higher. Applications
|
||||||
<constant>V4L2_BUF_FLAG_INPUT</constant> flag, and this field to the
|
should set this to 0.</entry>
|
||||||
number of a video input as in &v4l2-input; field
|
|
||||||
<structfield>index</structfield>.</entry>
|
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry>__u32</entry>
|
<entry>__u32</entry>
|
||||||
|
@ -921,13 +919,6 @@ previous key frame.</entry>
|
||||||
<entry>The <structfield>timecode</structfield> field is valid.
|
<entry>The <structfield>timecode</structfield> field is valid.
|
||||||
Drivers set or clear this flag when the <constant>VIDIOC_DQBUF</constant>
|
Drivers set or clear this flag when the <constant>VIDIOC_DQBUF</constant>
|
||||||
ioctl is called.</entry>
|
ioctl is called.</entry>
|
||||||
</row>
|
|
||||||
<row>
|
|
||||||
<entry><constant>V4L2_BUF_FLAG_INPUT</constant></entry>
|
|
||||||
<entry>0x0200</entry>
|
|
||||||
<entry>The <structfield>input</structfield> field is valid.
|
|
||||||
Applications set or clear this flag before calling the
|
|
||||||
<constant>VIDIOC_QBUF</constant> ioctl.</entry>
|
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry><constant>V4L2_BUF_FLAG_PREPARED</constant></entry>
|
<entry><constant>V4L2_BUF_FLAG_PREPARED</constant></entry>
|
||||||
|
|
|
@ -53,11 +53,11 @@ cropping and composing rectangles have the same size.</para>
|
||||||
</mediaobject>
|
</mediaobject>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
For complete list of the available selection targets see table <xref
|
|
||||||
linkend="v4l2-sel-target"/>
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
See <xref linkend="v4l2-selection-targets" /> for more
|
||||||
|
information.
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
|
|
||||||
<title>Configuration</title>
|
<title>Configuration</title>
|
||||||
|
@ -74,7 +74,7 @@ cropping/composing rectangles may have to be aligned, and both the source and
|
||||||
the sink may have arbitrary upper and lower size limits. Therefore, as usual,
|
the sink may have arbitrary upper and lower size limits. Therefore, as usual,
|
||||||
drivers are expected to adjust the requested parameters and return the actual
|
drivers are expected to adjust the requested parameters and return the actual
|
||||||
values selected. An application can control the rounding behaviour using <link
|
values selected. An application can control the rounding behaviour using <link
|
||||||
linkend="v4l2-sel-flags"> constraint flags </link>.</para>
|
linkend="v4l2-selection-flags"> constraint flags </link>.</para>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ top/left corner at position <constant> (0,0) </constant>. The rectangle's
|
||||||
coordinates are expressed in pixels.</para>
|
coordinates are expressed in pixels.</para>
|
||||||
|
|
||||||
<para>The top left corner, width and height of the source rectangle, that is
|
<para>The top left corner, width and height of the source rectangle, that is
|
||||||
the area actually sampled, is given by the <constant> V4L2_SEL_TGT_CROP_ACTIVE
|
the area actually sampled, is given by the <constant> V4L2_SEL_TGT_CROP
|
||||||
</constant> target. It uses the same coordinate system as <constant>
|
</constant> target. It uses the same coordinate system as <constant>
|
||||||
V4L2_SEL_TGT_CROP_BOUNDS </constant>. The active cropping area must lie
|
V4L2_SEL_TGT_CROP_BOUNDS </constant>. The active cropping area must lie
|
||||||
completely inside the capture boundaries. The driver may further adjust the
|
completely inside the capture boundaries. The driver may further adjust the
|
||||||
|
@ -111,13 +111,13 @@ height are equal to the image size set by <constant> VIDIOC_S_FMT </constant>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>The part of a buffer into which the image is inserted by the hardware is
|
<para>The part of a buffer into which the image is inserted by the hardware is
|
||||||
controlled by the <constant> V4L2_SEL_TGT_COMPOSE_ACTIVE </constant> target.
|
controlled by the <constant> V4L2_SEL_TGT_COMPOSE </constant> target.
|
||||||
The rectangle's coordinates are also expressed in the same coordinate system as
|
The rectangle's coordinates are also expressed in the same coordinate system as
|
||||||
the bounds rectangle. The composing rectangle must lie completely inside bounds
|
the bounds rectangle. The composing rectangle must lie completely inside bounds
|
||||||
rectangle. The driver must adjust the composing rectangle to fit to the
|
rectangle. The driver must adjust the composing rectangle to fit to the
|
||||||
bounding limits. Moreover, the driver can perform other adjustments according
|
bounding limits. Moreover, the driver can perform other adjustments according
|
||||||
to hardware limitations. The application can control rounding behaviour using
|
to hardware limitations. The application can control rounding behaviour using
|
||||||
<link linkend="v4l2-sel-flags"> constraint flags </link>.</para>
|
<link linkend="v4l2-selection-flags"> constraint flags </link>.</para>
|
||||||
|
|
||||||
<para>For capture devices the default composing rectangle is queried using
|
<para>For capture devices the default composing rectangle is queried using
|
||||||
<constant> V4L2_SEL_TGT_COMPOSE_DEFAULT </constant>. It is usually equal to the
|
<constant> V4L2_SEL_TGT_COMPOSE_DEFAULT </constant>. It is usually equal to the
|
||||||
|
@ -125,7 +125,7 @@ bounding rectangle.</para>
|
||||||
|
|
||||||
<para>The part of a buffer that is modified by the hardware is given by
|
<para>The part of a buffer that is modified by the hardware is given by
|
||||||
<constant> V4L2_SEL_TGT_COMPOSE_PADDED </constant>. It contains all pixels
|
<constant> V4L2_SEL_TGT_COMPOSE_PADDED </constant>. It contains all pixels
|
||||||
defined using <constant> V4L2_SEL_TGT_COMPOSE_ACTIVE </constant> plus all
|
defined using <constant> V4L2_SEL_TGT_COMPOSE </constant> plus all
|
||||||
padding data modified by hardware during insertion process. All pixels outside
|
padding data modified by hardware during insertion process. All pixels outside
|
||||||
this rectangle <emphasis>must not</emphasis> be changed by the hardware. The
|
this rectangle <emphasis>must not</emphasis> be changed by the hardware. The
|
||||||
content of pixels that lie inside the padded area but outside active area is
|
content of pixels that lie inside the padded area but outside active area is
|
||||||
|
@ -153,7 +153,7 @@ specified using <constant> VIDIOC_S_FMT </constant> ioctl.</para>
|
||||||
|
|
||||||
<para>The top left corner, width and height of the source rectangle, that is
|
<para>The top left corner, width and height of the source rectangle, that is
|
||||||
the area from which image date are processed by the hardware, is given by the
|
the area from which image date are processed by the hardware, is given by the
|
||||||
<constant> V4L2_SEL_TGT_CROP_ACTIVE </constant>. Its coordinates are expressed
|
<constant> V4L2_SEL_TGT_CROP </constant>. Its coordinates are expressed
|
||||||
in in the same coordinate system as the bounds rectangle. The active cropping
|
in in the same coordinate system as the bounds rectangle. The active cropping
|
||||||
area must lie completely inside the crop boundaries and the driver may further
|
area must lie completely inside the crop boundaries and the driver may further
|
||||||
adjust the requested size and/or position according to hardware
|
adjust the requested size and/or position according to hardware
|
||||||
|
@ -165,7 +165,7 @@ bounding rectangle.</para>
|
||||||
|
|
||||||
<para>The part of a video signal or graphics display where the image is
|
<para>The part of a video signal or graphics display where the image is
|
||||||
inserted by the hardware is controlled by <constant>
|
inserted by the hardware is controlled by <constant>
|
||||||
V4L2_SEL_TGT_COMPOSE_ACTIVE </constant> target. The rectangle's coordinates
|
V4L2_SEL_TGT_COMPOSE </constant> target. The rectangle's coordinates
|
||||||
are expressed in pixels. The composing rectangle must lie completely inside the
|
are expressed in pixels. The composing rectangle must lie completely inside the
|
||||||
bounds rectangle. The driver must adjust the area to fit to the bounding
|
bounds rectangle. The driver must adjust the area to fit to the bounding
|
||||||
limits. Moreover, the driver can perform other adjustments according to
|
limits. Moreover, the driver can perform other adjustments according to
|
||||||
|
@ -184,7 +184,7 @@ such a padded area is driver-dependent feature not covered by this document.
|
||||||
Driver developers are encouraged to keep padded rectangle equal to active one.
|
Driver developers are encouraged to keep padded rectangle equal to active one.
|
||||||
The padded target is accessed by the <constant> V4L2_SEL_TGT_COMPOSE_PADDED
|
The padded target is accessed by the <constant> V4L2_SEL_TGT_COMPOSE_PADDED
|
||||||
</constant> identifier. It must contain all pixels from the <constant>
|
</constant> identifier. It must contain all pixels from the <constant>
|
||||||
V4L2_SEL_TGT_COMPOSE_ACTIVE </constant> target.</para>
|
V4L2_SEL_TGT_COMPOSE </constant> target.</para>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
@ -193,8 +193,8 @@ V4L2_SEL_TGT_COMPOSE_ACTIVE </constant> target.</para>
|
||||||
<title>Scaling control</title>
|
<title>Scaling control</title>
|
||||||
|
|
||||||
<para>An application can detect if scaling is performed by comparing the width
|
<para>An application can detect if scaling is performed by comparing the width
|
||||||
and the height of rectangles obtained using <constant> V4L2_SEL_TGT_CROP_ACTIVE
|
and the height of rectangles obtained using <constant> V4L2_SEL_TGT_CROP
|
||||||
</constant> and <constant> V4L2_SEL_TGT_COMPOSE_ACTIVE </constant> targets. If
|
</constant> and <constant> V4L2_SEL_TGT_COMPOSE </constant> targets. If
|
||||||
these are not equal then the scaling is applied. The application can compute
|
these are not equal then the scaling is applied. The application can compute
|
||||||
the scaling ratios using these values.</para>
|
the scaling ratios using these values.</para>
|
||||||
|
|
||||||
|
@ -252,7 +252,7 @@ area)</para>
|
||||||
ret = ioctl(fd, &VIDIOC-G-SELECTION;, &sel);
|
ret = ioctl(fd, &VIDIOC-G-SELECTION;, &sel);
|
||||||
if (ret)
|
if (ret)
|
||||||
exit(-1);
|
exit(-1);
|
||||||
sel.target = V4L2_SEL_TGT_CROP_ACTIVE;
|
sel.target = V4L2_SEL_TGT_CROP;
|
||||||
ret = ioctl(fd, &VIDIOC-S-SELECTION;, &sel);
|
ret = ioctl(fd, &VIDIOC-S-SELECTION;, &sel);
|
||||||
if (ret)
|
if (ret)
|
||||||
exit(-1);
|
exit(-1);
|
||||||
|
@ -281,7 +281,7 @@ area)</para>
|
||||||
r.left = sel.r.width / 4;
|
r.left = sel.r.width / 4;
|
||||||
r.top = sel.r.height / 4;
|
r.top = sel.r.height / 4;
|
||||||
sel.r = r;
|
sel.r = r;
|
||||||
sel.target = V4L2_SEL_TGT_COMPOSE_ACTIVE;
|
sel.target = V4L2_SEL_TGT_COMPOSE;
|
||||||
sel.flags = V4L2_SEL_FLAG_LE;
|
sel.flags = V4L2_SEL_FLAG_LE;
|
||||||
ret = ioctl(fd, &VIDIOC-S-SELECTION;, &sel);
|
ret = ioctl(fd, &VIDIOC-S-SELECTION;, &sel);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -298,11 +298,11 @@ V4L2_BUF_TYPE_VIDEO_OUTPUT </constant> for other devices</para>
|
||||||
|
|
||||||
&v4l2-selection; compose = {
|
&v4l2-selection; compose = {
|
||||||
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT,
|
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT,
|
||||||
.target = V4L2_SEL_TGT_COMPOSE_ACTIVE,
|
.target = V4L2_SEL_TGT_COMPOSE,
|
||||||
};
|
};
|
||||||
&v4l2-selection; crop = {
|
&v4l2-selection; crop = {
|
||||||
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT,
|
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT,
|
||||||
.target = V4L2_SEL_TGT_CROP_ACTIVE,
|
.target = V4L2_SEL_TGT_CROP,
|
||||||
};
|
};
|
||||||
double hscale, vscale;
|
double hscale, vscale;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,164 @@
|
||||||
|
<section id="v4l2-selections-common">
|
||||||
|
|
||||||
|
<title>Common selection definitions</title>
|
||||||
|
|
||||||
|
<para>While the <link linkend="selection-api">V4L2 selection
|
||||||
|
API</link> and <link linkend="v4l2-subdev-selections">V4L2 subdev
|
||||||
|
selection APIs</link> are very similar, there's one fundamental
|
||||||
|
difference between the two. On sub-device API, the selection
|
||||||
|
rectangle refers to the media bus format, and is bound to a
|
||||||
|
sub-device's pad. On the V4L2 interface the selection rectangles
|
||||||
|
refer to the in-memory pixel format.</para>
|
||||||
|
|
||||||
|
<para>This section defines the common definitions of the
|
||||||
|
selection interfaces on the two APIs.</para>
|
||||||
|
|
||||||
|
<section id="v4l2-selection-targets">
|
||||||
|
|
||||||
|
<title>Selection targets</title>
|
||||||
|
|
||||||
|
<para>The precise meaning of the selection targets may be
|
||||||
|
dependent on which of the two interfaces they are used.</para>
|
||||||
|
|
||||||
|
<table pgwide="1" frame="none" id="v4l2-selection-targets-table">
|
||||||
|
<title>Selection target definitions</title>
|
||||||
|
<tgroup cols="5">
|
||||||
|
<colspec colname="c1" />
|
||||||
|
<colspec colname="c2" />
|
||||||
|
<colspec colname="c3" />
|
||||||
|
<colspec colname="c4" />
|
||||||
|
<colspec colname="c5" />
|
||||||
|
&cs-def;
|
||||||
|
<thead>
|
||||||
|
<row rowsep="1">
|
||||||
|
<entry align="left">Target name</entry>
|
||||||
|
<entry align="left">id</entry>
|
||||||
|
<entry align="left">Definition</entry>
|
||||||
|
<entry align="left">Valid for V4L2</entry>
|
||||||
|
<entry align="left">Valid for V4L2 subdev</entry>
|
||||||
|
</row>
|
||||||
|
</thead>
|
||||||
|
<tbody valign="top">
|
||||||
|
<row>
|
||||||
|
<entry><constant>V4L2_SEL_TGT_CROP</constant></entry>
|
||||||
|
<entry>0x0000</entry>
|
||||||
|
<entry>Crop rectangle. Defines the cropped area.</entry>
|
||||||
|
<entry>Yes</entry>
|
||||||
|
<entry>Yes</entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry><constant>V4L2_SEL_TGT_CROP_DEFAULT</constant></entry>
|
||||||
|
<entry>0x0001</entry>
|
||||||
|
<entry>Suggested cropping rectangle that covers the "whole picture".</entry>
|
||||||
|
<entry>Yes</entry>
|
||||||
|
<entry>No</entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry><constant>V4L2_SEL_TGT_CROP_BOUNDS</constant></entry>
|
||||||
|
<entry>0x0002</entry>
|
||||||
|
<entry>Bounds of the crop rectangle. All valid crop
|
||||||
|
rectangles fit inside the crop bounds rectangle.
|
||||||
|
</entry>
|
||||||
|
<entry>Yes</entry>
|
||||||
|
<entry>Yes</entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry><constant>V4L2_SEL_TGT_COMPOSE</constant></entry>
|
||||||
|
<entry>0x0100</entry>
|
||||||
|
<entry>Compose rectangle. Used to configure scaling
|
||||||
|
and composition.</entry>
|
||||||
|
<entry>Yes</entry>
|
||||||
|
<entry>Yes</entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry><constant>V4L2_SEL_TGT_COMPOSE_DEFAULT</constant></entry>
|
||||||
|
<entry>0x0101</entry>
|
||||||
|
<entry>Suggested composition rectangle that covers the "whole picture".</entry>
|
||||||
|
<entry>Yes</entry>
|
||||||
|
<entry>No</entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry><constant>V4L2_SEL_TGT_COMPOSE_BOUNDS</constant></entry>
|
||||||
|
<entry>0x0102</entry>
|
||||||
|
<entry>Bounds of the compose rectangle. All valid compose
|
||||||
|
rectangles fit inside the compose bounds rectangle.</entry>
|
||||||
|
<entry>Yes</entry>
|
||||||
|
<entry>Yes</entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry><constant>V4L2_SEL_TGT_COMPOSE_PADDED</constant></entry>
|
||||||
|
<entry>0x0103</entry>
|
||||||
|
<entry>The active area and all padding pixels that are inserted or
|
||||||
|
modified by hardware.</entry>
|
||||||
|
<entry>Yes</entry>
|
||||||
|
<entry>No</entry>
|
||||||
|
</row>
|
||||||
|
</tbody>
|
||||||
|
</tgroup>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="v4l2-selection-flags">
|
||||||
|
|
||||||
|
<title>Selection flags</title>
|
||||||
|
|
||||||
|
<table pgwide="1" frame="none" id="v4l2-selection-flags-table">
|
||||||
|
<title>Selection flag definitions</title>
|
||||||
|
<tgroup cols="5">
|
||||||
|
<colspec colname="c1" />
|
||||||
|
<colspec colname="c2" />
|
||||||
|
<colspec colname="c3" />
|
||||||
|
<colspec colname="c4" />
|
||||||
|
<colspec colname="c5" />
|
||||||
|
&cs-def;
|
||||||
|
<thead>
|
||||||
|
<row rowsep="1">
|
||||||
|
<entry align="left">Flag name</entry>
|
||||||
|
<entry align="left">id</entry>
|
||||||
|
<entry align="left">Definition</entry>
|
||||||
|
<entry align="left">Valid for V4L2</entry>
|
||||||
|
<entry align="left">Valid for V4L2 subdev</entry>
|
||||||
|
</row>
|
||||||
|
</thead>
|
||||||
|
<tbody valign="top">
|
||||||
|
<row>
|
||||||
|
<entry><constant>V4L2_SEL_FLAG_GE</constant></entry>
|
||||||
|
<entry>(1 << 0)</entry>
|
||||||
|
<entry>Suggest the driver it should choose greater or
|
||||||
|
equal rectangle (in size) than was requested. Albeit the
|
||||||
|
driver may choose a lesser size, it will only do so due to
|
||||||
|
hardware limitations. Without this flag (and
|
||||||
|
<constant>V4L2_SEL_FLAG_LE</constant>) the
|
||||||
|
behaviour is to choose the closest possible
|
||||||
|
rectangle.</entry>
|
||||||
|
<entry>Yes</entry>
|
||||||
|
<entry>Yes</entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry><constant>V4L2_SEL_FLAG_LE</constant></entry>
|
||||||
|
<entry>(1 << 1)</entry>
|
||||||
|
<entry>Suggest the driver it
|
||||||
|
should choose lesser or equal rectangle (in size) than was
|
||||||
|
requested. Albeit the driver may choose a greater size, it
|
||||||
|
will only do so due to hardware limitations.</entry>
|
||||||
|
<entry>Yes</entry>
|
||||||
|
<entry>Yes</entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry><constant>V4L2_SEL_FLAG_KEEP_CONFIG</constant></entry>
|
||||||
|
<entry>(1 << 2)</entry>
|
||||||
|
<entry>The configuration must not be propagated to any
|
||||||
|
further processing steps. If this flag is not given, the
|
||||||
|
configuration is propagated inside the subdevice to all
|
||||||
|
further processing steps.</entry>
|
||||||
|
<entry>No</entry>
|
||||||
|
<entry>Yes</entry>
|
||||||
|
</row>
|
||||||
|
</tbody>
|
||||||
|
</tgroup>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</section>
|
|
@ -589,6 +589,11 @@ and discussions on the V4L mailing list.</revremark>
|
||||||
&sub-write;
|
&sub-write;
|
||||||
</appendix>
|
</appendix>
|
||||||
|
|
||||||
|
<appendix>
|
||||||
|
<title>Common definitions for V4L2 and V4L2 subdev interfaces</title>
|
||||||
|
&sub-selections-common;
|
||||||
|
</appendix>
|
||||||
|
|
||||||
<appendix id="videodev">
|
<appendix id="videodev">
|
||||||
<title>Video For Linux Two Header File</title>
|
<title>Video For Linux Two Header File</title>
|
||||||
&sub-videodev2-h;
|
&sub-videodev2-h;
|
||||||
|
|
|
@ -97,7 +97,13 @@ information.</para>
|
||||||
<row>
|
<row>
|
||||||
<entry>__u32</entry>
|
<entry>__u32</entry>
|
||||||
<entry><structfield>count</structfield></entry>
|
<entry><structfield>count</structfield></entry>
|
||||||
<entry>The number of buffers requested or granted.</entry>
|
<entry>The number of buffers requested or granted. If count == 0, then
|
||||||
|
<constant>VIDIOC_CREATE_BUFS</constant> will set <structfield>index</structfield>
|
||||||
|
to the current number of created buffers, and it will check the validity of
|
||||||
|
<structfield>memory</structfield> and <structfield>format.type</structfield>.
|
||||||
|
If those are invalid -1 is returned and errno is set to &EINVAL;,
|
||||||
|
otherwise <constant>VIDIOC_CREATE_BUFS</constant> returns 0. It will
|
||||||
|
never set errno to &EBUSY; in this particular case.</entry>
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry>__u32</entry>
|
<entry>__u32</entry>
|
||||||
|
|
|
@ -135,6 +135,12 @@ bounds or the value in the <structfield>type</structfield> field is
|
||||||
wrong.</para>
|
wrong.</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><errorcode>EBUSY</errorcode></term>
|
||||||
|
<listitem>
|
||||||
|
<para>A hardware seek is in progress.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
</refentry>
|
</refentry>
|
||||||
|
|
|
@ -65,9 +65,9 @@ Do not use multiplanar buffers. Use <constant> V4L2_BUF_TYPE_VIDEO_CAPTURE
|
||||||
</constant>. Use <constant> V4L2_BUF_TYPE_VIDEO_OUTPUT </constant> instead of
|
</constant>. Use <constant> V4L2_BUF_TYPE_VIDEO_OUTPUT </constant> instead of
|
||||||
<constant> V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE </constant>. The next step is
|
<constant> V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE </constant>. The next step is
|
||||||
setting the value of &v4l2-selection; <structfield>target</structfield> field
|
setting the value of &v4l2-selection; <structfield>target</structfield> field
|
||||||
to <constant> V4L2_SEL_TGT_CROP_ACTIVE </constant> (<constant>
|
to <constant> V4L2_SEL_TGT_CROP </constant> (<constant>
|
||||||
V4L2_SEL_TGT_COMPOSE_ACTIVE </constant>). Please refer to table <xref
|
V4L2_SEL_TGT_COMPOSE </constant>). Please refer to table <xref
|
||||||
linkend="v4l2-sel-target" /> or <xref linkend="selection-api" /> for additional
|
linkend="v4l2-selections-common" /> or <xref linkend="selection-api" /> for additional
|
||||||
targets. The <structfield>flags</structfield> and <structfield>reserved
|
targets. The <structfield>flags</structfield> and <structfield>reserved
|
||||||
</structfield> fields of &v4l2-selection; are ignored and they must be filled
|
</structfield> fields of &v4l2-selection; are ignored and they must be filled
|
||||||
with zeros. The driver fills the rest of the structure or
|
with zeros. The driver fills the rest of the structure or
|
||||||
|
@ -86,9 +86,9 @@ use multiplanar buffers. Use <constant> V4L2_BUF_TYPE_VIDEO_CAPTURE
|
||||||
</constant>. Use <constant> V4L2_BUF_TYPE_VIDEO_OUTPUT </constant> instead of
|
</constant>. Use <constant> V4L2_BUF_TYPE_VIDEO_OUTPUT </constant> instead of
|
||||||
<constant> V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE </constant>. The next step is
|
<constant> V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE </constant>. The next step is
|
||||||
setting the value of &v4l2-selection; <structfield>target</structfield> to
|
setting the value of &v4l2-selection; <structfield>target</structfield> to
|
||||||
<constant>V4L2_SEL_TGT_CROP_ACTIVE</constant> (<constant>
|
<constant>V4L2_SEL_TGT_CROP</constant> (<constant>
|
||||||
V4L2_SEL_TGT_COMPOSE_ACTIVE </constant>). Please refer to table <xref
|
V4L2_SEL_TGT_COMPOSE </constant>). Please refer to table <xref
|
||||||
linkend="v4l2-sel-target" /> or <xref linkend="selection-api" /> for additional
|
linkend="v4l2-selections-common" /> or <xref linkend="selection-api" /> for additional
|
||||||
targets. The &v4l2-rect; <structfield>r</structfield> rectangle need to be
|
targets. The &v4l2-rect; <structfield>r</structfield> rectangle need to be
|
||||||
set to the desired active area. Field &v4l2-selection; <structfield> reserved
|
set to the desired active area. Field &v4l2-selection; <structfield> reserved
|
||||||
</structfield> is ignored and must be filled with zeros. The driver may adjust
|
</structfield> is ignored and must be filled with zeros. The driver may adjust
|
||||||
|
@ -154,74 +154,8 @@ exist no rectangle </emphasis> that satisfies the constraints.</para>
|
||||||
|
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<para>Selection targets and flags are documented in <xref
|
||||||
<table frame="none" pgwide="1" id="v4l2-sel-target">
|
linkend="v4l2-selections-common"/>.</para>
|
||||||
<title>Selection targets.</title>
|
|
||||||
<tgroup cols="3">
|
|
||||||
&cs-def;
|
|
||||||
<tbody valign="top">
|
|
||||||
<row>
|
|
||||||
<entry><constant>V4L2_SEL_TGT_CROP_ACTIVE</constant></entry>
|
|
||||||
<entry>0x0000</entry>
|
|
||||||
<entry>The area that is currently cropped by hardware.</entry>
|
|
||||||
</row>
|
|
||||||
<row>
|
|
||||||
<entry><constant>V4L2_SEL_TGT_CROP_DEFAULT</constant></entry>
|
|
||||||
<entry>0x0001</entry>
|
|
||||||
<entry>Suggested cropping rectangle that covers the "whole picture".</entry>
|
|
||||||
</row>
|
|
||||||
<row>
|
|
||||||
<entry><constant>V4L2_SEL_TGT_CROP_BOUNDS</constant></entry>
|
|
||||||
<entry>0x0002</entry>
|
|
||||||
<entry>Limits for the cropping rectangle.</entry>
|
|
||||||
</row>
|
|
||||||
<row>
|
|
||||||
<entry><constant>V4L2_SEL_TGT_COMPOSE_ACTIVE</constant></entry>
|
|
||||||
<entry>0x0100</entry>
|
|
||||||
<entry>The area to which data is composed by hardware.</entry>
|
|
||||||
</row>
|
|
||||||
<row>
|
|
||||||
<entry><constant>V4L2_SEL_TGT_COMPOSE_DEFAULT</constant></entry>
|
|
||||||
<entry>0x0101</entry>
|
|
||||||
<entry>Suggested composing rectangle that covers the "whole picture".</entry>
|
|
||||||
</row>
|
|
||||||
<row>
|
|
||||||
<entry><constant>V4L2_SEL_TGT_COMPOSE_BOUNDS</constant></entry>
|
|
||||||
<entry>0x0102</entry>
|
|
||||||
<entry>Limits for the composing rectangle.</entry>
|
|
||||||
</row>
|
|
||||||
<row>
|
|
||||||
<entry><constant>V4L2_SEL_TGT_COMPOSE_PADDED</constant></entry>
|
|
||||||
<entry>0x0103</entry>
|
|
||||||
<entry>The active area and all padding pixels that are inserted or modified by hardware.</entry>
|
|
||||||
</row>
|
|
||||||
</tbody>
|
|
||||||
</tgroup>
|
|
||||||
</table>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<table frame="none" pgwide="1" id="v4l2-sel-flags">
|
|
||||||
<title>Selection constraint flags</title>
|
|
||||||
<tgroup cols="3">
|
|
||||||
&cs-def;
|
|
||||||
<tbody valign="top">
|
|
||||||
<row>
|
|
||||||
<entry><constant>V4L2_SEL_FLAG_GE</constant></entry>
|
|
||||||
<entry>0x00000001</entry>
|
|
||||||
<entry>Indicates that the adjusted rectangle must contain the original
|
|
||||||
&v4l2-selection; <structfield>r</structfield> rectangle.</entry>
|
|
||||||
</row>
|
|
||||||
<row>
|
|
||||||
<entry><constant>V4L2_SEL_FLAG_LE</constant></entry>
|
|
||||||
<entry>0x00000002</entry>
|
|
||||||
<entry>Indicates that the adjusted rectangle must be inside the original
|
|
||||||
&v4l2-rect; <structfield>r</structfield> rectangle.</entry>
|
|
||||||
</row>
|
|
||||||
</tbody>
|
|
||||||
</tgroup>
|
|
||||||
</table>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<figure id="sel-const-adjust">
|
<figure id="sel-const-adjust">
|
||||||
|
@ -252,14 +186,14 @@ exist no rectangle </emphasis> that satisfies the constraints.</para>
|
||||||
<row>
|
<row>
|
||||||
<entry>__u32</entry>
|
<entry>__u32</entry>
|
||||||
<entry><structfield>target</structfield></entry>
|
<entry><structfield>target</structfield></entry>
|
||||||
<entry>Used to select between <link linkend="v4l2-sel-target"> cropping
|
<entry>Used to select between <link linkend="v4l2-selections-common"> cropping
|
||||||
and composing rectangles</link>.</entry>
|
and composing rectangles</link>.</entry>
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry>__u32</entry>
|
<entry>__u32</entry>
|
||||||
<entry><structfield>flags</structfield></entry>
|
<entry><structfield>flags</structfield></entry>
|
||||||
<entry>Flags controlling the selection rectangle adjustments, refer to
|
<entry>Flags controlling the selection rectangle adjustments, refer to
|
||||||
<link linkend="v4l2-sel-flags">selection flags</link>.</entry>
|
<link linkend="v4l2-selection-flags">selection flags</link>.</entry>
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry>&v4l2-rect;</entry>
|
<entry>&v4l2-rect;</entry>
|
||||||
|
|
|
@ -275,6 +275,18 @@ can or must be switched. (B/G PAL tuners for example are typically not
|
||||||
see the description of ioctl &VIDIOC-ENUMINPUT; for details. Only
|
see the description of ioctl &VIDIOC-ENUMINPUT; for details. Only
|
||||||
<constant>V4L2_TUNER_ANALOG_TV</constant> tuners can have this capability.</entry>
|
<constant>V4L2_TUNER_ANALOG_TV</constant> tuners can have this capability.</entry>
|
||||||
</row>
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry><constant>V4L2_TUNER_CAP_HWSEEK_BOUNDED</constant></entry>
|
||||||
|
<entry>0x0004</entry>
|
||||||
|
<entry>If set, then this tuner supports the hardware seek functionality
|
||||||
|
where the seek stops when it reaches the end of the frequency range.</entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry><constant>V4L2_TUNER_CAP_HWSEEK_WRAP</constant></entry>
|
||||||
|
<entry>0x0008</entry>
|
||||||
|
<entry>If set, then this tuner supports the hardware seek functionality
|
||||||
|
where the seek wraps around when it reaches the end of the frequency range.</entry>
|
||||||
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry><constant>V4L2_TUNER_CAP_STEREO</constant></entry>
|
<entry><constant>V4L2_TUNER_CAP_STEREO</constant></entry>
|
||||||
<entry>0x0010</entry>
|
<entry>0x0010</entry>
|
||||||
|
|
|
@ -71,12 +71,9 @@ initialize the <structfield>bytesused</structfield>,
|
||||||
<structfield>field</structfield> and
|
<structfield>field</structfield> and
|
||||||
<structfield>timestamp</structfield> fields, see <xref
|
<structfield>timestamp</structfield> fields, see <xref
|
||||||
linkend="buffer" /> for details.
|
linkend="buffer" /> for details.
|
||||||
Applications must also set <structfield>flags</structfield> to 0. If a driver
|
Applications must also set <structfield>flags</structfield> to 0.
|
||||||
supports capturing from specific video inputs and you want to specify a video
|
The <structfield>reserved2</structfield> and
|
||||||
input, then <structfield>flags</structfield> should be set to
|
<structfield>reserved</structfield> fields must be set to 0. When using
|
||||||
<constant>V4L2_BUF_FLAG_INPUT</constant> and the field
|
|
||||||
<structfield>input</structfield> must be initialized to the desired input.
|
|
||||||
The <structfield>reserved</structfield> field must be set to 0. When using
|
|
||||||
the <link linkend="planar-apis">multi-planar API</link>, the
|
the <link linkend="planar-apis">multi-planar API</link>, the
|
||||||
<structfield>m.planes</structfield> field must contain a userspace pointer
|
<structfield>m.planes</structfield> field must contain a userspace pointer
|
||||||
to a filled-in array of &v4l2-plane; and the <structfield>length</structfield>
|
to a filled-in array of &v4l2-plane; and the <structfield>length</structfield>
|
||||||
|
|
|
@ -58,6 +58,9 @@ To do this applications initialize the <structfield>tuner</structfield>,
|
||||||
call the <constant>VIDIOC_S_HW_FREQ_SEEK</constant> ioctl with a pointer
|
call the <constant>VIDIOC_S_HW_FREQ_SEEK</constant> ioctl with a pointer
|
||||||
to this structure.</para>
|
to this structure.</para>
|
||||||
|
|
||||||
|
<para>If an error is returned, then the original frequency will
|
||||||
|
be restored.</para>
|
||||||
|
|
||||||
<para>This ioctl is supported if the <constant>V4L2_CAP_HW_FREQ_SEEK</constant> capability is set.</para>
|
<para>This ioctl is supported if the <constant>V4L2_CAP_HW_FREQ_SEEK</constant> capability is set.</para>
|
||||||
|
|
||||||
<table pgwide="1" frame="none" id="v4l2-hw-freq-seek">
|
<table pgwide="1" frame="none" id="v4l2-hw-freq-seek">
|
||||||
|
@ -87,7 +90,10 @@ field and the &v4l2-tuner; <structfield>index</structfield> field.</entry>
|
||||||
<row>
|
<row>
|
||||||
<entry>__u32</entry>
|
<entry>__u32</entry>
|
||||||
<entry><structfield>wrap_around</structfield></entry>
|
<entry><structfield>wrap_around</structfield></entry>
|
||||||
<entry>If non-zero, wrap around when at the end of the frequency range, else stop seeking.</entry>
|
<entry>If non-zero, wrap around when at the end of the frequency range, else stop seeking.
|
||||||
|
The &v4l2-tuner; <structfield>capability</structfield> field will tell you what the
|
||||||
|
hardware supports.
|
||||||
|
</entry>
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry>__u32</entry>
|
<entry>__u32</entry>
|
||||||
|
@ -118,9 +124,15 @@ wrong.</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><errorcode>EAGAIN</errorcode></term>
|
<term><errorcode>ENODATA</errorcode></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>The ioctl timed-out. Try again.</para>
|
<para>The hardware seek found no channels.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><errorcode>EBUSY</errorcode></term>
|
||||||
|
<listitem>
|
||||||
|
<para>Another hardware seek is already in progress.</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
|
|
|
@ -72,10 +72,10 @@
|
||||||
<section>
|
<section>
|
||||||
<title>Types of selection targets</title>
|
<title>Types of selection targets</title>
|
||||||
|
|
||||||
<para>There are two types of selection targets: actual and bounds.
|
<para>There are two types of selection targets: actual and bounds. The
|
||||||
The ACTUAL targets are the targets which configure the hardware.
|
actual targets are the targets which configure the hardware. The BOUNDS
|
||||||
The BOUNDS target will return a rectangle that contain all
|
target will return a rectangle that contain all possible actual
|
||||||
possible ACTUAL rectangles.</para>
|
rectangles.</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
|
@ -87,71 +87,8 @@
|
||||||
<constant>EINVAL</constant>.</para>
|
<constant>EINVAL</constant>.</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<table pgwide="1" frame="none" id="v4l2-subdev-selection-targets">
|
<para>Selection targets and flags are documented in <xref
|
||||||
<title>V4L2 subdev selection targets</title>
|
linkend="v4l2-selections-common"/>.</para>
|
||||||
<tgroup cols="3">
|
|
||||||
&cs-def;
|
|
||||||
<tbody valign="top">
|
|
||||||
<row>
|
|
||||||
<entry><constant>V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL</constant></entry>
|
|
||||||
<entry>0x0000</entry>
|
|
||||||
<entry>Actual crop. Defines the cropping
|
|
||||||
performed by the processing step.</entry>
|
|
||||||
</row>
|
|
||||||
<row>
|
|
||||||
<entry><constant>V4L2_SUBDEV_SEL_TGT_CROP_BOUNDS</constant></entry>
|
|
||||||
<entry>0x0002</entry>
|
|
||||||
<entry>Bounds of the crop rectangle.</entry>
|
|
||||||
</row>
|
|
||||||
<row>
|
|
||||||
<entry><constant>V4L2_SUBDEV_SEL_TGT_COMPOSE_ACTUAL</constant></entry>
|
|
||||||
<entry>0x0100</entry>
|
|
||||||
<entry>Actual compose rectangle. Used to configure scaling
|
|
||||||
on sink pads and composition on source pads.</entry>
|
|
||||||
</row>
|
|
||||||
<row>
|
|
||||||
<entry><constant>V4L2_SUBDEV_SEL_TGT_COMPOSE_BOUNDS</constant></entry>
|
|
||||||
<entry>0x0102</entry>
|
|
||||||
<entry>Bounds of the compose rectangle.</entry>
|
|
||||||
</row>
|
|
||||||
</tbody>
|
|
||||||
</tgroup>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<table pgwide="1" frame="none" id="v4l2-subdev-selection-flags">
|
|
||||||
<title>V4L2 subdev selection flags</title>
|
|
||||||
<tgroup cols="3">
|
|
||||||
&cs-def;
|
|
||||||
<tbody valign="top">
|
|
||||||
<row>
|
|
||||||
<entry><constant>V4L2_SUBDEV_SEL_FLAG_SIZE_GE</constant></entry>
|
|
||||||
<entry>(1 << 0)</entry> <entry>Suggest the driver it
|
|
||||||
should choose greater or equal rectangle (in size) than
|
|
||||||
was requested. Albeit the driver may choose a lesser size,
|
|
||||||
it will only do so due to hardware limitations. Without
|
|
||||||
this flag (and
|
|
||||||
<constant>V4L2_SUBDEV_SEL_FLAG_SIZE_LE</constant>) the
|
|
||||||
behaviour is to choose the closest possible
|
|
||||||
rectangle.</entry>
|
|
||||||
</row>
|
|
||||||
<row>
|
|
||||||
<entry><constant>V4L2_SUBDEV_SEL_FLAG_SIZE_LE</constant></entry>
|
|
||||||
<entry>(1 << 1)</entry> <entry>Suggest the driver it
|
|
||||||
should choose lesser or equal rectangle (in size) than was
|
|
||||||
requested. Albeit the driver may choose a greater size, it
|
|
||||||
will only do so due to hardware limitations.</entry>
|
|
||||||
</row>
|
|
||||||
<row>
|
|
||||||
<entry><constant>V4L2_SUBDEV_SEL_FLAG_KEEP_CONFIG</constant></entry>
|
|
||||||
<entry>(1 << 2)</entry>
|
|
||||||
<entry>The configuration should not be propagated to any
|
|
||||||
further processing steps. If this flag is not given, the
|
|
||||||
configuration is propagated inside the subdevice to all
|
|
||||||
further processing steps.</entry>
|
|
||||||
</row>
|
|
||||||
</tbody>
|
|
||||||
</tgroup>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<table pgwide="1" frame="none" id="v4l2-subdev-selection">
|
<table pgwide="1" frame="none" id="v4l2-subdev-selection">
|
||||||
<title>struct <structname>v4l2_subdev_selection</structname></title>
|
<title>struct <structname>v4l2_subdev_selection</structname></title>
|
||||||
|
@ -173,13 +110,13 @@
|
||||||
<entry>__u32</entry>
|
<entry>__u32</entry>
|
||||||
<entry><structfield>target</structfield></entry>
|
<entry><structfield>target</structfield></entry>
|
||||||
<entry>Target selection rectangle. See
|
<entry>Target selection rectangle. See
|
||||||
<xref linkend="v4l2-subdev-selection-targets">.</xref>.</entry>
|
<xref linkend="v4l2-selections-common" />.</entry>
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry>__u32</entry>
|
<entry>__u32</entry>
|
||||||
<entry><structfield>flags</structfield></entry>
|
<entry><structfield>flags</structfield></entry>
|
||||||
<entry>Flags. See
|
<entry>Flags. See
|
||||||
<xref linkend="v4l2-subdev-selection-flags">.</xref></entry>
|
<xref linkend="v4l2-selection-flags" />.</entry>
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry>&v4l2-rect;</entry>
|
<entry>&v4l2-rect;</entry>
|
||||||
|
|
|
@ -29,7 +29,7 @@ use IO::Handle;
|
||||||
"af9015", "ngene", "az6027", "lme2510_lg", "lme2510c_s7395",
|
"af9015", "ngene", "az6027", "lme2510_lg", "lme2510c_s7395",
|
||||||
"lme2510c_s7395_old", "drxk", "drxk_terratec_h5",
|
"lme2510c_s7395_old", "drxk", "drxk_terratec_h5",
|
||||||
"drxk_hauppauge_hvr930c", "tda10071", "it9135", "it9137",
|
"drxk_hauppauge_hvr930c", "tda10071", "it9135", "it9137",
|
||||||
"drxk_pctv");
|
"drxk_pctv", "drxk_terratec_htc_stick", "sms1xxx_hcw");
|
||||||
|
|
||||||
# Check args
|
# Check args
|
||||||
syntax() if (scalar(@ARGV) != 1);
|
syntax() if (scalar(@ARGV) != 1);
|
||||||
|
@ -676,6 +676,24 @@ sub drxk_terratec_h5 {
|
||||||
"$fwfile"
|
"$fwfile"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub drxk_terratec_htc_stick {
|
||||||
|
my $url = "http://ftp.terratec.de/Receiver/Cinergy_HTC_Stick/Updates/";
|
||||||
|
my $zipfile = "Cinergy_HTC_Stick_Drv_5.09.1202.00_XP_Vista_7.exe";
|
||||||
|
my $hash = "6722a2442a05423b781721fbc069ed5e";
|
||||||
|
my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 0);
|
||||||
|
my $drvfile = "Cinergy HTC Stick/BDA Driver 5.09.1202.00/Windows 32 Bit/emOEM.sys";
|
||||||
|
my $fwfile = "dvb-usb-terratec-htc-stick-drxk.fw";
|
||||||
|
|
||||||
|
checkstandard();
|
||||||
|
|
||||||
|
wgetfile($zipfile, $url . $zipfile);
|
||||||
|
verify($zipfile, $hash);
|
||||||
|
unzip($zipfile, $tmpdir);
|
||||||
|
extract("$tmpdir/$drvfile", 0x4e5c0, 42692, "$fwfile");
|
||||||
|
|
||||||
|
"$fwfile"
|
||||||
|
}
|
||||||
|
|
||||||
sub it9135 {
|
sub it9135 {
|
||||||
my $sourcefile = "dvb-usb-it9135.zip";
|
my $sourcefile = "dvb-usb-it9135.zip";
|
||||||
my $url = "http://www.ite.com.tw/uploads/firmware/v3.6.0.0/$sourcefile";
|
my $url = "http://www.ite.com.tw/uploads/firmware/v3.6.0.0/$sourcefile";
|
||||||
|
@ -748,6 +766,28 @@ sub drxk_pctv {
|
||||||
"$fwfile";
|
"$fwfile";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub sms1xxx_hcw {
|
||||||
|
my $url = "http://steventoth.net/linux/sms1xxx/";
|
||||||
|
my %files = (
|
||||||
|
'sms1xxx-hcw-55xxx-dvbt-01.fw' => "afb6f9fb9a71d64392e8564ef9577e5a",
|
||||||
|
'sms1xxx-hcw-55xxx-dvbt-02.fw' => "b44807098ba26e52cbedeadc052ba58f",
|
||||||
|
'sms1xxx-hcw-55xxx-isdbt-02.fw' => "dae934eeea85225acbd63ce6cfe1c9e4",
|
||||||
|
);
|
||||||
|
|
||||||
|
checkstandard();
|
||||||
|
|
||||||
|
my $allfiles;
|
||||||
|
foreach my $fwfile (keys %files) {
|
||||||
|
wgetfile($fwfile, "$url/$fwfile");
|
||||||
|
verify($fwfile, $files{$fwfile});
|
||||||
|
$allfiles .= " $fwfile";
|
||||||
|
}
|
||||||
|
|
||||||
|
$allfiles =~ s/^\s//;
|
||||||
|
|
||||||
|
$allfiles;
|
||||||
|
}
|
||||||
|
|
||||||
# ---------------------------------------------------------------
|
# ---------------------------------------------------------------
|
||||||
# Utilities
|
# Utilities
|
||||||
|
|
||||||
|
|
|
@ -600,3 +600,21 @@ When: June 2013
|
||||||
Why: Unsupported/unmaintained/unused since 2.6
|
Why: Unsupported/unmaintained/unused since 2.6
|
||||||
|
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
|
What: V4L2 selections API target rectangle and flags unification, the
|
||||||
|
following definitions will be removed: V4L2_SEL_TGT_CROP_ACTIVE,
|
||||||
|
V4L2_SEL_TGT_COMPOSE_ACTIVE, V4L2_SUBDEV_SEL_*, V4L2_SUBDEV_SEL_FLAG_*
|
||||||
|
in favor of common V4L2_SEL_TGT_* and V4L2_SEL_FLAG_* definitions.
|
||||||
|
For more details see include/linux/v4l2-common.h.
|
||||||
|
When: 3.8
|
||||||
|
Why: The regular V4L2 selections and the subdev selection API originally
|
||||||
|
defined distinct names for the target rectangles and flags - V4L2_SEL_*
|
||||||
|
and V4L2_SUBDEV_SEL_*. Although, it turned out that the meaning of these
|
||||||
|
target rectangles is virtually identical and the APIs were consolidated
|
||||||
|
to use single set of names - V4L2_SEL_*. This didn't involve any ABI
|
||||||
|
changes. Alias definitions were created for the original ones to avoid
|
||||||
|
any instabilities in the user space interface. After few cycles these
|
||||||
|
backward compatibility definitions will be removed.
|
||||||
|
Who: Sylwester Nawrocki <sylvester.nawrocki@gmail.com>
|
||||||
|
|
||||||
|
----------------------------
|
||||||
|
|
|
@ -594,6 +594,15 @@ You should also set these fields:
|
||||||
unlocked_ioctl file operation is called this lock will be taken by the
|
unlocked_ioctl file operation is called this lock will be taken by the
|
||||||
core and released afterwards. See the next section for more details.
|
core and released afterwards. See the next section for more details.
|
||||||
|
|
||||||
|
- queue: a pointer to the struct vb2_queue associated with this device node.
|
||||||
|
If queue is non-NULL, and queue->lock is non-NULL, then queue->lock is
|
||||||
|
used for the queuing ioctls (VIDIOC_REQBUFS, CREATE_BUFS, QBUF, DQBUF,
|
||||||
|
QUERYBUF, PREPARE_BUF, STREAMON and STREAMOFF) instead of the lock above.
|
||||||
|
That way the vb2 queuing framework does not have to wait for other ioctls.
|
||||||
|
This queue pointer is also used by the vb2 helper functions to check for
|
||||||
|
queuing ownership (i.e. is the filehandle calling it allowed to do the
|
||||||
|
operation).
|
||||||
|
|
||||||
- prio: keeps track of the priorities. Used to implement VIDIOC_G/S_PRIORITY.
|
- prio: keeps track of the priorities. Used to implement VIDIOC_G/S_PRIORITY.
|
||||||
If left to NULL, then it will use the struct v4l2_prio_state in v4l2_device.
|
If left to NULL, then it will use the struct v4l2_prio_state in v4l2_device.
|
||||||
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),
|
||||||
|
@ -647,47 +656,43 @@ manually set the struct media_entity type and name fields.
|
||||||
A reference to the entity will be automatically acquired/released when the
|
A reference to the entity will be automatically acquired/released when the
|
||||||
video device is opened/closed.
|
video device is opened/closed.
|
||||||
|
|
||||||
v4l2_file_operations and locking
|
ioctls and locking
|
||||||
--------------------------------
|
------------------
|
||||||
|
|
||||||
You can set a pointer to a mutex_lock in struct video_device. Usually this
|
The V4L core provides optional locking services. The main service is the
|
||||||
will be either a top-level mutex or a mutex per device node. By default this
|
lock field in struct video_device, which is a pointer to a mutex. If you set
|
||||||
lock will be used for unlocked_ioctl, but you can disable locking for
|
this pointer, then that will be used by unlocked_ioctl to serialize all ioctls.
|
||||||
selected ioctls by calling:
|
|
||||||
|
|
||||||
void v4l2_disable_ioctl_locking(struct video_device *vdev, unsigned int cmd);
|
If you are using the videobuf2 framework, then there is a second lock that you
|
||||||
|
can set: video_device->queue->lock. If set, then this lock will be used instead
|
||||||
|
of video_device->lock to serialize all queuing ioctls (see the previous section
|
||||||
|
for the full list of those ioctls).
|
||||||
|
|
||||||
E.g.: v4l2_disable_ioctl_locking(vdev, VIDIOC_DQBUF);
|
The advantage of using a different lock for the queuing ioctls is that for some
|
||||||
|
drivers (particularly USB drivers) certain commands such as setting controls
|
||||||
|
can take a long time, so you want to use a separate lock for the buffer queuing
|
||||||
|
ioctls. That way your VIDIOC_DQBUF doesn't stall because the driver is busy
|
||||||
|
changing the e.g. exposure of the webcam.
|
||||||
|
|
||||||
You have to call this before you register the video_device.
|
Of course, you can always do all the locking yourself by leaving both lock
|
||||||
|
pointers at NULL.
|
||||||
|
|
||||||
Particularly with USB drivers where certain commands such as setting controls
|
If you use the old videobuf then you must pass the video_device lock to the
|
||||||
can take a long time you may want to do your own locking for the buffer queuing
|
videobuf queue initialize function: if videobuf has to wait for a frame to
|
||||||
ioctls.
|
arrive, then it will temporarily unlock the lock and relock it afterwards. If
|
||||||
|
your driver also waits in the code, then you should do the same to allow other
|
||||||
If you want still finer-grained locking then you have to set mutex_lock to NULL
|
processes to access the device node while the first process is waiting for
|
||||||
and do you own locking completely.
|
something.
|
||||||
|
|
||||||
It is up to the driver developer to decide which method to use. However, if
|
|
||||||
your driver has high-latency operations (for example, changing the exposure
|
|
||||||
of a USB webcam might take a long time), then you might be better off with
|
|
||||||
doing your own locking if you want to allow the user to do other things with
|
|
||||||
the device while waiting for the high-latency command to finish.
|
|
||||||
|
|
||||||
If a lock is specified then all ioctl commands will be serialized on that
|
|
||||||
lock. If you use videobuf then you must pass the same lock to the videobuf
|
|
||||||
queue initialize function: if videobuf has to wait for a frame to arrive, then
|
|
||||||
it will temporarily unlock the lock and relock it afterwards. If your driver
|
|
||||||
also waits in the code, then you should do the same to allow other processes
|
|
||||||
to access the device node while the first process is waiting for something.
|
|
||||||
|
|
||||||
In the case of videobuf2 you will need to implement the wait_prepare and
|
In the case of videobuf2 you will need to implement the wait_prepare and
|
||||||
wait_finish callbacks to unlock/lock if applicable. In particular, if you use
|
wait_finish callbacks to unlock/lock if applicable. If you use the queue->lock
|
||||||
the lock in struct video_device then you must unlock/lock this mutex in
|
pointer, then you can use the helper functions vb2_ops_wait_prepare/finish.
|
||||||
wait_prepare and wait_finish.
|
|
||||||
|
|
||||||
The implementation of a hotplug disconnect should also take the lock before
|
The implementation of a hotplug disconnect should also take the lock from
|
||||||
calling v4l2_device_disconnect.
|
video_device before calling v4l2_device_disconnect. If you are also using
|
||||||
|
video_device->queue->lock, then you have to first lock video_device->queue->lock
|
||||||
|
followed by video_device->lock. That way you can be sure no ioctl is running
|
||||||
|
when you call v4l2_device_disconnect.
|
||||||
|
|
||||||
video_device registration
|
video_device registration
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
|
@ -3156,8 +3156,7 @@ S: Maintained
|
||||||
F: drivers/media/video/gspca/t613.c
|
F: drivers/media/video/gspca/t613.c
|
||||||
|
|
||||||
GSPCA USB WEBCAM DRIVER
|
GSPCA USB WEBCAM DRIVER
|
||||||
M: Jean-Francois Moine <moinejf@free.fr>
|
M: Hans de Goede <hdegoede@redhat.com>
|
||||||
W: http://moinejf.free.fr
|
|
||||||
L: linux-media@vger.kernel.org
|
L: linux-media@vger.kernel.org
|
||||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
|
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
|
@ -1311,6 +1311,37 @@ module_exit(i2c_exit);
|
||||||
* ----------------------------------------------------
|
* ----------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __i2c_transfer - unlocked flavor of i2c_transfer
|
||||||
|
* @adap: Handle to I2C bus
|
||||||
|
* @msgs: One or more messages to execute before STOP is issued to
|
||||||
|
* terminate the operation; each message begins with a START.
|
||||||
|
* @num: Number of messages to be executed.
|
||||||
|
*
|
||||||
|
* Returns negative errno, else the number of messages executed.
|
||||||
|
*
|
||||||
|
* Adapter lock must be held when calling this function. No debug logging
|
||||||
|
* takes place. adap->algo->master_xfer existence isn't checked.
|
||||||
|
*/
|
||||||
|
int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
|
||||||
|
{
|
||||||
|
unsigned long orig_jiffies;
|
||||||
|
int ret, try;
|
||||||
|
|
||||||
|
/* Retry automatically on arbitration loss */
|
||||||
|
orig_jiffies = jiffies;
|
||||||
|
for (ret = 0, try = 0; try <= adap->retries; try++) {
|
||||||
|
ret = adap->algo->master_xfer(adap, msgs, num);
|
||||||
|
if (ret != -EAGAIN)
|
||||||
|
break;
|
||||||
|
if (time_after(jiffies, orig_jiffies + adap->timeout))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(__i2c_transfer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* i2c_transfer - execute a single or combined I2C message
|
* i2c_transfer - execute a single or combined I2C message
|
||||||
* @adap: Handle to I2C bus
|
* @adap: Handle to I2C bus
|
||||||
|
@ -1325,8 +1356,7 @@ module_exit(i2c_exit);
|
||||||
*/
|
*/
|
||||||
int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
|
int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
|
||||||
{
|
{
|
||||||
unsigned long orig_jiffies;
|
int ret;
|
||||||
int ret, try;
|
|
||||||
|
|
||||||
/* REVISIT the fault reporting model here is weak:
|
/* REVISIT the fault reporting model here is weak:
|
||||||
*
|
*
|
||||||
|
@ -1364,15 +1394,7 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
|
||||||
i2c_lock_adapter(adap);
|
i2c_lock_adapter(adap);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Retry automatically on arbitration loss */
|
ret = __i2c_transfer(adap, msgs, num);
|
||||||
orig_jiffies = jiffies;
|
|
||||||
for (ret = 0, try = 0; try <= adap->retries; try++) {
|
|
||||||
ret = adap->algo->master_xfer(adap, msgs, num);
|
|
||||||
if (ret != -EAGAIN)
|
|
||||||
break;
|
|
||||||
if (time_after(jiffies, orig_jiffies + adap->timeout))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
i2c_unlock_adapter(adap);
|
i2c_unlock_adapter(adap);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -6,20 +6,82 @@ menuconfig MEDIA_SUPPORT
|
||||||
tristate "Multimedia support"
|
tristate "Multimedia support"
|
||||||
depends on HAS_IOMEM
|
depends on HAS_IOMEM
|
||||||
help
|
help
|
||||||
If you want to use Video for Linux, DVB for Linux, or DAB adapters,
|
If you want to use Webcams, Video grabber devices and/or TV devices
|
||||||
enable this option and other options below.
|
enable this option and other options below.
|
||||||
|
Additional info and docs are available on the web at
|
||||||
|
<http://linuxtv.org>
|
||||||
|
|
||||||
if MEDIA_SUPPORT
|
if MEDIA_SUPPORT
|
||||||
|
|
||||||
comment "Multimedia core support"
|
comment "Multimedia core support"
|
||||||
|
|
||||||
|
#
|
||||||
|
# Multimedia support - automatically enable V4L2 and DVB core
|
||||||
|
#
|
||||||
|
config MEDIA_CAMERA_SUPPORT
|
||||||
|
bool "Cameras/video grabbers support"
|
||||||
|
---help---
|
||||||
|
Enable support for webcams and video grabbers.
|
||||||
|
|
||||||
|
Say Y when you have a webcam or a video capture grabber board.
|
||||||
|
|
||||||
|
config MEDIA_ANALOG_TV_SUPPORT
|
||||||
|
bool "Analog TV support"
|
||||||
|
---help---
|
||||||
|
Enable analog TV support.
|
||||||
|
|
||||||
|
Say Y when you have a TV board with analog support or with a
|
||||||
|
hybrid analog/digital TV chipset.
|
||||||
|
|
||||||
|
Note: There are several DVB cards that are based on chips that
|
||||||
|
support both analog and digital TV. Disabling this option
|
||||||
|
will disable support for them.
|
||||||
|
|
||||||
|
config MEDIA_DIGITAL_TV_SUPPORT
|
||||||
|
bool "Digital TV support"
|
||||||
|
---help---
|
||||||
|
Enable digital TV support.
|
||||||
|
|
||||||
|
Say Y when you have a board with digital support or a board with
|
||||||
|
hybrid digital TV and analog TV.
|
||||||
|
|
||||||
|
config MEDIA_RADIO_SUPPORT
|
||||||
|
bool "AM/FM radio receivers/transmitters support"
|
||||||
|
---help---
|
||||||
|
Enable AM/FM radio support.
|
||||||
|
|
||||||
|
Additional info and docs are available on the web at
|
||||||
|
<http://linuxtv.org>
|
||||||
|
|
||||||
|
Say Y when you have a board with radio support.
|
||||||
|
|
||||||
|
Note: There are several TV cards that are based on chips that
|
||||||
|
support radio reception. Disabling this option will
|
||||||
|
disable support for them.
|
||||||
|
|
||||||
|
config MEDIA_RC_SUPPORT
|
||||||
|
bool "Remote Controller support"
|
||||||
|
depends on INPUT
|
||||||
|
---help---
|
||||||
|
Enable support for Remote Controllers on Linux. This is
|
||||||
|
needed in order to support several video capture adapters,
|
||||||
|
standalone IR receivers/transmitters, and RF receivers.
|
||||||
|
|
||||||
|
Enable this option if you have a video capture board even
|
||||||
|
if you don't need IR, as otherwise, you may not be able to
|
||||||
|
compile the driver for your adapter.
|
||||||
|
|
||||||
|
Say Y when you have a TV or an IR device.
|
||||||
|
|
||||||
#
|
#
|
||||||
# Media controller
|
# Media controller
|
||||||
|
# Selectable only for webcam/grabbers, as other drivers don't use it
|
||||||
#
|
#
|
||||||
|
|
||||||
config MEDIA_CONTROLLER
|
config MEDIA_CONTROLLER
|
||||||
bool "Media Controller API (EXPERIMENTAL)"
|
bool "Media Controller API (EXPERIMENTAL)"
|
||||||
depends on EXPERIMENTAL
|
depends on EXPERIMENTAL
|
||||||
|
depends on MEDIA_CAMERA_SUPPORT
|
||||||
---help---
|
---help---
|
||||||
Enable the media controller API used to query media devices internal
|
Enable the media controller API used to query media devices internal
|
||||||
topology and configure it dynamically.
|
topology and configure it dynamically.
|
||||||
|
@ -27,26 +89,15 @@ config MEDIA_CONTROLLER
|
||||||
This API is mostly used by camera interfaces in embedded platforms.
|
This API is mostly used by camera interfaces in embedded platforms.
|
||||||
|
|
||||||
#
|
#
|
||||||
# V4L core and enabled API's
|
# Video4Linux support
|
||||||
|
# Only enables if one of the V4L2 types (ATV, webcam, radio) is selected
|
||||||
#
|
#
|
||||||
|
|
||||||
config VIDEO_DEV
|
config VIDEO_DEV
|
||||||
tristate "Video For Linux"
|
tristate
|
||||||
---help---
|
depends on MEDIA_SUPPORT
|
||||||
V4L core support for video capture and overlay devices, webcams and
|
depends on MEDIA_CAMERA_SUPPORT || MEDIA_ANALOG_TV_SUPPORT || MEDIA_RADIO_SUPPORT
|
||||||
AM/FM radio cards.
|
default y
|
||||||
|
|
||||||
This kernel includes support for the new Video for Linux Two API,
|
|
||||||
(V4L2).
|
|
||||||
|
|
||||||
Additional info and docs are available on the web at
|
|
||||||
<http://linuxtv.org>
|
|
||||||
|
|
||||||
Documentation for V4L2 is also available on the web at
|
|
||||||
<http://bytesex.org/v4l/>.
|
|
||||||
|
|
||||||
To compile this driver as a module, choose M here: the
|
|
||||||
module will be called videodev.
|
|
||||||
|
|
||||||
config VIDEO_V4L2_COMMON
|
config VIDEO_V4L2_COMMON
|
||||||
tristate
|
tristate
|
||||||
|
@ -64,25 +115,15 @@ config VIDEO_V4L2_SUBDEV_API
|
||||||
|
|
||||||
#
|
#
|
||||||
# DVB Core
|
# DVB Core
|
||||||
|
# Only enables if one of DTV is selected
|
||||||
#
|
#
|
||||||
|
|
||||||
config DVB_CORE
|
config DVB_CORE
|
||||||
tristate "DVB for Linux"
|
tristate
|
||||||
|
depends on MEDIA_SUPPORT
|
||||||
|
depends on MEDIA_DIGITAL_TV_SUPPORT
|
||||||
|
default y
|
||||||
select CRC32
|
select CRC32
|
||||||
help
|
|
||||||
DVB core utility functions for device handling, software fallbacks etc.
|
|
||||||
|
|
||||||
Enable this if you own a DVB/ATSC adapter and want to use it or if
|
|
||||||
you compile Linux for a digital SetTopBox.
|
|
||||||
|
|
||||||
Say Y when you have a DVB or an ATSC card and want to use it.
|
|
||||||
|
|
||||||
API specs and user tools are available from <http://www.linuxtv.org/>.
|
|
||||||
|
|
||||||
Please report problems regarding this support to the LinuxDVB
|
|
||||||
mailing list.
|
|
||||||
|
|
||||||
If unsure say N.
|
|
||||||
|
|
||||||
config DVB_NET
|
config DVB_NET
|
||||||
bool "DVB Network Support"
|
bool "DVB Network Support"
|
||||||
|
@ -97,12 +138,7 @@ config DVB_NET
|
||||||
You may want to disable the network support on embedded devices. If
|
You may want to disable the network support on embedded devices. If
|
||||||
unsure say Y.
|
unsure say Y.
|
||||||
|
|
||||||
config VIDEO_MEDIA
|
comment "Media drivers"
|
||||||
tristate
|
|
||||||
default (DVB_CORE && (VIDEO_DEV = n)) || (VIDEO_DEV && (DVB_CORE = n)) || (DVB_CORE && VIDEO_DEV)
|
|
||||||
|
|
||||||
comment "Multimedia drivers"
|
|
||||||
|
|
||||||
source "drivers/media/common/Kconfig"
|
source "drivers/media/common/Kconfig"
|
||||||
source "drivers/media/rc/Kconfig"
|
source "drivers/media/rc/Kconfig"
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
config MEDIA_ATTACH
|
config MEDIA_ATTACH
|
||||||
bool "Load and attach frontend and tuner driver modules as needed"
|
bool "Load and attach frontend and tuner driver modules as needed"
|
||||||
depends on VIDEO_MEDIA
|
depends on MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT || MEDIA_RADIO_SUPPORT
|
||||||
depends on MODULES
|
depends on MODULES
|
||||||
|
default y if !EXPERT
|
||||||
help
|
help
|
||||||
Remove the static dependency of DVB card drivers on all
|
Remove the static dependency of DVB card drivers on all
|
||||||
frontend modules for all possible card variants. Instead,
|
frontend modules for all possible card variants. Instead,
|
||||||
|
@ -19,15 +20,15 @@ config MEDIA_ATTACH
|
||||||
|
|
||||||
config MEDIA_TUNER
|
config MEDIA_TUNER
|
||||||
tristate
|
tristate
|
||||||
default VIDEO_MEDIA && I2C
|
depends on (MEDIA_ANALOG_TV_SUPPORT || MEDIA_RADIO_SUPPORT) && I2C
|
||||||
depends on VIDEO_MEDIA && I2C
|
default y
|
||||||
select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
|
select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
|
||||||
select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE
|
select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE
|
||||||
select MEDIA_TUNER_XC4000 if !MEDIA_TUNER_CUSTOMISE
|
select MEDIA_TUNER_XC4000 if !MEDIA_TUNER_CUSTOMISE
|
||||||
select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMISE
|
select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMISE
|
||||||
select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
|
select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
|
||||||
select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMISE && EXPERIMENTAL
|
select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMISE && MEDIA_RADIO_SUPPORT && EXPERIMENTAL
|
||||||
select MEDIA_TUNER_TEA5767 if !MEDIA_TUNER_CUSTOMISE
|
select MEDIA_TUNER_TEA5767 if !MEDIA_TUNER_CUSTOMISE && MEDIA_RADIO_SUPPORT
|
||||||
select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
|
select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
|
||||||
select MEDIA_TUNER_TDA9887 if !MEDIA_TUNER_CUSTOMISE
|
select MEDIA_TUNER_TDA9887 if !MEDIA_TUNER_CUSTOMISE
|
||||||
select MEDIA_TUNER_MC44S803 if !MEDIA_TUNER_CUSTOMISE
|
select MEDIA_TUNER_MC44S803 if !MEDIA_TUNER_CUSTOMISE
|
||||||
|
@ -47,10 +48,11 @@ config MEDIA_TUNER_CUSTOMISE
|
||||||
|
|
||||||
menu "Customize TV tuners"
|
menu "Customize TV tuners"
|
||||||
visible if MEDIA_TUNER_CUSTOMISE
|
visible if MEDIA_TUNER_CUSTOMISE
|
||||||
|
depends on MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT || MEDIA_RADIO_SUPPORT
|
||||||
|
|
||||||
config MEDIA_TUNER_SIMPLE
|
config MEDIA_TUNER_SIMPLE
|
||||||
tristate "Simple tuner support"
|
tristate "Simple tuner support"
|
||||||
depends on VIDEO_MEDIA && I2C
|
depends on MEDIA_SUPPORT && I2C
|
||||||
select MEDIA_TUNER_TDA9887
|
select MEDIA_TUNER_TDA9887
|
||||||
default m if MEDIA_TUNER_CUSTOMISE
|
default m if MEDIA_TUNER_CUSTOMISE
|
||||||
help
|
help
|
||||||
|
@ -58,7 +60,7 @@ config MEDIA_TUNER_SIMPLE
|
||||||
|
|
||||||
config MEDIA_TUNER_TDA8290
|
config MEDIA_TUNER_TDA8290
|
||||||
tristate "TDA 8290/8295 + 8275(a)/18271 tuner combo"
|
tristate "TDA 8290/8295 + 8275(a)/18271 tuner combo"
|
||||||
depends on VIDEO_MEDIA && I2C
|
depends on MEDIA_SUPPORT && I2C
|
||||||
select MEDIA_TUNER_TDA827X
|
select MEDIA_TUNER_TDA827X
|
||||||
select MEDIA_TUNER_TDA18271
|
select MEDIA_TUNER_TDA18271
|
||||||
default m if MEDIA_TUNER_CUSTOMISE
|
default m if MEDIA_TUNER_CUSTOMISE
|
||||||
|
@ -67,21 +69,21 @@ config MEDIA_TUNER_TDA8290
|
||||||
|
|
||||||
config MEDIA_TUNER_TDA827X
|
config MEDIA_TUNER_TDA827X
|
||||||
tristate "Philips TDA827X silicon tuner"
|
tristate "Philips TDA827X silicon tuner"
|
||||||
depends on VIDEO_MEDIA && I2C
|
depends on MEDIA_SUPPORT && I2C
|
||||||
default m if MEDIA_TUNER_CUSTOMISE
|
default m if MEDIA_TUNER_CUSTOMISE
|
||||||
help
|
help
|
||||||
A DVB-T silicon tuner module. Say Y when you want to support this tuner.
|
A DVB-T silicon tuner module. Say Y when you want to support this tuner.
|
||||||
|
|
||||||
config MEDIA_TUNER_TDA18271
|
config MEDIA_TUNER_TDA18271
|
||||||
tristate "NXP TDA18271 silicon tuner"
|
tristate "NXP TDA18271 silicon tuner"
|
||||||
depends on VIDEO_MEDIA && I2C
|
depends on MEDIA_SUPPORT && I2C
|
||||||
default m if MEDIA_TUNER_CUSTOMISE
|
default m if MEDIA_TUNER_CUSTOMISE
|
||||||
help
|
help
|
||||||
A silicon tuner module. Say Y when you want to support this tuner.
|
A silicon tuner module. Say Y when you want to support this tuner.
|
||||||
|
|
||||||
config MEDIA_TUNER_TDA9887
|
config MEDIA_TUNER_TDA9887
|
||||||
tristate "TDA 9885/6/7 analog IF demodulator"
|
tristate "TDA 9885/6/7 analog IF demodulator"
|
||||||
depends on VIDEO_MEDIA && I2C
|
depends on MEDIA_SUPPORT && I2C
|
||||||
default m if MEDIA_TUNER_CUSTOMISE
|
default m if MEDIA_TUNER_CUSTOMISE
|
||||||
help
|
help
|
||||||
Say Y here to include support for Philips TDA9885/6/7
|
Say Y here to include support for Philips TDA9885/6/7
|
||||||
|
@ -89,7 +91,7 @@ config MEDIA_TUNER_TDA9887
|
||||||
|
|
||||||
config MEDIA_TUNER_TEA5761
|
config MEDIA_TUNER_TEA5761
|
||||||
tristate "TEA 5761 radio tuner (EXPERIMENTAL)"
|
tristate "TEA 5761 radio tuner (EXPERIMENTAL)"
|
||||||
depends on VIDEO_MEDIA && I2C
|
depends on MEDIA_SUPPORT && I2C
|
||||||
depends on EXPERIMENTAL
|
depends on EXPERIMENTAL
|
||||||
default m if MEDIA_TUNER_CUSTOMISE
|
default m if MEDIA_TUNER_CUSTOMISE
|
||||||
help
|
help
|
||||||
|
@ -97,63 +99,63 @@ config MEDIA_TUNER_TEA5761
|
||||||
|
|
||||||
config MEDIA_TUNER_TEA5767
|
config MEDIA_TUNER_TEA5767
|
||||||
tristate "TEA 5767 radio tuner"
|
tristate "TEA 5767 radio tuner"
|
||||||
depends on VIDEO_MEDIA && I2C
|
depends on MEDIA_SUPPORT && I2C
|
||||||
default m if MEDIA_TUNER_CUSTOMISE
|
default m if MEDIA_TUNER_CUSTOMISE
|
||||||
help
|
help
|
||||||
Say Y here to include support for the Philips TEA5767 radio tuner.
|
Say Y here to include support for the Philips TEA5767 radio tuner.
|
||||||
|
|
||||||
config MEDIA_TUNER_MT20XX
|
config MEDIA_TUNER_MT20XX
|
||||||
tristate "Microtune 2032 / 2050 tuners"
|
tristate "Microtune 2032 / 2050 tuners"
|
||||||
depends on VIDEO_MEDIA && I2C
|
depends on MEDIA_SUPPORT && I2C
|
||||||
default m if MEDIA_TUNER_CUSTOMISE
|
default m if MEDIA_TUNER_CUSTOMISE
|
||||||
help
|
help
|
||||||
Say Y here to include support for the MT2032 / MT2050 tuner.
|
Say Y here to include support for the MT2032 / MT2050 tuner.
|
||||||
|
|
||||||
config MEDIA_TUNER_MT2060
|
config MEDIA_TUNER_MT2060
|
||||||
tristate "Microtune MT2060 silicon IF tuner"
|
tristate "Microtune MT2060 silicon IF tuner"
|
||||||
depends on VIDEO_MEDIA && I2C
|
depends on MEDIA_SUPPORT && I2C
|
||||||
default m if MEDIA_TUNER_CUSTOMISE
|
default m if MEDIA_TUNER_CUSTOMISE
|
||||||
help
|
help
|
||||||
A driver for the silicon IF tuner MT2060 from Microtune.
|
A driver for the silicon IF tuner MT2060 from Microtune.
|
||||||
|
|
||||||
config MEDIA_TUNER_MT2063
|
config MEDIA_TUNER_MT2063
|
||||||
tristate "Microtune MT2063 silicon IF tuner"
|
tristate "Microtune MT2063 silicon IF tuner"
|
||||||
depends on VIDEO_MEDIA && I2C
|
depends on MEDIA_SUPPORT && I2C
|
||||||
default m if MEDIA_TUNER_CUSTOMISE
|
default m if MEDIA_TUNER_CUSTOMISE
|
||||||
help
|
help
|
||||||
A driver for the silicon IF tuner MT2063 from Microtune.
|
A driver for the silicon IF tuner MT2063 from Microtune.
|
||||||
|
|
||||||
config MEDIA_TUNER_MT2266
|
config MEDIA_TUNER_MT2266
|
||||||
tristate "Microtune MT2266 silicon tuner"
|
tristate "Microtune MT2266 silicon tuner"
|
||||||
depends on VIDEO_MEDIA && I2C
|
depends on MEDIA_SUPPORT && I2C
|
||||||
default m if MEDIA_TUNER_CUSTOMISE
|
default m if MEDIA_TUNER_CUSTOMISE
|
||||||
help
|
help
|
||||||
A driver for the silicon baseband tuner MT2266 from Microtune.
|
A driver for the silicon baseband tuner MT2266 from Microtune.
|
||||||
|
|
||||||
config MEDIA_TUNER_MT2131
|
config MEDIA_TUNER_MT2131
|
||||||
tristate "Microtune MT2131 silicon tuner"
|
tristate "Microtune MT2131 silicon tuner"
|
||||||
depends on VIDEO_MEDIA && I2C
|
depends on MEDIA_SUPPORT && I2C
|
||||||
default m if MEDIA_TUNER_CUSTOMISE
|
default m if MEDIA_TUNER_CUSTOMISE
|
||||||
help
|
help
|
||||||
A driver for the silicon baseband tuner MT2131 from Microtune.
|
A driver for the silicon baseband tuner MT2131 from Microtune.
|
||||||
|
|
||||||
config MEDIA_TUNER_QT1010
|
config MEDIA_TUNER_QT1010
|
||||||
tristate "Quantek QT1010 silicon tuner"
|
tristate "Quantek QT1010 silicon tuner"
|
||||||
depends on VIDEO_MEDIA && I2C
|
depends on MEDIA_SUPPORT && I2C
|
||||||
default m if MEDIA_TUNER_CUSTOMISE
|
default m if MEDIA_TUNER_CUSTOMISE
|
||||||
help
|
help
|
||||||
A driver for the silicon tuner QT1010 from Quantek.
|
A driver for the silicon tuner QT1010 from Quantek.
|
||||||
|
|
||||||
config MEDIA_TUNER_XC2028
|
config MEDIA_TUNER_XC2028
|
||||||
tristate "XCeive xc2028/xc3028 tuners"
|
tristate "XCeive xc2028/xc3028 tuners"
|
||||||
depends on VIDEO_MEDIA && I2C
|
depends on MEDIA_SUPPORT && I2C
|
||||||
default m if MEDIA_TUNER_CUSTOMISE
|
default m if MEDIA_TUNER_CUSTOMISE
|
||||||
help
|
help
|
||||||
Say Y here to include support for the xc2028/xc3028 tuners.
|
Say Y here to include support for the xc2028/xc3028 tuners.
|
||||||
|
|
||||||
config MEDIA_TUNER_XC5000
|
config MEDIA_TUNER_XC5000
|
||||||
tristate "Xceive XC5000 silicon tuner"
|
tristate "Xceive XC5000 silicon tuner"
|
||||||
depends on VIDEO_MEDIA && I2C
|
depends on MEDIA_SUPPORT && I2C
|
||||||
default m if MEDIA_TUNER_CUSTOMISE
|
default m if MEDIA_TUNER_CUSTOMISE
|
||||||
help
|
help
|
||||||
A driver for the silicon tuner XC5000 from Xceive.
|
A driver for the silicon tuner XC5000 from Xceive.
|
||||||
|
@ -162,7 +164,7 @@ config MEDIA_TUNER_XC5000
|
||||||
|
|
||||||
config MEDIA_TUNER_XC4000
|
config MEDIA_TUNER_XC4000
|
||||||
tristate "Xceive XC4000 silicon tuner"
|
tristate "Xceive XC4000 silicon tuner"
|
||||||
depends on VIDEO_MEDIA && I2C
|
depends on MEDIA_SUPPORT && I2C
|
||||||
default m if MEDIA_TUNER_CUSTOMISE
|
default m if MEDIA_TUNER_CUSTOMISE
|
||||||
help
|
help
|
||||||
A driver for the silicon tuner XC4000 from Xceive.
|
A driver for the silicon tuner XC4000 from Xceive.
|
||||||
|
@ -171,70 +173,70 @@ config MEDIA_TUNER_XC4000
|
||||||
|
|
||||||
config MEDIA_TUNER_MXL5005S
|
config MEDIA_TUNER_MXL5005S
|
||||||
tristate "MaxLinear MSL5005S silicon tuner"
|
tristate "MaxLinear MSL5005S silicon tuner"
|
||||||
depends on VIDEO_MEDIA && I2C
|
depends on MEDIA_SUPPORT && I2C
|
||||||
default m if MEDIA_TUNER_CUSTOMISE
|
default m if MEDIA_TUNER_CUSTOMISE
|
||||||
help
|
help
|
||||||
A driver for the silicon tuner MXL5005S from MaxLinear.
|
A driver for the silicon tuner MXL5005S from MaxLinear.
|
||||||
|
|
||||||
config MEDIA_TUNER_MXL5007T
|
config MEDIA_TUNER_MXL5007T
|
||||||
tristate "MaxLinear MxL5007T silicon tuner"
|
tristate "MaxLinear MxL5007T silicon tuner"
|
||||||
depends on VIDEO_MEDIA && I2C
|
depends on MEDIA_SUPPORT && I2C
|
||||||
default m if MEDIA_TUNER_CUSTOMISE
|
default m if MEDIA_TUNER_CUSTOMISE
|
||||||
help
|
help
|
||||||
A driver for the silicon tuner MxL5007T from MaxLinear.
|
A driver for the silicon tuner MxL5007T from MaxLinear.
|
||||||
|
|
||||||
config MEDIA_TUNER_MC44S803
|
config MEDIA_TUNER_MC44S803
|
||||||
tristate "Freescale MC44S803 Low Power CMOS Broadband tuners"
|
tristate "Freescale MC44S803 Low Power CMOS Broadband tuners"
|
||||||
depends on VIDEO_MEDIA && I2C
|
depends on MEDIA_SUPPORT && I2C
|
||||||
default m if MEDIA_TUNER_CUSTOMISE
|
default m if MEDIA_TUNER_CUSTOMISE
|
||||||
help
|
help
|
||||||
Say Y here to support the Freescale MC44S803 based tuners
|
Say Y here to support the Freescale MC44S803 based tuners
|
||||||
|
|
||||||
config MEDIA_TUNER_MAX2165
|
config MEDIA_TUNER_MAX2165
|
||||||
tristate "Maxim MAX2165 silicon tuner"
|
tristate "Maxim MAX2165 silicon tuner"
|
||||||
depends on VIDEO_MEDIA && I2C
|
depends on MEDIA_SUPPORT && I2C
|
||||||
default m if MEDIA_TUNER_CUSTOMISE
|
default m if MEDIA_TUNER_CUSTOMISE
|
||||||
help
|
help
|
||||||
A driver for the silicon tuner MAX2165 from Maxim.
|
A driver for the silicon tuner MAX2165 from Maxim.
|
||||||
|
|
||||||
config MEDIA_TUNER_TDA18218
|
config MEDIA_TUNER_TDA18218
|
||||||
tristate "NXP TDA18218 silicon tuner"
|
tristate "NXP TDA18218 silicon tuner"
|
||||||
depends on VIDEO_MEDIA && I2C
|
depends on MEDIA_SUPPORT && I2C
|
||||||
default m if MEDIA_TUNER_CUSTOMISE
|
default m if MEDIA_TUNER_CUSTOMISE
|
||||||
help
|
help
|
||||||
NXP TDA18218 silicon tuner driver.
|
NXP TDA18218 silicon tuner driver.
|
||||||
|
|
||||||
config MEDIA_TUNER_FC0011
|
config MEDIA_TUNER_FC0011
|
||||||
tristate "Fitipower FC0011 silicon tuner"
|
tristate "Fitipower FC0011 silicon tuner"
|
||||||
depends on VIDEO_MEDIA && I2C
|
depends on MEDIA_SUPPORT && I2C
|
||||||
default m if MEDIA_TUNER_CUSTOMISE
|
default m if MEDIA_TUNER_CUSTOMISE
|
||||||
help
|
help
|
||||||
Fitipower FC0011 silicon tuner driver.
|
Fitipower FC0011 silicon tuner driver.
|
||||||
|
|
||||||
config MEDIA_TUNER_FC0012
|
config MEDIA_TUNER_FC0012
|
||||||
tristate "Fitipower FC0012 silicon tuner"
|
tristate "Fitipower FC0012 silicon tuner"
|
||||||
depends on VIDEO_MEDIA && I2C
|
depends on MEDIA_SUPPORT && I2C
|
||||||
default m if MEDIA_TUNER_CUSTOMISE
|
default m if MEDIA_TUNER_CUSTOMISE
|
||||||
help
|
help
|
||||||
Fitipower FC0012 silicon tuner driver.
|
Fitipower FC0012 silicon tuner driver.
|
||||||
|
|
||||||
config MEDIA_TUNER_FC0013
|
config MEDIA_TUNER_FC0013
|
||||||
tristate "Fitipower FC0013 silicon tuner"
|
tristate "Fitipower FC0013 silicon tuner"
|
||||||
depends on VIDEO_MEDIA && I2C
|
depends on MEDIA_SUPPORT && I2C
|
||||||
default m if MEDIA_TUNER_CUSTOMISE
|
default m if MEDIA_TUNER_CUSTOMISE
|
||||||
help
|
help
|
||||||
Fitipower FC0013 silicon tuner driver.
|
Fitipower FC0013 silicon tuner driver.
|
||||||
|
|
||||||
config MEDIA_TUNER_TDA18212
|
config MEDIA_TUNER_TDA18212
|
||||||
tristate "NXP TDA18212 silicon tuner"
|
tristate "NXP TDA18212 silicon tuner"
|
||||||
depends on VIDEO_MEDIA && I2C
|
depends on MEDIA_SUPPORT && I2C
|
||||||
default m if MEDIA_TUNER_CUSTOMISE
|
default m if MEDIA_TUNER_CUSTOMISE
|
||||||
help
|
help
|
||||||
NXP TDA18212 silicon tuner driver.
|
NXP TDA18212 silicon tuner driver.
|
||||||
|
|
||||||
config MEDIA_TUNER_TUA9001
|
config MEDIA_TUNER_TUA9001
|
||||||
tristate "Infineon TUA 9001 silicon tuner"
|
tristate "Infineon TUA 9001 silicon tuner"
|
||||||
depends on VIDEO_MEDIA && I2C
|
depends on MEDIA_SUPPORT && I2C
|
||||||
default m if MEDIA_TUNER_CUSTOMISE
|
default m if MEDIA_TUNER_CUSTOMISE
|
||||||
help
|
help
|
||||||
Infineon TUA 9001 silicon tuner driver.
|
Infineon TUA 9001 silicon tuner driver.
|
||||||
|
|
|
@ -90,11 +90,22 @@ struct firmware_properties {
|
||||||
int scode_nr;
|
int scode_nr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum xc2028_state {
|
||||||
|
XC2028_NO_FIRMWARE = 0,
|
||||||
|
XC2028_WAITING_FIRMWARE,
|
||||||
|
XC2028_ACTIVE,
|
||||||
|
XC2028_SLEEP,
|
||||||
|
XC2028_NODEV,
|
||||||
|
};
|
||||||
|
|
||||||
struct xc2028_data {
|
struct xc2028_data {
|
||||||
struct list_head hybrid_tuner_instance_list;
|
struct list_head hybrid_tuner_instance_list;
|
||||||
struct tuner_i2c_props i2c_props;
|
struct tuner_i2c_props i2c_props;
|
||||||
__u32 frequency;
|
__u32 frequency;
|
||||||
|
|
||||||
|
enum xc2028_state state;
|
||||||
|
const char *fname;
|
||||||
|
|
||||||
struct firmware_description *firm;
|
struct firmware_description *firm;
|
||||||
int firm_size;
|
int firm_size;
|
||||||
__u16 firm_version;
|
__u16 firm_version;
|
||||||
|
@ -255,6 +266,21 @@ static v4l2_std_id parse_audio_std_option(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int check_device_status(struct xc2028_data *priv)
|
||||||
|
{
|
||||||
|
switch (priv->state) {
|
||||||
|
case XC2028_NO_FIRMWARE:
|
||||||
|
case XC2028_WAITING_FIRMWARE:
|
||||||
|
return -EAGAIN;
|
||||||
|
case XC2028_ACTIVE:
|
||||||
|
case XC2028_SLEEP:
|
||||||
|
return 0;
|
||||||
|
case XC2028_NODEV:
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void free_firmware(struct xc2028_data *priv)
|
static void free_firmware(struct xc2028_data *priv)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -270,45 +296,28 @@ static void free_firmware(struct xc2028_data *priv)
|
||||||
|
|
||||||
priv->firm = NULL;
|
priv->firm = NULL;
|
||||||
priv->firm_size = 0;
|
priv->firm_size = 0;
|
||||||
|
priv->state = XC2028_NO_FIRMWARE;
|
||||||
|
|
||||||
memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
|
memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int load_all_firmwares(struct dvb_frontend *fe)
|
static int load_all_firmwares(struct dvb_frontend *fe,
|
||||||
|
const struct firmware *fw)
|
||||||
{
|
{
|
||||||
struct xc2028_data *priv = fe->tuner_priv;
|
struct xc2028_data *priv = fe->tuner_priv;
|
||||||
const struct firmware *fw = NULL;
|
|
||||||
const unsigned char *p, *endp;
|
const unsigned char *p, *endp;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
int n, n_array;
|
int n, n_array;
|
||||||
char name[33];
|
char name[33];
|
||||||
char *fname;
|
|
||||||
|
|
||||||
tuner_dbg("%s called\n", __func__);
|
tuner_dbg("%s called\n", __func__);
|
||||||
|
|
||||||
if (!firmware_name[0])
|
|
||||||
fname = priv->ctrl.fname;
|
|
||||||
else
|
|
||||||
fname = firmware_name;
|
|
||||||
|
|
||||||
tuner_dbg("Reading firmware %s\n", fname);
|
|
||||||
rc = request_firmware(&fw, fname, priv->i2c_props.adap->dev.parent);
|
|
||||||
if (rc < 0) {
|
|
||||||
if (rc == -ENOENT)
|
|
||||||
tuner_err("Error: firmware %s not found.\n",
|
|
||||||
fname);
|
|
||||||
else
|
|
||||||
tuner_err("Error %d while requesting firmware %s \n",
|
|
||||||
rc, fname);
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
p = fw->data;
|
p = fw->data;
|
||||||
endp = p + fw->size;
|
endp = p + fw->size;
|
||||||
|
|
||||||
if (fw->size < sizeof(name) - 1 + 2 + 2) {
|
if (fw->size < sizeof(name) - 1 + 2 + 2) {
|
||||||
tuner_err("Error: firmware file %s has invalid size!\n",
|
tuner_err("Error: firmware file %s has invalid size!\n",
|
||||||
fname);
|
priv->fname);
|
||||||
goto corrupt;
|
goto corrupt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,7 +332,7 @@ static int load_all_firmwares(struct dvb_frontend *fe)
|
||||||
p += 2;
|
p += 2;
|
||||||
|
|
||||||
tuner_info("Loading %d firmware images from %s, type: %s, ver %d.%d\n",
|
tuner_info("Loading %d firmware images from %s, type: %s, ver %d.%d\n",
|
||||||
n_array, fname, name,
|
n_array, priv->fname, name,
|
||||||
priv->firm_version >> 8, priv->firm_version & 0xff);
|
priv->firm_version >> 8, priv->firm_version & 0xff);
|
||||||
|
|
||||||
priv->firm = kcalloc(n_array, sizeof(*priv->firm), GFP_KERNEL);
|
priv->firm = kcalloc(n_array, sizeof(*priv->firm), GFP_KERNEL);
|
||||||
|
@ -417,9 +426,10 @@ err:
|
||||||
free_firmware(priv);
|
free_firmware(priv);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
release_firmware(fw);
|
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
tuner_dbg("Firmware files loaded.\n");
|
tuner_dbg("Firmware files loaded.\n");
|
||||||
|
else
|
||||||
|
priv->state = XC2028_NODEV;
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -707,22 +717,15 @@ static int check_firmware(struct dvb_frontend *fe, unsigned int type,
|
||||||
{
|
{
|
||||||
struct xc2028_data *priv = fe->tuner_priv;
|
struct xc2028_data *priv = fe->tuner_priv;
|
||||||
struct firmware_properties new_fw;
|
struct firmware_properties new_fw;
|
||||||
int rc = 0, retry_count = 0;
|
int rc, retry_count = 0;
|
||||||
u16 version, hwmodel;
|
u16 version, hwmodel;
|
||||||
v4l2_std_id std0;
|
v4l2_std_id std0;
|
||||||
|
|
||||||
tuner_dbg("%s called\n", __func__);
|
tuner_dbg("%s called\n", __func__);
|
||||||
|
|
||||||
if (!priv->firm) {
|
rc = check_device_status(priv);
|
||||||
if (!priv->ctrl.fname) {
|
if (rc < 0)
|
||||||
tuner_info("xc2028/3028 firmware name not set!\n");
|
return rc;
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = load_all_firmwares(fe);
|
|
||||||
if (rc < 0)
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (priv->ctrl.mts && !(type & FM))
|
if (priv->ctrl.mts && !(type & FM))
|
||||||
type |= MTS;
|
type |= MTS;
|
||||||
|
@ -749,9 +752,13 @@ retry:
|
||||||
printk("scode_nr %d\n", new_fw.scode_nr);
|
printk("scode_nr %d\n", new_fw.scode_nr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No need to reload base firmware if it matches */
|
/*
|
||||||
if (((BASE | new_fw.type) & BASE_TYPES) ==
|
* No need to reload base firmware if it matches and if the tuner
|
||||||
(priv->cur_fw.type & BASE_TYPES)) {
|
* is not at sleep mode
|
||||||
|
*/
|
||||||
|
if ((priv->state = XC2028_ACTIVE) &&
|
||||||
|
(((BASE | new_fw.type) & BASE_TYPES) ==
|
||||||
|
(priv->cur_fw.type & BASE_TYPES))) {
|
||||||
tuner_dbg("BASE firmware not changed.\n");
|
tuner_dbg("BASE firmware not changed.\n");
|
||||||
goto skip_base;
|
goto skip_base;
|
||||||
}
|
}
|
||||||
|
@ -872,10 +879,13 @@ read_not_reliable:
|
||||||
* 2. Tell whether BASE firmware was just changed the next time through.
|
* 2. Tell whether BASE firmware was just changed the next time through.
|
||||||
*/
|
*/
|
||||||
priv->cur_fw.type |= BASE;
|
priv->cur_fw.type |= BASE;
|
||||||
|
priv->state = XC2028_ACTIVE;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
priv->state = XC2028_SLEEP;
|
||||||
|
|
||||||
memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
|
memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
|
||||||
if (retry_count < 8) {
|
if (retry_count < 8) {
|
||||||
msleep(50);
|
msleep(50);
|
||||||
|
@ -893,28 +903,39 @@ static int xc2028_signal(struct dvb_frontend *fe, u16 *strength)
|
||||||
{
|
{
|
||||||
struct xc2028_data *priv = fe->tuner_priv;
|
struct xc2028_data *priv = fe->tuner_priv;
|
||||||
u16 frq_lock, signal = 0;
|
u16 frq_lock, signal = 0;
|
||||||
int rc;
|
int rc, i;
|
||||||
|
|
||||||
tuner_dbg("%s called\n", __func__);
|
tuner_dbg("%s called\n", __func__);
|
||||||
|
|
||||||
|
rc = check_device_status(priv);
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
mutex_lock(&priv->lock);
|
mutex_lock(&priv->lock);
|
||||||
|
|
||||||
/* Sync Lock Indicator */
|
/* Sync Lock Indicator */
|
||||||
rc = xc2028_get_reg(priv, XREG_LOCK, &frq_lock);
|
for (i = 0; i < 3; i++) {
|
||||||
if (rc < 0)
|
rc = xc2028_get_reg(priv, XREG_LOCK, &frq_lock);
|
||||||
goto ret;
|
if (rc < 0)
|
||||||
|
goto ret;
|
||||||
|
|
||||||
/* Frequency is locked */
|
if (frq_lock)
|
||||||
if (frq_lock == 1)
|
break;
|
||||||
signal = 1 << 11;
|
msleep(6);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Frequency didn't lock */
|
||||||
|
if (frq_lock == 2)
|
||||||
|
goto ret;
|
||||||
|
|
||||||
/* Get SNR of the video signal */
|
/* Get SNR of the video signal */
|
||||||
rc = xc2028_get_reg(priv, XREG_SNR, &signal);
|
rc = xc2028_get_reg(priv, XREG_SNR, &signal);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
/* Use both frq_lock and signal to generate the result */
|
/* Signal level is 3 bits only */
|
||||||
signal = signal || ((signal & 0x07) << 12);
|
|
||||||
|
signal = ((1 << 12) - 1) | ((signal & 0x07) << 12);
|
||||||
|
|
||||||
ret:
|
ret:
|
||||||
mutex_unlock(&priv->lock);
|
mutex_unlock(&priv->lock);
|
||||||
|
@ -926,6 +947,49 @@ ret:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int xc2028_get_afc(struct dvb_frontend *fe, s32 *afc)
|
||||||
|
{
|
||||||
|
struct xc2028_data *priv = fe->tuner_priv;
|
||||||
|
int i, rc;
|
||||||
|
u16 frq_lock = 0;
|
||||||
|
s16 afc_reg = 0;
|
||||||
|
|
||||||
|
rc = check_device_status(priv);
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
mutex_lock(&priv->lock);
|
||||||
|
|
||||||
|
/* Sync Lock Indicator */
|
||||||
|
for (i = 0; i < 3; i++) {
|
||||||
|
rc = xc2028_get_reg(priv, XREG_LOCK, &frq_lock);
|
||||||
|
if (rc < 0)
|
||||||
|
goto ret;
|
||||||
|
|
||||||
|
if (frq_lock)
|
||||||
|
break;
|
||||||
|
msleep(6);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Frequency didn't lock */
|
||||||
|
if (frq_lock == 2)
|
||||||
|
goto ret;
|
||||||
|
|
||||||
|
/* Get AFC */
|
||||||
|
rc = xc2028_get_reg(priv, XREG_FREQ_ERROR, &afc_reg);
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
*afc = afc_reg * 15625; /* Hz */
|
||||||
|
|
||||||
|
tuner_dbg("AFC is %d Hz\n", *afc);
|
||||||
|
|
||||||
|
ret:
|
||||||
|
mutex_unlock(&priv->lock);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
#define DIV 15625
|
#define DIV 15625
|
||||||
|
|
||||||
static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
|
static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
|
||||||
|
@ -1111,11 +1175,16 @@ static int xc2028_set_params(struct dvb_frontend *fe)
|
||||||
u32 delsys = c->delivery_system;
|
u32 delsys = c->delivery_system;
|
||||||
u32 bw = c->bandwidth_hz;
|
u32 bw = c->bandwidth_hz;
|
||||||
struct xc2028_data *priv = fe->tuner_priv;
|
struct xc2028_data *priv = fe->tuner_priv;
|
||||||
unsigned int type=0;
|
int rc;
|
||||||
|
unsigned int type = 0;
|
||||||
u16 demod = 0;
|
u16 demod = 0;
|
||||||
|
|
||||||
tuner_dbg("%s called\n", __func__);
|
tuner_dbg("%s called\n", __func__);
|
||||||
|
|
||||||
|
rc = check_device_status(priv);
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
switch (delsys) {
|
switch (delsys) {
|
||||||
case SYS_DVBT:
|
case SYS_DVBT:
|
||||||
case SYS_DVBT2:
|
case SYS_DVBT2:
|
||||||
|
@ -1201,7 +1270,11 @@ static int xc2028_set_params(struct dvb_frontend *fe)
|
||||||
static int xc2028_sleep(struct dvb_frontend *fe)
|
static int xc2028_sleep(struct dvb_frontend *fe)
|
||||||
{
|
{
|
||||||
struct xc2028_data *priv = fe->tuner_priv;
|
struct xc2028_data *priv = fe->tuner_priv;
|
||||||
int rc = 0;
|
int rc;
|
||||||
|
|
||||||
|
rc = check_device_status(priv);
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
/* Avoid firmware reload on slow devices or if PM disabled */
|
/* Avoid firmware reload on slow devices or if PM disabled */
|
||||||
if (no_poweroff || priv->ctrl.disable_power_mgmt)
|
if (no_poweroff || priv->ctrl.disable_power_mgmt)
|
||||||
|
@ -1220,7 +1293,7 @@ static int xc2028_sleep(struct dvb_frontend *fe)
|
||||||
else
|
else
|
||||||
rc = send_seq(priv, {0x80, XREG_POWER_DOWN, 0x00, 0x00});
|
rc = send_seq(priv, {0x80, XREG_POWER_DOWN, 0x00, 0x00});
|
||||||
|
|
||||||
priv->cur_fw.type = 0; /* need firmware reload */
|
priv->state = XC2028_SLEEP;
|
||||||
|
|
||||||
mutex_unlock(&priv->lock);
|
mutex_unlock(&priv->lock);
|
||||||
|
|
||||||
|
@ -1237,8 +1310,9 @@ static int xc2028_dvb_release(struct dvb_frontend *fe)
|
||||||
|
|
||||||
/* only perform final cleanup if this is the last instance */
|
/* only perform final cleanup if this is the last instance */
|
||||||
if (hybrid_tuner_report_instance_count(priv) == 1) {
|
if (hybrid_tuner_report_instance_count(priv) == 1) {
|
||||||
kfree(priv->ctrl.fname);
|
|
||||||
free_firmware(priv);
|
free_firmware(priv);
|
||||||
|
kfree(priv->ctrl.fname);
|
||||||
|
priv->ctrl.fname = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv)
|
if (priv)
|
||||||
|
@ -1254,14 +1328,42 @@ static int xc2028_dvb_release(struct dvb_frontend *fe)
|
||||||
static int xc2028_get_frequency(struct dvb_frontend *fe, u32 *frequency)
|
static int xc2028_get_frequency(struct dvb_frontend *fe, u32 *frequency)
|
||||||
{
|
{
|
||||||
struct xc2028_data *priv = fe->tuner_priv;
|
struct xc2028_data *priv = fe->tuner_priv;
|
||||||
|
int rc;
|
||||||
|
|
||||||
tuner_dbg("%s called\n", __func__);
|
tuner_dbg("%s called\n", __func__);
|
||||||
|
|
||||||
|
rc = check_device_status(priv);
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
*frequency = priv->frequency;
|
*frequency = priv->frequency;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void load_firmware_cb(const struct firmware *fw,
|
||||||
|
void *context)
|
||||||
|
{
|
||||||
|
struct dvb_frontend *fe = context;
|
||||||
|
struct xc2028_data *priv = fe->tuner_priv;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
tuner_dbg("request_firmware_nowait(): %s\n", fw ? "OK" : "error");
|
||||||
|
if (!fw) {
|
||||||
|
tuner_err("Could not load firmware %s.\n", priv->fname);
|
||||||
|
priv->state = XC2028_NODEV;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = load_all_firmwares(fe, fw);
|
||||||
|
|
||||||
|
release_firmware(fw);
|
||||||
|
|
||||||
|
if (rc < 0)
|
||||||
|
return;
|
||||||
|
priv->state = XC2028_SLEEP;
|
||||||
|
}
|
||||||
|
|
||||||
static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg)
|
static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg)
|
||||||
{
|
{
|
||||||
struct xc2028_data *priv = fe->tuner_priv;
|
struct xc2028_data *priv = fe->tuner_priv;
|
||||||
|
@ -1272,21 +1374,49 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg)
|
||||||
|
|
||||||
mutex_lock(&priv->lock);
|
mutex_lock(&priv->lock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy the config data.
|
||||||
|
* For the firmware name, keep a local copy of the string,
|
||||||
|
* in order to avoid troubles during device release.
|
||||||
|
*/
|
||||||
|
if (priv->ctrl.fname)
|
||||||
|
kfree(priv->ctrl.fname);
|
||||||
memcpy(&priv->ctrl, p, sizeof(priv->ctrl));
|
memcpy(&priv->ctrl, p, sizeof(priv->ctrl));
|
||||||
if (priv->ctrl.max_len < 9)
|
|
||||||
priv->ctrl.max_len = 13;
|
|
||||||
|
|
||||||
if (p->fname) {
|
if (p->fname) {
|
||||||
if (priv->ctrl.fname && strcmp(p->fname, priv->ctrl.fname)) {
|
|
||||||
kfree(priv->ctrl.fname);
|
|
||||||
free_firmware(priv);
|
|
||||||
}
|
|
||||||
|
|
||||||
priv->ctrl.fname = kstrdup(p->fname, GFP_KERNEL);
|
priv->ctrl.fname = kstrdup(p->fname, GFP_KERNEL);
|
||||||
if (priv->ctrl.fname == NULL)
|
if (priv->ctrl.fname == NULL)
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If firmware name changed, frees firmware. As free_firmware will
|
||||||
|
* reset the status to NO_FIRMWARE, this forces a new request_firmware
|
||||||
|
*/
|
||||||
|
if (!firmware_name[0] && p->fname &&
|
||||||
|
priv->fname && strcmp(p->fname, priv->fname))
|
||||||
|
free_firmware(priv);
|
||||||
|
|
||||||
|
if (priv->ctrl.max_len < 9)
|
||||||
|
priv->ctrl.max_len = 13;
|
||||||
|
|
||||||
|
if (priv->state == XC2028_NO_FIRMWARE) {
|
||||||
|
if (!firmware_name[0])
|
||||||
|
priv->fname = priv->ctrl.fname;
|
||||||
|
else
|
||||||
|
priv->fname = firmware_name;
|
||||||
|
|
||||||
|
rc = request_firmware_nowait(THIS_MODULE, 1,
|
||||||
|
priv->fname,
|
||||||
|
priv->i2c_props.adap->dev.parent,
|
||||||
|
GFP_KERNEL,
|
||||||
|
fe, load_firmware_cb);
|
||||||
|
if (rc < 0) {
|
||||||
|
tuner_err("Failed to request firmware %s\n",
|
||||||
|
priv->fname);
|
||||||
|
priv->state = XC2028_NODEV;
|
||||||
|
}
|
||||||
|
priv->state = XC2028_WAITING_FIRMWARE;
|
||||||
|
}
|
||||||
mutex_unlock(&priv->lock);
|
mutex_unlock(&priv->lock);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -1305,6 +1435,7 @@ static const struct dvb_tuner_ops xc2028_dvb_tuner_ops = {
|
||||||
.release = xc2028_dvb_release,
|
.release = xc2028_dvb_release,
|
||||||
.get_frequency = xc2028_get_frequency,
|
.get_frequency = xc2028_get_frequency,
|
||||||
.get_rf_strength = xc2028_signal,
|
.get_rf_strength = xc2028_signal,
|
||||||
|
.get_afc = xc2028_get_afc,
|
||||||
.set_params = xc2028_set_params,
|
.set_params = xc2028_set_params,
|
||||||
.sleep = xc2028_sleep,
|
.sleep = xc2028_sleep,
|
||||||
};
|
};
|
||||||
|
@ -1375,3 +1506,5 @@ MODULE_DESCRIPTION("Xceive xc2028/xc3028 tuner driver");
|
||||||
MODULE_AUTHOR("Michel Ludwig <michel.ludwig@gmail.com>");
|
MODULE_AUTHOR("Michel Ludwig <michel.ludwig@gmail.com>");
|
||||||
MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
|
MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
MODULE_FIRMWARE(XC2028_DEFAULT_FIRMWARE);
|
||||||
|
MODULE_FIRMWARE(XC3028L_DEFAULT_FIRMWARE);
|
||||||
|
|
|
@ -717,6 +717,12 @@ static int xc5000_set_params(struct dvb_frontend *fe)
|
||||||
priv->freq_hz = freq - 1750000;
|
priv->freq_hz = freq - 1750000;
|
||||||
priv->video_standard = DTV6;
|
priv->video_standard = DTV6;
|
||||||
break;
|
break;
|
||||||
|
case SYS_ISDBT:
|
||||||
|
/* All ISDB-T are currently for 6 MHz bw */
|
||||||
|
if (!bw)
|
||||||
|
bw = 6000000;
|
||||||
|
/* fall to OFDM handling */
|
||||||
|
case SYS_DMBTH:
|
||||||
case SYS_DVBT:
|
case SYS_DVBT:
|
||||||
case SYS_DVBT2:
|
case SYS_DVBT2:
|
||||||
dprintk(1, "%s() OFDM\n", __func__);
|
dprintk(1, "%s() OFDM\n", __func__);
|
||||||
|
|
|
@ -578,6 +578,7 @@ static int demod_attach_drxk(struct ddb_input *input)
|
||||||
|
|
||||||
memset(&config, 0, sizeof(config));
|
memset(&config, 0, sizeof(config));
|
||||||
config.microcode_name = "drxk_a3.mc";
|
config.microcode_name = "drxk_a3.mc";
|
||||||
|
config.qam_demod_parameter_count = 4;
|
||||||
config.adr = 0x29 + (input->nr & 1);
|
config.adr = 0x29 + (input->nr & 1);
|
||||||
|
|
||||||
fe = input->fe = dvb_attach(drxk_attach, &config, i2c);
|
fe = input->fe = dvb_attach(drxk_attach, &config, i2c);
|
||||||
|
|
|
@ -220,6 +220,7 @@ struct dvb_tuner_ops {
|
||||||
#define TUNER_STATUS_STEREO 2
|
#define TUNER_STATUS_STEREO 2
|
||||||
int (*get_status)(struct dvb_frontend *fe, u32 *status);
|
int (*get_status)(struct dvb_frontend *fe, u32 *status);
|
||||||
int (*get_rf_strength)(struct dvb_frontend *fe, u16 *strength);
|
int (*get_rf_strength)(struct dvb_frontend *fe, u16 *strength);
|
||||||
|
int (*get_afc)(struct dvb_frontend *fe, s32 *afc);
|
||||||
|
|
||||||
/** These are provided separately from set_params in order to facilitate silicon
|
/** These are provided separately from set_params in order to facilitate silicon
|
||||||
* tuners which require sophisticated tuning loops, controlling each parameter separately. */
|
* tuners which require sophisticated tuning loops, controlling each parameter separately. */
|
||||||
|
|
|
@ -418,9 +418,12 @@ config DVB_USB_RTL28XXU
|
||||||
tristate "Realtek RTL28xxU DVB USB support"
|
tristate "Realtek RTL28xxU DVB USB support"
|
||||||
depends on DVB_USB && EXPERIMENTAL
|
depends on DVB_USB && EXPERIMENTAL
|
||||||
select DVB_RTL2830
|
select DVB_RTL2830
|
||||||
|
select DVB_RTL2832
|
||||||
select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE
|
select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE
|
||||||
select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
|
select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
|
||||||
select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
|
select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
|
||||||
|
select MEDIA_TUNER_FC0012 if !MEDIA_TUNER_CUSTOMISE
|
||||||
|
select MEDIA_TUNER_FC0013 if !MEDIA_TUNER_CUSTOMISE
|
||||||
help
|
help
|
||||||
Say Y here to support the Realtek RTL28xxU DVB USB receiver.
|
Say Y here to support the Realtek RTL28xxU DVB USB receiver.
|
||||||
|
|
||||||
|
|
|
@ -593,9 +593,7 @@ static int az6007_read_mac_addr(struct dvb_usb_device *d, u8 mac[6])
|
||||||
memcpy(mac, st->data, sizeof(mac));
|
memcpy(mac, st->data, sizeof(mac));
|
||||||
|
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
deb_info("%s: mac is %02x:%02x:%02x:%02x:%02x:%02x\n",
|
deb_info("%s: mac is %pM\n", __func__, mac);
|
||||||
__func__, mac[0], mac[1], mac[2],
|
|
||||||
mac[3], mac[4], mac[5]);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,6 +100,7 @@
|
||||||
#define USB_PID_CONCEPTRONIC_CTVDIGRCU 0xe397
|
#define USB_PID_CONCEPTRONIC_CTVDIGRCU 0xe397
|
||||||
#define USB_PID_CONEXANT_D680_DMB 0x86d6
|
#define USB_PID_CONEXANT_D680_DMB 0x86d6
|
||||||
#define USB_PID_CREATIX_CTX1921 0x1921
|
#define USB_PID_CREATIX_CTX1921 0x1921
|
||||||
|
#define USB_PID_DELOCK_USB2_DVBT 0xb803
|
||||||
#define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064
|
#define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064
|
||||||
#define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065
|
#define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065
|
||||||
#define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8
|
#define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8
|
||||||
|
@ -160,6 +161,7 @@
|
||||||
#define USB_PID_TERRATEC_CINERGY_T_STICK 0x0093
|
#define USB_PID_TERRATEC_CINERGY_T_STICK 0x0093
|
||||||
#define USB_PID_TERRATEC_CINERGY_T_STICK_RC 0x0097
|
#define USB_PID_TERRATEC_CINERGY_T_STICK_RC 0x0097
|
||||||
#define USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC 0x0099
|
#define USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC 0x0099
|
||||||
|
#define USB_PID_TERRATEC_CINERGY_T_STICK_BLACK_REV1 0x00a9
|
||||||
#define USB_PID_TWINHAN_VP7041_COLD 0x3201
|
#define USB_PID_TWINHAN_VP7041_COLD 0x3201
|
||||||
#define USB_PID_TWINHAN_VP7041_WARM 0x3202
|
#define USB_PID_TWINHAN_VP7041_WARM 0x3202
|
||||||
#define USB_PID_TWINHAN_VP7020_COLD 0x3203
|
#define USB_PID_TWINHAN_VP7020_COLD 0x3203
|
||||||
|
@ -245,6 +247,7 @@
|
||||||
#define USB_PID_TERRATEC_H7_2 0x10a3
|
#define USB_PID_TERRATEC_H7_2 0x10a3
|
||||||
#define USB_PID_TERRATEC_T3 0x10a0
|
#define USB_PID_TERRATEC_T3 0x10a0
|
||||||
#define USB_PID_TERRATEC_T5 0x10a1
|
#define USB_PID_TERRATEC_T5 0x10a1
|
||||||
|
#define USB_PID_NOXON_DAB_STICK 0x00b3
|
||||||
#define USB_PID_PINNACLE_EXPRESSCARD_320CX 0x022e
|
#define USB_PID_PINNACLE_EXPRESSCARD_320CX 0x022e
|
||||||
#define USB_PID_PINNACLE_PCTV2000E 0x022c
|
#define USB_PID_PINNACLE_PCTV2000E 0x022c
|
||||||
#define USB_PID_PINNACLE_PCTV_DVB_T_FLASH 0x0228
|
#define USB_PID_PINNACLE_PCTV_DVB_T_FLASH 0x0228
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
|
* Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
|
||||||
* Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
|
* Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
|
||||||
|
* Copyright (C) 2012 Thomas Mair <thomas.mair86@googlemail.com>
|
||||||
*
|
*
|
||||||
* 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 as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -22,10 +23,13 @@
|
||||||
#include "rtl28xxu.h"
|
#include "rtl28xxu.h"
|
||||||
|
|
||||||
#include "rtl2830.h"
|
#include "rtl2830.h"
|
||||||
|
#include "rtl2832.h"
|
||||||
|
|
||||||
#include "qt1010.h"
|
#include "qt1010.h"
|
||||||
#include "mt2060.h"
|
#include "mt2060.h"
|
||||||
#include "mxl5005s.h"
|
#include "mxl5005s.h"
|
||||||
|
#include "fc0012.h"
|
||||||
|
#include "fc0013.h"
|
||||||
|
|
||||||
/* debug */
|
/* debug */
|
||||||
static int dvb_usb_rtl28xxu_debug;
|
static int dvb_usb_rtl28xxu_debug;
|
||||||
|
@ -80,7 +84,7 @@ err:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rtl2831_wr_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len)
|
static int rtl28xx_wr_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len)
|
||||||
{
|
{
|
||||||
struct rtl28xxu_req req;
|
struct rtl28xxu_req req;
|
||||||
|
|
||||||
|
@ -116,12 +120,12 @@ static int rtl2831_rd_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len)
|
||||||
return rtl28xxu_ctrl_msg(d, &req);
|
return rtl28xxu_ctrl_msg(d, &req);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rtl2831_wr_reg(struct dvb_usb_device *d, u16 reg, u8 val)
|
static int rtl28xx_wr_reg(struct dvb_usb_device *d, u16 reg, u8 val)
|
||||||
{
|
{
|
||||||
return rtl2831_wr_regs(d, reg, &val, 1);
|
return rtl28xx_wr_regs(d, reg, &val, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rtl2831_rd_reg(struct dvb_usb_device *d, u16 reg, u8 *val)
|
static int rtl28xx_rd_reg(struct dvb_usb_device *d, u16 reg, u8 *val)
|
||||||
{
|
{
|
||||||
return rtl2831_rd_regs(d, reg, val, 1);
|
return rtl2831_rd_regs(d, reg, val, 1);
|
||||||
}
|
}
|
||||||
|
@ -308,12 +312,12 @@ static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* GPIO direction */
|
/* GPIO direction */
|
||||||
ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_DIR, 0x0a);
|
ret = rtl28xx_wr_reg(adap->dev, SYS_GPIO_DIR, 0x0a);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
/* enable as output GPIO0, GPIO2, GPIO4 */
|
/* enable as output GPIO0, GPIO2, GPIO4 */
|
||||||
ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_OUT_EN, 0x15);
|
ret = rtl28xx_wr_reg(adap->dev, SYS_GPIO_OUT_EN, 0x15);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
@ -381,34 +385,159 @@ err:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct rtl2832_config rtl28xxu_rtl2832_fc0012_config = {
|
||||||
|
.i2c_addr = 0x10, /* 0x20 */
|
||||||
|
.xtal = 28800000,
|
||||||
|
.if_dvbt = 0,
|
||||||
|
.tuner = TUNER_RTL2832_FC0012
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct rtl2832_config rtl28xxu_rtl2832_fc0013_config = {
|
||||||
|
.i2c_addr = 0x10, /* 0x20 */
|
||||||
|
.xtal = 28800000,
|
||||||
|
.if_dvbt = 0,
|
||||||
|
.tuner = TUNER_RTL2832_FC0013
|
||||||
|
};
|
||||||
|
|
||||||
|
static int rtl2832u_fc0012_tuner_callback(struct dvb_usb_device *d,
|
||||||
|
int cmd, int arg)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
u8 val;
|
||||||
|
|
||||||
|
deb_info("%s cmd=%d arg=%d\n", __func__, cmd, arg);
|
||||||
|
switch (cmd) {
|
||||||
|
case FC_FE_CALLBACK_VHF_ENABLE:
|
||||||
|
/* set output values */
|
||||||
|
ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &val);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (arg)
|
||||||
|
val &= 0xbf; /* set GPIO6 low */
|
||||||
|
else
|
||||||
|
val |= 0x40; /* set GPIO6 high */
|
||||||
|
|
||||||
|
|
||||||
|
ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, val);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
err("%s: failed=%d\n", __func__, ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int rtl2832u_fc0013_tuner_callback(struct dvb_usb_device *d,
|
||||||
|
int cmd, int arg)
|
||||||
|
{
|
||||||
|
/* TODO implement*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtl2832u_tuner_callback(struct dvb_usb_device *d, int cmd, int arg)
|
||||||
|
{
|
||||||
|
struct rtl28xxu_priv *priv = d->priv;
|
||||||
|
|
||||||
|
switch (priv->tuner) {
|
||||||
|
case TUNER_RTL2832_FC0012:
|
||||||
|
return rtl2832u_fc0012_tuner_callback(d, cmd, arg);
|
||||||
|
|
||||||
|
case TUNER_RTL2832_FC0013:
|
||||||
|
return rtl2832u_fc0013_tuner_callback(d, cmd, arg);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtl2832u_frontend_callback(void *adapter_priv, int component,
|
||||||
|
int cmd, int arg)
|
||||||
|
{
|
||||||
|
struct i2c_adapter *adap = adapter_priv;
|
||||||
|
struct dvb_usb_device *d = i2c_get_adapdata(adap);
|
||||||
|
|
||||||
|
switch (component) {
|
||||||
|
case DVB_FRONTEND_COMPONENT_TUNER:
|
||||||
|
return rtl2832u_tuner_callback(d, cmd, arg);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
|
static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct rtl28xxu_priv *priv = adap->dev->priv;
|
struct rtl28xxu_priv *priv = adap->dev->priv;
|
||||||
u8 buf[1];
|
struct rtl2832_config *rtl2832_config;
|
||||||
|
|
||||||
|
u8 buf[2], val;
|
||||||
/* open RTL2832U/RTL2832 I2C gate */
|
/* open RTL2832U/RTL2832 I2C gate */
|
||||||
struct rtl28xxu_req req_gate_open = {0x0120, 0x0011, 0x0001, "\x18"};
|
struct rtl28xxu_req req_gate_open = {0x0120, 0x0011, 0x0001, "\x18"};
|
||||||
/* close RTL2832U/RTL2832 I2C gate */
|
/* close RTL2832U/RTL2832 I2C gate */
|
||||||
struct rtl28xxu_req req_gate_close = {0x0120, 0x0011, 0x0001, "\x10"};
|
struct rtl28xxu_req req_gate_close = {0x0120, 0x0011, 0x0001, "\x10"};
|
||||||
|
/* for FC0012 tuner probe */
|
||||||
|
struct rtl28xxu_req req_fc0012 = {0x00c6, CMD_I2C_RD, 1, buf};
|
||||||
|
/* for FC0013 tuner probe */
|
||||||
|
struct rtl28xxu_req req_fc0013 = {0x00c6, CMD_I2C_RD, 1, buf};
|
||||||
|
/* for MT2266 tuner probe */
|
||||||
|
struct rtl28xxu_req req_mt2266 = {0x00c0, CMD_I2C_RD, 1, buf};
|
||||||
/* for FC2580 tuner probe */
|
/* for FC2580 tuner probe */
|
||||||
struct rtl28xxu_req req_fc2580 = {0x01ac, CMD_I2C_RD, 1, buf};
|
struct rtl28xxu_req req_fc2580 = {0x01ac, CMD_I2C_RD, 1, buf};
|
||||||
|
/* for MT2063 tuner probe */
|
||||||
|
struct rtl28xxu_req req_mt2063 = {0x00c0, CMD_I2C_RD, 1, buf};
|
||||||
|
/* for MAX3543 tuner probe */
|
||||||
|
struct rtl28xxu_req req_max3543 = {0x00c0, CMD_I2C_RD, 1, buf};
|
||||||
|
/* for TUA9001 tuner probe */
|
||||||
|
struct rtl28xxu_req req_tua9001 = {0x7ec0, CMD_I2C_RD, 2, buf};
|
||||||
|
/* for MXL5007T tuner probe */
|
||||||
|
struct rtl28xxu_req req_mxl5007t = {0xd9c0, CMD_I2C_RD, 1, buf};
|
||||||
|
/* for E4000 tuner probe */
|
||||||
|
struct rtl28xxu_req req_e4000 = {0x02c8, CMD_I2C_RD, 1, buf};
|
||||||
|
/* for TDA18272 tuner probe */
|
||||||
|
struct rtl28xxu_req req_tda18272 = {0x00c0, CMD_I2C_RD, 2, buf};
|
||||||
|
|
||||||
deb_info("%s:\n", __func__);
|
deb_info("%s:\n", __func__);
|
||||||
|
|
||||||
/* GPIO direction */
|
|
||||||
ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_DIR, 0x0a);
|
ret = rtl28xx_rd_reg(adap->dev, SYS_GPIO_DIR, &val);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
/* enable as output GPIO0, GPIO2, GPIO4 */
|
val &= 0xbf;
|
||||||
ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_OUT_EN, 0x15);
|
|
||||||
|
ret = rtl28xx_wr_reg(adap->dev, SYS_GPIO_DIR, val);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
ret = rtl2831_wr_reg(adap->dev, SYS_DEMOD_CTL, 0xe8);
|
|
||||||
|
/* enable as output GPIO3 and GPIO6*/
|
||||||
|
ret = rtl28xx_rd_reg(adap->dev, SYS_GPIO_OUT_EN, &val);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
val |= 0x48;
|
||||||
|
|
||||||
|
ret = rtl28xx_wr_reg(adap->dev, SYS_GPIO_OUT_EN, val);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Probe used tuner. We need to know used tuner before demod attach
|
* Probe used tuner. We need to know used tuner before demod attach
|
||||||
* since there is some demod params needed to set according to tuner.
|
* since there is some demod params needed to set according to tuner.
|
||||||
|
@ -419,25 +548,108 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
priv->tuner = TUNER_NONE;
|
||||||
|
|
||||||
|
/* check FC0012 ID register; reg=00 val=a1 */
|
||||||
|
ret = rtl28xxu_ctrl_msg(adap->dev, &req_fc0012);
|
||||||
|
if (ret == 0 && buf[0] == 0xa1) {
|
||||||
|
priv->tuner = TUNER_RTL2832_FC0012;
|
||||||
|
rtl2832_config = &rtl28xxu_rtl2832_fc0012_config;
|
||||||
|
info("%s: FC0012 tuner found", __func__);
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check FC0013 ID register; reg=00 val=a3 */
|
||||||
|
ret = rtl28xxu_ctrl_msg(adap->dev, &req_fc0013);
|
||||||
|
if (ret == 0 && buf[0] == 0xa3) {
|
||||||
|
priv->tuner = TUNER_RTL2832_FC0013;
|
||||||
|
rtl2832_config = &rtl28xxu_rtl2832_fc0013_config;
|
||||||
|
info("%s: FC0013 tuner found", __func__);
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check MT2266 ID register; reg=00 val=85 */
|
||||||
|
ret = rtl28xxu_ctrl_msg(adap->dev, &req_mt2266);
|
||||||
|
if (ret == 0 && buf[0] == 0x85) {
|
||||||
|
priv->tuner = TUNER_RTL2832_MT2266;
|
||||||
|
/* TODO implement tuner */
|
||||||
|
info("%s: MT2266 tuner found", __func__);
|
||||||
|
goto unsupported;
|
||||||
|
}
|
||||||
|
|
||||||
/* check FC2580 ID register; reg=01 val=56 */
|
/* check FC2580 ID register; reg=01 val=56 */
|
||||||
ret = rtl28xxu_ctrl_msg(adap->dev, &req_fc2580);
|
ret = rtl28xxu_ctrl_msg(adap->dev, &req_fc2580);
|
||||||
if (ret == 0 && buf[0] == 0x56) {
|
if (ret == 0 && buf[0] == 0x56) {
|
||||||
priv->tuner = TUNER_RTL2832_FC2580;
|
priv->tuner = TUNER_RTL2832_FC2580;
|
||||||
deb_info("%s: FC2580\n", __func__);
|
/* TODO implement tuner */
|
||||||
goto found;
|
info("%s: FC2580 tuner found", __func__);
|
||||||
} else {
|
goto unsupported;
|
||||||
deb_info("%s: FC2580 probe failed=%d - %02x\n",
|
|
||||||
__func__, ret, buf[0]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check MT2063 ID register; reg=00 val=9e || 9c */
|
||||||
|
ret = rtl28xxu_ctrl_msg(adap->dev, &req_mt2063);
|
||||||
|
if (ret == 0 && (buf[0] == 0x9e || buf[0] == 0x9c)) {
|
||||||
|
priv->tuner = TUNER_RTL2832_MT2063;
|
||||||
|
/* TODO implement tuner */
|
||||||
|
info("%s: MT2063 tuner found", __func__);
|
||||||
|
goto unsupported;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check MAX3543 ID register; reg=00 val=38 */
|
||||||
|
ret = rtl28xxu_ctrl_msg(adap->dev, &req_max3543);
|
||||||
|
if (ret == 0 && buf[0] == 0x38) {
|
||||||
|
priv->tuner = TUNER_RTL2832_MAX3543;
|
||||||
|
/* TODO implement tuner */
|
||||||
|
info("%s: MAX3534 tuner found", __func__);
|
||||||
|
goto unsupported;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check TUA9001 ID register; reg=7e val=2328 */
|
||||||
|
ret = rtl28xxu_ctrl_msg(adap->dev, &req_tua9001);
|
||||||
|
if (ret == 0 && buf[0] == 0x23 && buf[1] == 0x28) {
|
||||||
|
priv->tuner = TUNER_RTL2832_TUA9001;
|
||||||
|
/* TODO implement tuner */
|
||||||
|
info("%s: TUA9001 tuner found", __func__);
|
||||||
|
goto unsupported;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check MXL5007R ID register; reg=d9 val=14 */
|
||||||
|
ret = rtl28xxu_ctrl_msg(adap->dev, &req_mxl5007t);
|
||||||
|
if (ret == 0 && buf[0] == 0x14) {
|
||||||
|
priv->tuner = TUNER_RTL2832_MXL5007T;
|
||||||
|
/* TODO implement tuner */
|
||||||
|
info("%s: MXL5007T tuner found", __func__);
|
||||||
|
goto unsupported;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check E4000 ID register; reg=02 val=40 */
|
||||||
|
ret = rtl28xxu_ctrl_msg(adap->dev, &req_e4000);
|
||||||
|
if (ret == 0 && buf[0] == 0x40) {
|
||||||
|
priv->tuner = TUNER_RTL2832_E4000;
|
||||||
|
/* TODO implement tuner */
|
||||||
|
info("%s: E4000 tuner found", __func__);
|
||||||
|
goto unsupported;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check TDA18272 ID register; reg=00 val=c760 */
|
||||||
|
ret = rtl28xxu_ctrl_msg(adap->dev, &req_tda18272);
|
||||||
|
if (ret == 0 && (buf[0] == 0xc7 || buf[1] == 0x60)) {
|
||||||
|
priv->tuner = TUNER_RTL2832_TDA18272;
|
||||||
|
/* TODO implement tuner */
|
||||||
|
info("%s: TDA18272 tuner found", __func__);
|
||||||
|
goto unsupported;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsupported:
|
||||||
/* close demod I2C gate */
|
/* close demod I2C gate */
|
||||||
ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate_close);
|
ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate_close);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
/* tuner not found */
|
/* tuner not found */
|
||||||
|
deb_info("No compatible tuner found");
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
goto err;
|
return ret;
|
||||||
|
|
||||||
found:
|
found:
|
||||||
/* close demod I2C gate */
|
/* close demod I2C gate */
|
||||||
|
@ -446,9 +658,18 @@ found:
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
/* attach demodulator */
|
/* attach demodulator */
|
||||||
/* TODO: */
|
adap->fe_adap[0].fe = dvb_attach(rtl2832_attach, rtl2832_config,
|
||||||
|
&adap->dev->i2c_adap);
|
||||||
|
if (adap->fe_adap[0].fe == NULL) {
|
||||||
|
ret = -ENODEV;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set fe callbacks */
|
||||||
|
adap->fe_adap[0].fe->callback = rtl2832u_frontend_callback;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
deb_info("%s: failed=%d\n", __func__, ret);
|
deb_info("%s: failed=%d\n", __func__, ret);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -531,10 +752,24 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
|
||||||
deb_info("%s:\n", __func__);
|
deb_info("%s:\n", __func__);
|
||||||
|
|
||||||
switch (priv->tuner) {
|
switch (priv->tuner) {
|
||||||
case TUNER_RTL2832_FC2580:
|
case TUNER_RTL2832_FC0012:
|
||||||
/* TODO: */
|
fe = dvb_attach(fc0012_attach, adap->fe_adap[0].fe,
|
||||||
fe = NULL;
|
&adap->dev->i2c_adap, 0xc6>>1, 0, FC_XTAL_28_8_MHZ);
|
||||||
|
|
||||||
|
/* since fc0012 includs reading the signal strength delegate
|
||||||
|
* that to the tuner driver */
|
||||||
|
adap->fe_adap[0].fe->ops.read_signal_strength = adap->fe_adap[0].
|
||||||
|
fe->ops.tuner_ops.get_rf_strength;
|
||||||
|
return 0;
|
||||||
break;
|
break;
|
||||||
|
case TUNER_RTL2832_FC0013:
|
||||||
|
fe = dvb_attach(fc0013_attach, adap->fe_adap[0].fe,
|
||||||
|
&adap->dev->i2c_adap, 0xc6>>1, 0, FC_XTAL_28_8_MHZ);
|
||||||
|
|
||||||
|
/* fc0013 also supports signal strength reading */
|
||||||
|
adap->fe_adap[0].fe->ops.read_signal_strength = adap->fe_adap[0]
|
||||||
|
.fe->ops.tuner_ops.get_rf_strength;
|
||||||
|
return 0;
|
||||||
default:
|
default:
|
||||||
fe = NULL;
|
fe = NULL;
|
||||||
err("unknown tuner=%d", priv->tuner);
|
err("unknown tuner=%d", priv->tuner);
|
||||||
|
@ -551,14 +786,14 @@ err:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rtl28xxu_streaming_ctrl(struct dvb_usb_adapter *adap , int onoff)
|
static int rtl2831u_streaming_ctrl(struct dvb_usb_adapter *adap , int onoff)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
u8 buf[2], gpio;
|
u8 buf[2], gpio;
|
||||||
|
|
||||||
deb_info("%s: onoff=%d\n", __func__, onoff);
|
deb_info("%s: onoff=%d\n", __func__, onoff);
|
||||||
|
|
||||||
ret = rtl2831_rd_reg(adap->dev, SYS_GPIO_OUT_VAL, &gpio);
|
ret = rtl28xx_rd_reg(adap->dev, SYS_GPIO_OUT_VAL, &gpio);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
@ -572,11 +807,11 @@ static int rtl28xxu_streaming_ctrl(struct dvb_usb_adapter *adap , int onoff)
|
||||||
gpio &= (~0x04); /* LED off */
|
gpio &= (~0x04); /* LED off */
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_OUT_VAL, gpio);
|
ret = rtl28xx_wr_reg(adap->dev, SYS_GPIO_OUT_VAL, gpio);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
ret = rtl2831_wr_regs(adap->dev, USB_EPA_CTL, buf, 2);
|
ret = rtl28xx_wr_regs(adap->dev, USB_EPA_CTL, buf, 2);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
@ -586,7 +821,33 @@ err:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rtl28xxu_power_ctrl(struct dvb_usb_device *d, int onoff)
|
static int rtl2832u_streaming_ctrl(struct dvb_usb_adapter *adap , int onoff)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
u8 buf[2];
|
||||||
|
|
||||||
|
deb_info("%s: onoff=%d\n", __func__, onoff);
|
||||||
|
|
||||||
|
|
||||||
|
if (onoff) {
|
||||||
|
buf[0] = 0x00;
|
||||||
|
buf[1] = 0x00;
|
||||||
|
} else {
|
||||||
|
buf[0] = 0x10; /* stall EPA */
|
||||||
|
buf[1] = 0x02; /* reset EPA */
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = rtl28xx_wr_regs(adap->dev, USB_EPA_CTL, buf, 2);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
err:
|
||||||
|
deb_info("%s: failed=%d\n", __func__, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtl2831u_power_ctrl(struct dvb_usb_device *d, int onoff)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
u8 gpio, sys0;
|
u8 gpio, sys0;
|
||||||
|
@ -594,12 +855,12 @@ static int rtl28xxu_power_ctrl(struct dvb_usb_device *d, int onoff)
|
||||||
deb_info("%s: onoff=%d\n", __func__, onoff);
|
deb_info("%s: onoff=%d\n", __func__, onoff);
|
||||||
|
|
||||||
/* demod adc */
|
/* demod adc */
|
||||||
ret = rtl2831_rd_reg(d, SYS_SYS0, &sys0);
|
ret = rtl28xx_rd_reg(d, SYS_SYS0, &sys0);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
/* tuner power, read GPIOs */
|
/* tuner power, read GPIOs */
|
||||||
ret = rtl2831_rd_reg(d, SYS_GPIO_OUT_VAL, &gpio);
|
ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &gpio);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
@ -619,12 +880,12 @@ static int rtl28xxu_power_ctrl(struct dvb_usb_device *d, int onoff)
|
||||||
deb_info("%s: WR SYS0=%02x GPIO_OUT_VAL=%02x\n", __func__, sys0, gpio);
|
deb_info("%s: WR SYS0=%02x GPIO_OUT_VAL=%02x\n", __func__, sys0, gpio);
|
||||||
|
|
||||||
/* demod adc */
|
/* demod adc */
|
||||||
ret = rtl2831_wr_reg(d, SYS_SYS0, sys0);
|
ret = rtl28xx_wr_reg(d, SYS_SYS0, sys0);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
/* tuner power, write GPIOs */
|
/* tuner power, write GPIOs */
|
||||||
ret = rtl2831_wr_reg(d, SYS_GPIO_OUT_VAL, gpio);
|
ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, gpio);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
@ -634,6 +895,128 @@ err:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int rtl2832u_power_ctrl(struct dvb_usb_device *d, int onoff)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
u8 val;
|
||||||
|
|
||||||
|
deb_info("%s: onoff=%d\n", __func__, onoff);
|
||||||
|
|
||||||
|
if (onoff) {
|
||||||
|
/* set output values */
|
||||||
|
ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &val);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
val |= 0x08;
|
||||||
|
val &= 0xef;
|
||||||
|
|
||||||
|
ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, val);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/* demod_ctl_1 */
|
||||||
|
ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL1, &val);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
val &= 0xef;
|
||||||
|
|
||||||
|
ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL1, val);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/* demod control */
|
||||||
|
/* PLL enable */
|
||||||
|
ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/* bit 7 to 1 */
|
||||||
|
val |= 0x80;
|
||||||
|
|
||||||
|
ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/* demod HW reset */
|
||||||
|
ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
/* bit 5 to 0 */
|
||||||
|
val &= 0xdf;
|
||||||
|
|
||||||
|
ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
val |= 0x20;
|
||||||
|
|
||||||
|
ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
mdelay(5);
|
||||||
|
|
||||||
|
/*enable ADC_Q and ADC_I */
|
||||||
|
ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
val |= 0x48;
|
||||||
|
|
||||||
|
ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* demod_ctl_1 */
|
||||||
|
ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL1, &val);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
val |= 0x0c;
|
||||||
|
|
||||||
|
ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL1, val);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/* set output values */
|
||||||
|
ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &val);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
val |= 0x10;
|
||||||
|
|
||||||
|
ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, val);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/* demod control */
|
||||||
|
ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
val &= 0x37;
|
||||||
|
|
||||||
|
ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
err:
|
||||||
|
deb_info("%s: failed=%d\n", __func__, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int rtl2831u_rc_query(struct dvb_usb_device *d)
|
static int rtl2831u_rc_query(struct dvb_usb_device *d)
|
||||||
{
|
{
|
||||||
int ret, i;
|
int ret, i;
|
||||||
|
@ -660,7 +1043,7 @@ static int rtl2831u_rc_query(struct dvb_usb_device *d)
|
||||||
/* init remote controller */
|
/* init remote controller */
|
||||||
if (!priv->rc_active) {
|
if (!priv->rc_active) {
|
||||||
for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) {
|
for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) {
|
||||||
ret = rtl2831_wr_reg(d, rc_nec_tab[i].reg,
|
ret = rtl28xx_wr_reg(d, rc_nec_tab[i].reg,
|
||||||
rc_nec_tab[i].val);
|
rc_nec_tab[i].val);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -690,12 +1073,12 @@ static int rtl2831u_rc_query(struct dvb_usb_device *d)
|
||||||
|
|
||||||
rc_keydown(d->rc_dev, rc_code, 0);
|
rc_keydown(d->rc_dev, rc_code, 0);
|
||||||
|
|
||||||
ret = rtl2831_wr_reg(d, SYS_IRRC_SR, 1);
|
ret = rtl28xx_wr_reg(d, SYS_IRRC_SR, 1);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
/* repeated intentionally to avoid extra keypress */
|
/* repeated intentionally to avoid extra keypress */
|
||||||
ret = rtl2831_wr_reg(d, SYS_IRRC_SR, 1);
|
ret = rtl28xx_wr_reg(d, SYS_IRRC_SR, 1);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
@ -732,7 +1115,7 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d)
|
||||||
/* init remote controller */
|
/* init remote controller */
|
||||||
if (!priv->rc_active) {
|
if (!priv->rc_active) {
|
||||||
for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) {
|
for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) {
|
||||||
ret = rtl2831_wr_reg(d, rc_nec_tab[i].reg,
|
ret = rtl28xx_wr_reg(d, rc_nec_tab[i].reg,
|
||||||
rc_nec_tab[i].val);
|
rc_nec_tab[i].val);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -740,14 +1123,14 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d)
|
||||||
priv->rc_active = true;
|
priv->rc_active = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = rtl2831_rd_reg(d, IR_RX_IF, &buf[0]);
|
ret = rtl28xx_rd_reg(d, IR_RX_IF, &buf[0]);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (buf[0] != 0x83)
|
if (buf[0] != 0x83)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
ret = rtl2831_rd_reg(d, IR_RX_BC, &buf[0]);
|
ret = rtl28xx_rd_reg(d, IR_RX_BC, &buf[0]);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
@ -756,9 +1139,9 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d)
|
||||||
|
|
||||||
/* TODO: pass raw IR to Kernel IR decoder */
|
/* TODO: pass raw IR to Kernel IR decoder */
|
||||||
|
|
||||||
ret = rtl2831_wr_reg(d, IR_RX_IF, 0x03);
|
ret = rtl28xx_wr_reg(d, IR_RX_IF, 0x03);
|
||||||
ret = rtl2831_wr_reg(d, IR_RX_BUF_CTRL, 0x80);
|
ret = rtl28xx_wr_reg(d, IR_RX_BUF_CTRL, 0x80);
|
||||||
ret = rtl2831_wr_reg(d, IR_RX_CTRL, 0x80);
|
ret = rtl28xx_wr_reg(d, IR_RX_CTRL, 0x80);
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -771,6 +1154,9 @@ enum rtl28xxu_usb_table_entry {
|
||||||
RTL2831U_0BDA_2831,
|
RTL2831U_0BDA_2831,
|
||||||
RTL2831U_14AA_0160,
|
RTL2831U_14AA_0160,
|
||||||
RTL2831U_14AA_0161,
|
RTL2831U_14AA_0161,
|
||||||
|
RTL2832U_0CCD_00A9,
|
||||||
|
RTL2832U_1F4D_B803,
|
||||||
|
RTL2832U_0CCD_00B3,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct usb_device_id rtl28xxu_table[] = {
|
static struct usb_device_id rtl28xxu_table[] = {
|
||||||
|
@ -783,6 +1169,12 @@ static struct usb_device_id rtl28xxu_table[] = {
|
||||||
USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT_2)},
|
USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT_2)},
|
||||||
|
|
||||||
/* RTL2832U */
|
/* RTL2832U */
|
||||||
|
[RTL2832U_0CCD_00A9] = {
|
||||||
|
USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_BLACK_REV1)},
|
||||||
|
[RTL2832U_1F4D_B803] = {
|
||||||
|
USB_DEVICE(USB_VID_GTEK, USB_PID_DELOCK_USB2_DVBT)},
|
||||||
|
[RTL2832U_0CCD_00B3] = {
|
||||||
|
USB_DEVICE(USB_VID_TERRATEC, USB_PID_NOXON_DAB_STICK)},
|
||||||
{} /* terminating entry */
|
{} /* terminating entry */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -805,7 +1197,7 @@ static struct dvb_usb_device_properties rtl28xxu_properties[] = {
|
||||||
{
|
{
|
||||||
.frontend_attach = rtl2831u_frontend_attach,
|
.frontend_attach = rtl2831u_frontend_attach,
|
||||||
.tuner_attach = rtl2831u_tuner_attach,
|
.tuner_attach = rtl2831u_tuner_attach,
|
||||||
.streaming_ctrl = rtl28xxu_streaming_ctrl,
|
.streaming_ctrl = rtl2831u_streaming_ctrl,
|
||||||
.stream = {
|
.stream = {
|
||||||
.type = USB_BULK,
|
.type = USB_BULK,
|
||||||
.count = 6,
|
.count = 6,
|
||||||
|
@ -821,7 +1213,7 @@ static struct dvb_usb_device_properties rtl28xxu_properties[] = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
.power_ctrl = rtl28xxu_power_ctrl,
|
.power_ctrl = rtl2831u_power_ctrl,
|
||||||
|
|
||||||
.rc.core = {
|
.rc.core = {
|
||||||
.protocol = RC_TYPE_NEC,
|
.protocol = RC_TYPE_NEC,
|
||||||
|
@ -867,7 +1259,7 @@ static struct dvb_usb_device_properties rtl28xxu_properties[] = {
|
||||||
{
|
{
|
||||||
.frontend_attach = rtl2832u_frontend_attach,
|
.frontend_attach = rtl2832u_frontend_attach,
|
||||||
.tuner_attach = rtl2832u_tuner_attach,
|
.tuner_attach = rtl2832u_tuner_attach,
|
||||||
.streaming_ctrl = rtl28xxu_streaming_ctrl,
|
.streaming_ctrl = rtl2832u_streaming_ctrl,
|
||||||
.stream = {
|
.stream = {
|
||||||
.type = USB_BULK,
|
.type = USB_BULK,
|
||||||
.count = 6,
|
.count = 6,
|
||||||
|
@ -883,7 +1275,7 @@ static struct dvb_usb_device_properties rtl28xxu_properties[] = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
.power_ctrl = rtl28xxu_power_ctrl,
|
.power_ctrl = rtl2832u_power_ctrl,
|
||||||
|
|
||||||
.rc.core = {
|
.rc.core = {
|
||||||
.protocol = RC_TYPE_NEC,
|
.protocol = RC_TYPE_NEC,
|
||||||
|
@ -896,10 +1288,25 @@ static struct dvb_usb_device_properties rtl28xxu_properties[] = {
|
||||||
|
|
||||||
.i2c_algo = &rtl28xxu_i2c_algo,
|
.i2c_algo = &rtl28xxu_i2c_algo,
|
||||||
|
|
||||||
.num_device_descs = 0, /* disabled as no support for RTL2832 */
|
.num_device_descs = 3,
|
||||||
.devices = {
|
.devices = {
|
||||||
{
|
{
|
||||||
.name = "Realtek RTL2832U reference design",
|
.name = "Terratec Cinergy T Stick Black",
|
||||||
|
.warm_ids = {
|
||||||
|
&rtl28xxu_table[RTL2832U_0CCD_00A9],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "G-Tek Electronics Group Lifeview LV5TDLX DVB-T",
|
||||||
|
.warm_ids = {
|
||||||
|
&rtl28xxu_table[RTL2832U_1F4D_B803],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "NOXON DAB/DAB+ USB dongle",
|
||||||
|
.warm_ids = {
|
||||||
|
&rtl28xxu_table[RTL2832U_0CCD_00B3],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -910,6 +1317,7 @@ static int rtl28xxu_probe(struct usb_interface *intf,
|
||||||
const struct usb_device_id *id)
|
const struct usb_device_id *id)
|
||||||
{
|
{
|
||||||
int ret, i;
|
int ret, i;
|
||||||
|
u8 val;
|
||||||
int properties_count = ARRAY_SIZE(rtl28xxu_properties);
|
int properties_count = ARRAY_SIZE(rtl28xxu_properties);
|
||||||
struct dvb_usb_device *d;
|
struct dvb_usb_device *d;
|
||||||
struct usb_device *udev;
|
struct usb_device *udev;
|
||||||
|
@ -954,16 +1362,25 @@ static int rtl28xxu_probe(struct usb_interface *intf,
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
|
||||||
/* init USB endpoints */
|
/* init USB endpoints */
|
||||||
ret = rtl2831_wr_reg(d, USB_SYSCTL_0, 0x09);
|
ret = rtl28xx_rd_reg(d, USB_SYSCTL_0, &val);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/* enable DMA and Full Packet Mode*/
|
||||||
|
val |= 0x09;
|
||||||
|
ret = rtl28xx_wr_reg(d, USB_SYSCTL_0, val);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
ret = rtl2831_wr_regs(d, USB_EPA_MAXPKT, "\x00\x02\x00\x00", 4);
|
/* set EPA maximum packet size to 0x0200 */
|
||||||
|
ret = rtl28xx_wr_regs(d, USB_EPA_MAXPKT, "\x00\x02\x00\x00", 4);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
ret = rtl2831_wr_regs(d, USB_EPA_FIFO_CFG, "\x14\x00\x00\x00", 4);
|
/* change EPA FIFO length */
|
||||||
|
ret = rtl28xx_wr_regs(d, USB_EPA_FIFO_CFG, "\x14\x00\x00\x00", 4);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
@ -1007,4 +1424,5 @@ module_exit(rtl28xxu_module_exit);
|
||||||
|
|
||||||
MODULE_DESCRIPTION("Realtek RTL28xxU DVB USB driver");
|
MODULE_DESCRIPTION("Realtek RTL28xxU DVB USB driver");
|
||||||
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
|
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
|
||||||
|
MODULE_AUTHOR("Thomas Mair <thomas.mair86@googlemail.com>");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
config DVB_FE_CUSTOMISE
|
config DVB_FE_CUSTOMISE
|
||||||
bool "Customise the frontend modules to build"
|
bool "Customise the frontend modules to build"
|
||||||
depends on DVB_CORE
|
depends on DVB_CORE
|
||||||
|
depends on EXPERT
|
||||||
default y if EXPERT
|
default y if EXPERT
|
||||||
help
|
help
|
||||||
This allows the user to select/deselect frontend drivers for their
|
This allows the user to select/deselect frontend drivers for their
|
||||||
|
@ -432,6 +433,13 @@ config DVB_RTL2830
|
||||||
help
|
help
|
||||||
Say Y when you want to support this frontend.
|
Say Y when you want to support this frontend.
|
||||||
|
|
||||||
|
config DVB_RTL2832
|
||||||
|
tristate "Realtek RTL2832 DVB-T"
|
||||||
|
depends on DVB_CORE && I2C
|
||||||
|
default m if DVB_FE_CUSTOMISE
|
||||||
|
help
|
||||||
|
Say Y when you want to support this frontend.
|
||||||
|
|
||||||
comment "DVB-C (cable) frontends"
|
comment "DVB-C (cable) frontends"
|
||||||
depends on DVB_CORE
|
depends on DVB_CORE
|
||||||
|
|
||||||
|
|
|
@ -99,6 +99,7 @@ obj-$(CONFIG_DVB_IT913X_FE) += it913x-fe.o
|
||||||
obj-$(CONFIG_DVB_A8293) += a8293.o
|
obj-$(CONFIG_DVB_A8293) += a8293.o
|
||||||
obj-$(CONFIG_DVB_TDA10071) += tda10071.o
|
obj-$(CONFIG_DVB_TDA10071) += tda10071.o
|
||||||
obj-$(CONFIG_DVB_RTL2830) += rtl2830.o
|
obj-$(CONFIG_DVB_RTL2830) += rtl2830.o
|
||||||
|
obj-$(CONFIG_DVB_RTL2832) += rtl2832.o
|
||||||
obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o
|
obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o
|
||||||
obj-$(CONFIG_DVB_AF9033) += af9033.o
|
obj-$(CONFIG_DVB_AF9033) += af9033.o
|
||||||
|
|
||||||
|
|
|
@ -21,24 +21,6 @@
|
||||||
#include "dvb_frontend.h"
|
#include "dvb_frontend.h"
|
||||||
#include "a8293.h"
|
#include "a8293.h"
|
||||||
|
|
||||||
static int debug;
|
|
||||||
module_param(debug, int, 0644);
|
|
||||||
MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
|
|
||||||
|
|
||||||
#define LOG_PREFIX "a8293"
|
|
||||||
|
|
||||||
#undef dbg
|
|
||||||
#define dbg(f, arg...) \
|
|
||||||
if (debug) \
|
|
||||||
printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg)
|
|
||||||
#undef err
|
|
||||||
#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg)
|
|
||||||
#undef info
|
|
||||||
#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg)
|
|
||||||
#undef warn
|
|
||||||
#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
|
|
||||||
|
|
||||||
|
|
||||||
struct a8293_priv {
|
struct a8293_priv {
|
||||||
struct i2c_adapter *i2c;
|
struct i2c_adapter *i2c;
|
||||||
const struct a8293_config *cfg;
|
const struct a8293_config *cfg;
|
||||||
|
@ -65,7 +47,8 @@ static int a8293_i2c(struct a8293_priv *priv, u8 *val, int len, bool rd)
|
||||||
if (ret == 1) {
|
if (ret == 1) {
|
||||||
ret = 0;
|
ret = 0;
|
||||||
} else {
|
} else {
|
||||||
warn("i2c failed=%d rd=%d", ret, rd);
|
dev_warn(&priv->i2c->dev, "%s: i2c failed=%d rd=%d\n",
|
||||||
|
KBUILD_MODNAME, ret, rd);
|
||||||
ret = -EREMOTEIO;
|
ret = -EREMOTEIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +71,8 @@ static int a8293_set_voltage(struct dvb_frontend *fe,
|
||||||
struct a8293_priv *priv = fe->sec_priv;
|
struct a8293_priv *priv = fe->sec_priv;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
dbg("%s: fe_sec_voltage=%d", __func__, fe_sec_voltage);
|
dev_dbg(&priv->i2c->dev, "%s: fe_sec_voltage=%d\n", __func__,
|
||||||
|
fe_sec_voltage);
|
||||||
|
|
||||||
switch (fe_sec_voltage) {
|
switch (fe_sec_voltage) {
|
||||||
case SEC_VOLTAGE_OFF:
|
case SEC_VOLTAGE_OFF:
|
||||||
|
@ -114,14 +98,12 @@ static int a8293_set_voltage(struct dvb_frontend *fe,
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
err:
|
err:
|
||||||
dbg("%s: failed=%d", __func__, ret);
|
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void a8293_release_sec(struct dvb_frontend *fe)
|
static void a8293_release_sec(struct dvb_frontend *fe)
|
||||||
{
|
{
|
||||||
dbg("%s:", __func__);
|
|
||||||
|
|
||||||
a8293_set_voltage(fe, SEC_VOLTAGE_OFF);
|
a8293_set_voltage(fe, SEC_VOLTAGE_OFF);
|
||||||
|
|
||||||
kfree(fe->sec_priv);
|
kfree(fe->sec_priv);
|
||||||
|
@ -154,7 +136,7 @@ struct dvb_frontend *a8293_attach(struct dvb_frontend *fe,
|
||||||
|
|
||||||
/* ENB=0 */
|
/* ENB=0 */
|
||||||
priv->reg[0] = 0x10;
|
priv->reg[0] = 0x10;
|
||||||
ret = a8293_wr(priv, &priv->reg[1], 1);
|
ret = a8293_wr(priv, &priv->reg[0], 1);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
@ -164,16 +146,17 @@ struct dvb_frontend *a8293_attach(struct dvb_frontend *fe,
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
info("Allegro A8293 SEC attached.");
|
|
||||||
|
|
||||||
fe->ops.release_sec = a8293_release_sec;
|
fe->ops.release_sec = a8293_release_sec;
|
||||||
|
|
||||||
/* override frontend ops */
|
/* override frontend ops */
|
||||||
fe->ops.set_voltage = a8293_set_voltage;
|
fe->ops.set_voltage = a8293_set_voltage;
|
||||||
|
|
||||||
|
dev_info(&priv->i2c->dev, "%s: Allegro A8293 SEC attached\n",
|
||||||
|
KBUILD_MODNAME);
|
||||||
|
|
||||||
return fe;
|
return fe;
|
||||||
err:
|
err:
|
||||||
dbg("%s: failed=%d", __func__, ret);
|
dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||||
kfree(priv);
|
kfree(priv);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,14 @@
|
||||||
* means that 1=DVBC, 0 = DVBT. Zero means the opposite.
|
* means that 1=DVBC, 0 = DVBT. Zero means the opposite.
|
||||||
* @mpeg_out_clk_strength: DRXK Mpeg output clock drive strength.
|
* @mpeg_out_clk_strength: DRXK Mpeg output clock drive strength.
|
||||||
* @microcode_name: Name of the firmware file with the microcode
|
* @microcode_name: Name of the firmware file with the microcode
|
||||||
|
* @qam_demod_parameter_count: The number of parameters used for the command
|
||||||
|
* to set the demodulator parameters. All
|
||||||
|
* firmwares are using the 2-parameter commmand.
|
||||||
|
* An exception is the "drxk_a3.mc" firmware,
|
||||||
|
* which uses the 4-parameter command.
|
||||||
|
* A value of 0 (default) or lower indicates that
|
||||||
|
* the correct number of parameters will be
|
||||||
|
* automatically detected.
|
||||||
*
|
*
|
||||||
* On the *_gpio vars, bit 0 is UIO-1, bit 1 is UIO-2 and bit 2 is
|
* On the *_gpio vars, bit 0 is UIO-1, bit 1 is UIO-2 and bit 2 is
|
||||||
* UIO-3.
|
* UIO-3.
|
||||||
|
@ -38,7 +46,8 @@ struct drxk_config {
|
||||||
u8 mpeg_out_clk_strength;
|
u8 mpeg_out_clk_strength;
|
||||||
int chunk_size;
|
int chunk_size;
|
||||||
|
|
||||||
const char *microcode_name;
|
const char *microcode_name;
|
||||||
|
int qam_demod_parameter_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(CONFIG_DVB_DRXK) || (defined(CONFIG_DVB_DRXK_MODULE) \
|
#if defined(CONFIG_DVB_DRXK) || (defined(CONFIG_DVB_DRXK_MODULE) \
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/firmware.h>
|
#include <linux/firmware.h>
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
|
#include <linux/hardirq.h>
|
||||||
#include <asm/div64.h>
|
#include <asm/div64.h>
|
||||||
|
|
||||||
#include "dvb_frontend.h"
|
#include "dvb_frontend.h"
|
||||||
|
@ -308,16 +309,42 @@ static u32 Log10Times100(u32 x)
|
||||||
/* I2C **********************************************************************/
|
/* I2C **********************************************************************/
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
|
|
||||||
static int i2c_read1(struct i2c_adapter *adapter, u8 adr, u8 *val)
|
static int drxk_i2c_lock(struct drxk_state *state)
|
||||||
|
{
|
||||||
|
i2c_lock_adapter(state->i2c);
|
||||||
|
state->drxk_i2c_exclusive_lock = true;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drxk_i2c_unlock(struct drxk_state *state)
|
||||||
|
{
|
||||||
|
if (!state->drxk_i2c_exclusive_lock)
|
||||||
|
return;
|
||||||
|
|
||||||
|
i2c_unlock_adapter(state->i2c);
|
||||||
|
state->drxk_i2c_exclusive_lock = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int drxk_i2c_transfer(struct drxk_state *state, struct i2c_msg *msgs,
|
||||||
|
unsigned len)
|
||||||
|
{
|
||||||
|
if (state->drxk_i2c_exclusive_lock)
|
||||||
|
return __i2c_transfer(state->i2c, msgs, len);
|
||||||
|
else
|
||||||
|
return i2c_transfer(state->i2c, msgs, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int i2c_read1(struct drxk_state *state, u8 adr, u8 *val)
|
||||||
{
|
{
|
||||||
struct i2c_msg msgs[1] = { {.addr = adr, .flags = I2C_M_RD,
|
struct i2c_msg msgs[1] = { {.addr = adr, .flags = I2C_M_RD,
|
||||||
.buf = val, .len = 1}
|
.buf = val, .len = 1}
|
||||||
};
|
};
|
||||||
|
|
||||||
return i2c_transfer(adapter, msgs, 1);
|
return drxk_i2c_transfer(state, msgs, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len)
|
static int i2c_write(struct drxk_state *state, u8 adr, u8 *data, int len)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
struct i2c_msg msg = {
|
struct i2c_msg msg = {
|
||||||
|
@ -330,7 +357,7 @@ static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len)
|
||||||
printk(KERN_CONT " %02x", data[i]);
|
printk(KERN_CONT " %02x", data[i]);
|
||||||
printk(KERN_CONT "\n");
|
printk(KERN_CONT "\n");
|
||||||
}
|
}
|
||||||
status = i2c_transfer(adap, &msg, 1);
|
status = drxk_i2c_transfer(state, &msg, 1);
|
||||||
if (status >= 0 && status != 1)
|
if (status >= 0 && status != 1)
|
||||||
status = -EIO;
|
status = -EIO;
|
||||||
|
|
||||||
|
@ -340,7 +367,7 @@ static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len)
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int i2c_read(struct i2c_adapter *adap,
|
static int i2c_read(struct drxk_state *state,
|
||||||
u8 adr, u8 *msg, int len, u8 *answ, int alen)
|
u8 adr, u8 *msg, int len, u8 *answ, int alen)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
|
@ -351,7 +378,7 @@ static int i2c_read(struct i2c_adapter *adap,
|
||||||
.buf = answ, .len = alen}
|
.buf = answ, .len = alen}
|
||||||
};
|
};
|
||||||
|
|
||||||
status = i2c_transfer(adap, msgs, 2);
|
status = drxk_i2c_transfer(state, msgs, 2);
|
||||||
if (status != 2) {
|
if (status != 2) {
|
||||||
if (debug > 2)
|
if (debug > 2)
|
||||||
printk(KERN_CONT ": ERROR!\n");
|
printk(KERN_CONT ": ERROR!\n");
|
||||||
|
@ -394,7 +421,7 @@ static int read16_flags(struct drxk_state *state, u32 reg, u16 *data, u8 flags)
|
||||||
len = 2;
|
len = 2;
|
||||||
}
|
}
|
||||||
dprintk(2, "(0x%08x, 0x%02x)\n", reg, flags);
|
dprintk(2, "(0x%08x, 0x%02x)\n", reg, flags);
|
||||||
status = i2c_read(state->i2c, adr, mm1, len, mm2, 2);
|
status = i2c_read(state, adr, mm1, len, mm2, 2);
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
return status;
|
return status;
|
||||||
if (data)
|
if (data)
|
||||||
|
@ -428,7 +455,7 @@ static int read32_flags(struct drxk_state *state, u32 reg, u32 *data, u8 flags)
|
||||||
len = 2;
|
len = 2;
|
||||||
}
|
}
|
||||||
dprintk(2, "(0x%08x, 0x%02x)\n", reg, flags);
|
dprintk(2, "(0x%08x, 0x%02x)\n", reg, flags);
|
||||||
status = i2c_read(state->i2c, adr, mm1, len, mm2, 4);
|
status = i2c_read(state, adr, mm1, len, mm2, 4);
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
return status;
|
return status;
|
||||||
if (data)
|
if (data)
|
||||||
|
@ -464,7 +491,7 @@ static int write16_flags(struct drxk_state *state, u32 reg, u16 data, u8 flags)
|
||||||
mm[len + 1] = (data >> 8) & 0xff;
|
mm[len + 1] = (data >> 8) & 0xff;
|
||||||
|
|
||||||
dprintk(2, "(0x%08x, 0x%04x, 0x%02x)\n", reg, data, flags);
|
dprintk(2, "(0x%08x, 0x%04x, 0x%02x)\n", reg, data, flags);
|
||||||
return i2c_write(state->i2c, adr, mm, len + 2);
|
return i2c_write(state, adr, mm, len + 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write16(struct drxk_state *state, u32 reg, u16 data)
|
static int write16(struct drxk_state *state, u32 reg, u16 data)
|
||||||
|
@ -495,7 +522,7 @@ static int write32_flags(struct drxk_state *state, u32 reg, u32 data, u8 flags)
|
||||||
mm[len + 3] = (data >> 24) & 0xff;
|
mm[len + 3] = (data >> 24) & 0xff;
|
||||||
dprintk(2, "(0x%08x, 0x%08x, 0x%02x)\n", reg, data, flags);
|
dprintk(2, "(0x%08x, 0x%08x, 0x%02x)\n", reg, data, flags);
|
||||||
|
|
||||||
return i2c_write(state->i2c, adr, mm, len + 4);
|
return i2c_write(state, adr, mm, len + 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write32(struct drxk_state *state, u32 reg, u32 data)
|
static int write32(struct drxk_state *state, u32 reg, u32 data)
|
||||||
|
@ -542,7 +569,7 @@ static int write_block(struct drxk_state *state, u32 Address,
|
||||||
printk(KERN_CONT " %02x", pBlock[i]);
|
printk(KERN_CONT " %02x", pBlock[i]);
|
||||||
printk(KERN_CONT "\n");
|
printk(KERN_CONT "\n");
|
||||||
}
|
}
|
||||||
status = i2c_write(state->i2c, state->demod_address,
|
status = i2c_write(state, state->demod_address,
|
||||||
&state->Chunk[0], Chunk + AdrLength);
|
&state->Chunk[0], Chunk + AdrLength);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
printk(KERN_ERR "drxk: %s: i2c write error at addr 0x%02x\n",
|
printk(KERN_ERR "drxk: %s: i2c write error at addr 0x%02x\n",
|
||||||
|
@ -568,17 +595,17 @@ int PowerUpDevice(struct drxk_state *state)
|
||||||
|
|
||||||
dprintk(1, "\n");
|
dprintk(1, "\n");
|
||||||
|
|
||||||
status = i2c_read1(state->i2c, state->demod_address, &data);
|
status = i2c_read1(state, state->demod_address, &data);
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
do {
|
do {
|
||||||
data = 0;
|
data = 0;
|
||||||
status = i2c_write(state->i2c, state->demod_address,
|
status = i2c_write(state, state->demod_address,
|
||||||
&data, 1);
|
&data, 1);
|
||||||
msleep(10);
|
msleep(10);
|
||||||
retryCount++;
|
retryCount++;
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
continue;
|
continue;
|
||||||
status = i2c_read1(state->i2c, state->demod_address,
|
status = i2c_read1(state, state->demod_address,
|
||||||
&data);
|
&data);
|
||||||
} while (status < 0 &&
|
} while (status < 0 &&
|
||||||
(retryCount < DRXK_MAX_RETRIES_POWERUP));
|
(retryCount < DRXK_MAX_RETRIES_POWERUP));
|
||||||
|
@ -932,7 +959,7 @@ static int GetDeviceCapabilities(struct drxk_state *state)
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
printk(KERN_ERR "drxk: status = 0x%08x\n", sioTopJtagidLo);
|
printk(KERN_INFO "drxk: status = 0x%08x\n", sioTopJtagidLo);
|
||||||
|
|
||||||
/* driver 0.9.0 */
|
/* driver 0.9.0 */
|
||||||
switch ((sioTopJtagidLo >> 29) & 0xF) {
|
switch ((sioTopJtagidLo >> 29) & 0xF) {
|
||||||
|
@ -2824,7 +2851,7 @@ static int ConfigureI2CBridge(struct drxk_state *state, bool bEnableBridge)
|
||||||
dprintk(1, "\n");
|
dprintk(1, "\n");
|
||||||
|
|
||||||
if (state->m_DrxkState == DRXK_UNINITIALIZED)
|
if (state->m_DrxkState == DRXK_UNINITIALIZED)
|
||||||
goto error;
|
return 0;
|
||||||
if (state->m_DrxkState == DRXK_POWERED_DOWN)
|
if (state->m_DrxkState == DRXK_POWERED_DOWN)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
@ -2977,7 +3004,7 @@ static int ADCSynchronization(struct drxk_state *state)
|
||||||
status = read16(state, IQM_AF_CLKNEG__A, &clkNeg);
|
status = read16(state, IQM_AF_CLKNEG__A, &clkNeg);
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
goto error;
|
goto error;
|
||||||
if ((clkNeg | IQM_AF_CLKNEG_CLKNEGDATA__M) ==
|
if ((clkNeg & IQM_AF_CLKNEG_CLKNEGDATA__M) ==
|
||||||
IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_POS) {
|
IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_POS) {
|
||||||
clkNeg &= (~(IQM_AF_CLKNEG_CLKNEGDATA__M));
|
clkNeg &= (~(IQM_AF_CLKNEG_CLKNEGDATA__M));
|
||||||
clkNeg |=
|
clkNeg |=
|
||||||
|
@ -5361,7 +5388,7 @@ static int GetQAMLockStatus(struct drxk_state *state, u32 *pLockStatus)
|
||||||
SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK, 0, NULL, 2,
|
SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK, 0, NULL, 2,
|
||||||
Result);
|
Result);
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
printk(KERN_ERR "drxk: %s status = %08x\n", __func__, status);
|
printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
|
||||||
|
|
||||||
if (Result[1] < SCU_RAM_QAM_LOCKED_LOCKED_DEMOD_LOCKED) {
|
if (Result[1] < SCU_RAM_QAM_LOCKED_LOCKED_DEMOD_LOCKED) {
|
||||||
/* 0x0000 NOT LOCKED */
|
/* 0x0000 NOT LOCKED */
|
||||||
|
@ -5388,12 +5415,67 @@ static int GetQAMLockStatus(struct drxk_state *state, u32 *pLockStatus)
|
||||||
#define QAM_LOCKRANGE__M 0x10
|
#define QAM_LOCKRANGE__M 0x10
|
||||||
#define QAM_LOCKRANGE_NORMAL 0x10
|
#define QAM_LOCKRANGE_NORMAL 0x10
|
||||||
|
|
||||||
|
static int QAMDemodulatorCommand(struct drxk_state *state,
|
||||||
|
int numberOfParameters)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
u16 cmdResult;
|
||||||
|
u16 setParamParameters[4] = { 0, 0, 0, 0 };
|
||||||
|
|
||||||
|
setParamParameters[0] = state->m_Constellation; /* modulation */
|
||||||
|
setParamParameters[1] = DRXK_QAM_I12_J17; /* interleave mode */
|
||||||
|
|
||||||
|
if (numberOfParameters == 2) {
|
||||||
|
u16 setEnvParameters[1] = { 0 };
|
||||||
|
|
||||||
|
if (state->m_OperationMode == OM_QAM_ITU_C)
|
||||||
|
setEnvParameters[0] = QAM_TOP_ANNEX_C;
|
||||||
|
else
|
||||||
|
setEnvParameters[0] = QAM_TOP_ANNEX_A;
|
||||||
|
|
||||||
|
status = scu_command(state,
|
||||||
|
SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV,
|
||||||
|
1, setEnvParameters, 1, &cmdResult);
|
||||||
|
if (status < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
status = scu_command(state,
|
||||||
|
SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM,
|
||||||
|
numberOfParameters, setParamParameters,
|
||||||
|
1, &cmdResult);
|
||||||
|
} else if (numberOfParameters == 4) {
|
||||||
|
if (state->m_OperationMode == OM_QAM_ITU_C)
|
||||||
|
setParamParameters[2] = QAM_TOP_ANNEX_C;
|
||||||
|
else
|
||||||
|
setParamParameters[2] = QAM_TOP_ANNEX_A;
|
||||||
|
|
||||||
|
setParamParameters[3] |= (QAM_MIRROR_AUTO_ON);
|
||||||
|
/* Env parameters */
|
||||||
|
/* check for LOCKRANGE Extented */
|
||||||
|
/* setParamParameters[3] |= QAM_LOCKRANGE_NORMAL; */
|
||||||
|
|
||||||
|
status = scu_command(state,
|
||||||
|
SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM,
|
||||||
|
numberOfParameters, setParamParameters,
|
||||||
|
1, &cmdResult);
|
||||||
|
} else {
|
||||||
|
printk(KERN_WARNING "drxk: Unknown QAM demodulator parameter "
|
||||||
|
"count %d\n", numberOfParameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (status < 0)
|
||||||
|
printk(KERN_WARNING "drxk: Warning %d on %s\n",
|
||||||
|
status, __func__);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz,
|
static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz,
|
||||||
s32 tunerFreqOffset)
|
s32 tunerFreqOffset)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
u16 setParamParameters[4] = { 0, 0, 0, 0 };
|
|
||||||
u16 cmdResult;
|
u16 cmdResult;
|
||||||
|
int qamDemodParamCount = state->qam_demod_parameter_count;
|
||||||
|
|
||||||
dprintk(1, "\n");
|
dprintk(1, "\n");
|
||||||
/*
|
/*
|
||||||
|
@ -5445,34 +5527,42 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz,
|
||||||
}
|
}
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
goto error;
|
goto error;
|
||||||
setParamParameters[0] = state->m_Constellation; /* modulation */
|
|
||||||
setParamParameters[1] = DRXK_QAM_I12_J17; /* interleave mode */
|
|
||||||
if (state->m_OperationMode == OM_QAM_ITU_C)
|
|
||||||
setParamParameters[2] = QAM_TOP_ANNEX_C;
|
|
||||||
else
|
|
||||||
setParamParameters[2] = QAM_TOP_ANNEX_A;
|
|
||||||
setParamParameters[3] |= (QAM_MIRROR_AUTO_ON);
|
|
||||||
/* Env parameters */
|
|
||||||
/* check for LOCKRANGE Extented */
|
|
||||||
/* setParamParameters[3] |= QAM_LOCKRANGE_NORMAL; */
|
|
||||||
|
|
||||||
status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM, 4, setParamParameters, 1, &cmdResult);
|
/* Use the 4-parameter if it's requested or we're probing for
|
||||||
if (status < 0) {
|
* the correct command. */
|
||||||
/* Fall-back to the simpler call */
|
if (state->qam_demod_parameter_count == 4
|
||||||
if (state->m_OperationMode == OM_QAM_ITU_C)
|
|| !state->qam_demod_parameter_count) {
|
||||||
setParamParameters[0] = QAM_TOP_ANNEX_C;
|
qamDemodParamCount = 4;
|
||||||
else
|
status = QAMDemodulatorCommand(state, qamDemodParamCount);
|
||||||
setParamParameters[0] = QAM_TOP_ANNEX_A;
|
|
||||||
status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV, 1, setParamParameters, 1, &cmdResult);
|
|
||||||
if (status < 0)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
setParamParameters[0] = state->m_Constellation; /* modulation */
|
|
||||||
setParamParameters[1] = DRXK_QAM_I12_J17; /* interleave mode */
|
|
||||||
status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM, 2, setParamParameters, 1, &cmdResult);
|
|
||||||
}
|
}
|
||||||
if (status < 0)
|
|
||||||
|
/* Use the 2-parameter command if it was requested or if we're
|
||||||
|
* probing for the correct command and the 4-parameter command
|
||||||
|
* failed. */
|
||||||
|
if (state->qam_demod_parameter_count == 2
|
||||||
|
|| (!state->qam_demod_parameter_count && status < 0)) {
|
||||||
|
qamDemodParamCount = 2;
|
||||||
|
status = QAMDemodulatorCommand(state, qamDemodParamCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status < 0) {
|
||||||
|
dprintk(1, "Could not set demodulator parameters. Make "
|
||||||
|
"sure qam_demod_parameter_count (%d) is correct for "
|
||||||
|
"your firmware (%s).\n",
|
||||||
|
state->qam_demod_parameter_count,
|
||||||
|
state->microcode_name);
|
||||||
goto error;
|
goto error;
|
||||||
|
} else if (!state->qam_demod_parameter_count) {
|
||||||
|
dprintk(1, "Auto-probing the correct QAM demodulator command "
|
||||||
|
"parameters was successful - using %d parameters.\n",
|
||||||
|
qamDemodParamCount);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* One of our commands was successful. We don't need to
|
||||||
|
* auto-probe anymore, now that we got the correct command.
|
||||||
|
*/
|
||||||
|
state->qam_demod_parameter_count = qamDemodParamCount;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* STEP 3: enable the system in a mode where the ADC provides valid
|
* STEP 3: enable the system in a mode where the ADC provides valid
|
||||||
|
@ -5968,34 +6058,15 @@ error:
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int load_microcode(struct drxk_state *state, const char *mc_name)
|
|
||||||
{
|
|
||||||
const struct firmware *fw = NULL;
|
|
||||||
int err = 0;
|
|
||||||
|
|
||||||
dprintk(1, "\n");
|
|
||||||
|
|
||||||
err = request_firmware(&fw, mc_name, state->i2c->dev.parent);
|
|
||||||
if (err < 0) {
|
|
||||||
printk(KERN_ERR
|
|
||||||
"drxk: Could not load firmware file %s.\n", mc_name);
|
|
||||||
printk(KERN_INFO
|
|
||||||
"drxk: Copy %s to your hotplug directory!\n", mc_name);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
err = DownloadMicrocode(state, fw->data, fw->size);
|
|
||||||
release_firmware(fw);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int init_drxk(struct drxk_state *state)
|
static int init_drxk(struct drxk_state *state)
|
||||||
{
|
{
|
||||||
int status = 0;
|
int status = 0, n = 0;
|
||||||
enum DRXPowerMode powerMode = DRXK_POWER_DOWN_OFDM;
|
enum DRXPowerMode powerMode = DRXK_POWER_DOWN_OFDM;
|
||||||
u16 driverVersion;
|
u16 driverVersion;
|
||||||
|
|
||||||
dprintk(1, "\n");
|
dprintk(1, "\n");
|
||||||
if ((state->m_DrxkState == DRXK_UNINITIALIZED)) {
|
if ((state->m_DrxkState == DRXK_UNINITIALIZED)) {
|
||||||
|
drxk_i2c_lock(state);
|
||||||
status = PowerUpDevice(state);
|
status = PowerUpDevice(state);
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -6073,8 +6144,12 @@ static int init_drxk(struct drxk_state *state)
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (state->microcode_name)
|
if (state->fw) {
|
||||||
load_microcode(state, state->microcode_name);
|
status = DownloadMicrocode(state, state->fw->data,
|
||||||
|
state->fw->size);
|
||||||
|
if (status < 0)
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
/* disable token-ring bus through OFDM block for possible ucode upload */
|
/* disable token-ring bus through OFDM block for possible ucode upload */
|
||||||
status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, SIO_OFDM_SH_OFDM_RING_ENABLE_OFF);
|
status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, SIO_OFDM_SH_OFDM_RING_ENABLE_OFF);
|
||||||
|
@ -6167,19 +6242,71 @@ static int init_drxk(struct drxk_state *state)
|
||||||
state->m_DrxkState = DRXK_POWERED_DOWN;
|
state->m_DrxkState = DRXK_POWERED_DOWN;
|
||||||
} else
|
} else
|
||||||
state->m_DrxkState = DRXK_STOPPED;
|
state->m_DrxkState = DRXK_STOPPED;
|
||||||
|
|
||||||
|
/* Initialize the supported delivery systems */
|
||||||
|
n = 0;
|
||||||
|
if (state->m_hasDVBC) {
|
||||||
|
state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_A;
|
||||||
|
state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_C;
|
||||||
|
strlcat(state->frontend.ops.info.name, " DVB-C",
|
||||||
|
sizeof(state->frontend.ops.info.name));
|
||||||
|
}
|
||||||
|
if (state->m_hasDVBT) {
|
||||||
|
state->frontend.ops.delsys[n++] = SYS_DVBT;
|
||||||
|
strlcat(state->frontend.ops.info.name, " DVB-T",
|
||||||
|
sizeof(state->frontend.ops.info.name));
|
||||||
|
}
|
||||||
|
drxk_i2c_unlock(state);
|
||||||
}
|
}
|
||||||
error:
|
error:
|
||||||
if (status < 0)
|
if (status < 0) {
|
||||||
|
state->m_DrxkState = DRXK_NO_DEV;
|
||||||
|
drxk_i2c_unlock(state);
|
||||||
printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
|
printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
|
||||||
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void load_firmware_cb(const struct firmware *fw,
|
||||||
|
void *context)
|
||||||
|
{
|
||||||
|
struct drxk_state *state = context;
|
||||||
|
|
||||||
|
dprintk(1, ": %s\n", fw ? "firmware loaded" : "firmware not loaded");
|
||||||
|
if (!fw) {
|
||||||
|
printk(KERN_ERR
|
||||||
|
"drxk: Could not load firmware file %s.\n",
|
||||||
|
state->microcode_name);
|
||||||
|
printk(KERN_INFO
|
||||||
|
"drxk: Copy %s to your hotplug directory!\n",
|
||||||
|
state->microcode_name);
|
||||||
|
state->microcode_name = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* As firmware is now load asynchronous, it is not possible
|
||||||
|
* anymore to fail at frontend attach. We might silently
|
||||||
|
* return here, and hope that the driver won't crash.
|
||||||
|
* We might also change all DVB callbacks to return -ENODEV
|
||||||
|
* if the device is not initialized.
|
||||||
|
* As the DRX-K devices have their own internal firmware,
|
||||||
|
* let's just hope that it will match a firmware revision
|
||||||
|
* compatible with this driver and proceed.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
state->fw = fw;
|
||||||
|
|
||||||
|
init_drxk(state);
|
||||||
|
}
|
||||||
|
|
||||||
static void drxk_release(struct dvb_frontend *fe)
|
static void drxk_release(struct dvb_frontend *fe)
|
||||||
{
|
{
|
||||||
struct drxk_state *state = fe->demodulator_priv;
|
struct drxk_state *state = fe->demodulator_priv;
|
||||||
|
|
||||||
dprintk(1, "\n");
|
dprintk(1, "\n");
|
||||||
|
if (state->fw)
|
||||||
|
release_firmware(state->fw);
|
||||||
|
|
||||||
kfree(state);
|
kfree(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6188,6 +6315,12 @@ static int drxk_sleep(struct dvb_frontend *fe)
|
||||||
struct drxk_state *state = fe->demodulator_priv;
|
struct drxk_state *state = fe->demodulator_priv;
|
||||||
|
|
||||||
dprintk(1, "\n");
|
dprintk(1, "\n");
|
||||||
|
|
||||||
|
if (state->m_DrxkState == DRXK_NO_DEV)
|
||||||
|
return -ENODEV;
|
||||||
|
if (state->m_DrxkState == DRXK_UNINITIALIZED)
|
||||||
|
return 0;
|
||||||
|
|
||||||
ShutDown(state);
|
ShutDown(state);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -6196,7 +6329,11 @@ static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
|
||||||
{
|
{
|
||||||
struct drxk_state *state = fe->demodulator_priv;
|
struct drxk_state *state = fe->demodulator_priv;
|
||||||
|
|
||||||
dprintk(1, "%s\n", enable ? "enable" : "disable");
|
dprintk(1, ": %s\n", enable ? "enable" : "disable");
|
||||||
|
|
||||||
|
if (state->m_DrxkState == DRXK_NO_DEV)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
return ConfigureI2CBridge(state, enable ? true : false);
|
return ConfigureI2CBridge(state, enable ? true : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6209,6 +6346,12 @@ static int drxk_set_parameters(struct dvb_frontend *fe)
|
||||||
|
|
||||||
dprintk(1, "\n");
|
dprintk(1, "\n");
|
||||||
|
|
||||||
|
if (state->m_DrxkState == DRXK_NO_DEV)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
if (state->m_DrxkState == DRXK_UNINITIALIZED)
|
||||||
|
return -EAGAIN;
|
||||||
|
|
||||||
if (!fe->ops.tuner_ops.get_if_frequency) {
|
if (!fe->ops.tuner_ops.get_if_frequency) {
|
||||||
printk(KERN_ERR
|
printk(KERN_ERR
|
||||||
"drxk: Error: get_if_frequency() not defined at tuner. Can't work without it!\n");
|
"drxk: Error: get_if_frequency() not defined at tuner. Can't work without it!\n");
|
||||||
|
@ -6262,6 +6405,12 @@ static int drxk_read_status(struct dvb_frontend *fe, fe_status_t *status)
|
||||||
u32 stat;
|
u32 stat;
|
||||||
|
|
||||||
dprintk(1, "\n");
|
dprintk(1, "\n");
|
||||||
|
|
||||||
|
if (state->m_DrxkState == DRXK_NO_DEV)
|
||||||
|
return -ENODEV;
|
||||||
|
if (state->m_DrxkState == DRXK_UNINITIALIZED)
|
||||||
|
return -EAGAIN;
|
||||||
|
|
||||||
*status = 0;
|
*status = 0;
|
||||||
GetLockStatus(state, &stat, 0);
|
GetLockStatus(state, &stat, 0);
|
||||||
if (stat == MPEG_LOCK)
|
if (stat == MPEG_LOCK)
|
||||||
|
@ -6275,8 +6424,15 @@ static int drxk_read_status(struct dvb_frontend *fe, fe_status_t *status)
|
||||||
|
|
||||||
static int drxk_read_ber(struct dvb_frontend *fe, u32 *ber)
|
static int drxk_read_ber(struct dvb_frontend *fe, u32 *ber)
|
||||||
{
|
{
|
||||||
|
struct drxk_state *state = fe->demodulator_priv;
|
||||||
|
|
||||||
dprintk(1, "\n");
|
dprintk(1, "\n");
|
||||||
|
|
||||||
|
if (state->m_DrxkState == DRXK_NO_DEV)
|
||||||
|
return -ENODEV;
|
||||||
|
if (state->m_DrxkState == DRXK_UNINITIALIZED)
|
||||||
|
return -EAGAIN;
|
||||||
|
|
||||||
*ber = 0;
|
*ber = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -6288,6 +6444,12 @@ static int drxk_read_signal_strength(struct dvb_frontend *fe,
|
||||||
u32 val = 0;
|
u32 val = 0;
|
||||||
|
|
||||||
dprintk(1, "\n");
|
dprintk(1, "\n");
|
||||||
|
|
||||||
|
if (state->m_DrxkState == DRXK_NO_DEV)
|
||||||
|
return -ENODEV;
|
||||||
|
if (state->m_DrxkState == DRXK_UNINITIALIZED)
|
||||||
|
return -EAGAIN;
|
||||||
|
|
||||||
ReadIFAgc(state, &val);
|
ReadIFAgc(state, &val);
|
||||||
*strength = val & 0xffff;
|
*strength = val & 0xffff;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -6299,6 +6461,12 @@ static int drxk_read_snr(struct dvb_frontend *fe, u16 *snr)
|
||||||
s32 snr2;
|
s32 snr2;
|
||||||
|
|
||||||
dprintk(1, "\n");
|
dprintk(1, "\n");
|
||||||
|
|
||||||
|
if (state->m_DrxkState == DRXK_NO_DEV)
|
||||||
|
return -ENODEV;
|
||||||
|
if (state->m_DrxkState == DRXK_UNINITIALIZED)
|
||||||
|
return -EAGAIN;
|
||||||
|
|
||||||
GetSignalToNoise(state, &snr2);
|
GetSignalToNoise(state, &snr2);
|
||||||
*snr = snr2 & 0xffff;
|
*snr = snr2 & 0xffff;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -6310,6 +6478,12 @@ static int drxk_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
|
||||||
u16 err;
|
u16 err;
|
||||||
|
|
||||||
dprintk(1, "\n");
|
dprintk(1, "\n");
|
||||||
|
|
||||||
|
if (state->m_DrxkState == DRXK_NO_DEV)
|
||||||
|
return -ENODEV;
|
||||||
|
if (state->m_DrxkState == DRXK_UNINITIALIZED)
|
||||||
|
return -EAGAIN;
|
||||||
|
|
||||||
DVBTQAMGetAccPktErr(state, &err);
|
DVBTQAMGetAccPktErr(state, &err);
|
||||||
*ucblocks = (u32) err;
|
*ucblocks = (u32) err;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -6318,9 +6492,16 @@ static int drxk_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
|
||||||
static int drxk_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings
|
static int drxk_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings
|
||||||
*sets)
|
*sets)
|
||||||
{
|
{
|
||||||
|
struct drxk_state *state = fe->demodulator_priv;
|
||||||
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
|
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
|
||||||
|
|
||||||
dprintk(1, "\n");
|
dprintk(1, "\n");
|
||||||
|
|
||||||
|
if (state->m_DrxkState == DRXK_NO_DEV)
|
||||||
|
return -ENODEV;
|
||||||
|
if (state->m_DrxkState == DRXK_UNINITIALIZED)
|
||||||
|
return -EAGAIN;
|
||||||
|
|
||||||
switch (p->delivery_system) {
|
switch (p->delivery_system) {
|
||||||
case SYS_DVBC_ANNEX_A:
|
case SYS_DVBC_ANNEX_A:
|
||||||
case SYS_DVBC_ANNEX_C:
|
case SYS_DVBC_ANNEX_C:
|
||||||
|
@ -6371,10 +6552,9 @@ static struct dvb_frontend_ops drxk_ops = {
|
||||||
struct dvb_frontend *drxk_attach(const struct drxk_config *config,
|
struct dvb_frontend *drxk_attach(const struct drxk_config *config,
|
||||||
struct i2c_adapter *i2c)
|
struct i2c_adapter *i2c)
|
||||||
{
|
{
|
||||||
int n;
|
|
||||||
|
|
||||||
struct drxk_state *state = NULL;
|
struct drxk_state *state = NULL;
|
||||||
u8 adr = config->adr;
|
u8 adr = config->adr;
|
||||||
|
int status;
|
||||||
|
|
||||||
dprintk(1, "\n");
|
dprintk(1, "\n");
|
||||||
state = kzalloc(sizeof(struct drxk_state), GFP_KERNEL);
|
state = kzalloc(sizeof(struct drxk_state), GFP_KERNEL);
|
||||||
|
@ -6385,6 +6565,7 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config,
|
||||||
state->demod_address = adr;
|
state->demod_address = adr;
|
||||||
state->single_master = config->single_master;
|
state->single_master = config->single_master;
|
||||||
state->microcode_name = config->microcode_name;
|
state->microcode_name = config->microcode_name;
|
||||||
|
state->qam_demod_parameter_count = config->qam_demod_parameter_count;
|
||||||
state->no_i2c_bridge = config->no_i2c_bridge;
|
state->no_i2c_bridge = config->no_i2c_bridge;
|
||||||
state->antenna_gpio = config->antenna_gpio;
|
state->antenna_gpio = config->antenna_gpio;
|
||||||
state->antenna_dvbt = config->antenna_dvbt;
|
state->antenna_dvbt = config->antenna_dvbt;
|
||||||
|
@ -6425,22 +6606,21 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config,
|
||||||
state->frontend.demodulator_priv = state;
|
state->frontend.demodulator_priv = state;
|
||||||
|
|
||||||
init_state(state);
|
init_state(state);
|
||||||
if (init_drxk(state) < 0)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
/* Initialize the supported delivery systems */
|
/* Load firmware and initialize DRX-K */
|
||||||
n = 0;
|
if (state->microcode_name) {
|
||||||
if (state->m_hasDVBC) {
|
status = request_firmware_nowait(THIS_MODULE, 1,
|
||||||
state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_A;
|
state->microcode_name,
|
||||||
state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_C;
|
state->i2c->dev.parent,
|
||||||
strlcat(state->frontend.ops.info.name, " DVB-C",
|
GFP_KERNEL,
|
||||||
sizeof(state->frontend.ops.info.name));
|
state, load_firmware_cb);
|
||||||
}
|
if (status < 0) {
|
||||||
if (state->m_hasDVBT) {
|
printk(KERN_ERR
|
||||||
state->frontend.ops.delsys[n++] = SYS_DVBT;
|
"drxk: failed to request a firmware\n");
|
||||||
strlcat(state->frontend.ops.info.name, " DVB-T",
|
return NULL;
|
||||||
sizeof(state->frontend.ops.info.name));
|
}
|
||||||
}
|
} else if (init_drxk(state) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
printk(KERN_INFO "drxk: frontend initialized.\n");
|
printk(KERN_INFO "drxk: frontend initialized.\n");
|
||||||
return &state->frontend;
|
return &state->frontend;
|
||||||
|
|
|
@ -94,7 +94,15 @@ enum DRXPowerMode {
|
||||||
|
|
||||||
|
|
||||||
enum AGC_CTRL_MODE { DRXK_AGC_CTRL_AUTO = 0, DRXK_AGC_CTRL_USER, DRXK_AGC_CTRL_OFF };
|
enum AGC_CTRL_MODE { DRXK_AGC_CTRL_AUTO = 0, DRXK_AGC_CTRL_USER, DRXK_AGC_CTRL_OFF };
|
||||||
enum EDrxkState { DRXK_UNINITIALIZED = 0, DRXK_STOPPED, DRXK_DTV_STARTED, DRXK_ATV_STARTED, DRXK_POWERED_DOWN };
|
enum EDrxkState {
|
||||||
|
DRXK_UNINITIALIZED = 0,
|
||||||
|
DRXK_STOPPED,
|
||||||
|
DRXK_DTV_STARTED,
|
||||||
|
DRXK_ATV_STARTED,
|
||||||
|
DRXK_POWERED_DOWN,
|
||||||
|
DRXK_NO_DEV /* If drxk init failed */
|
||||||
|
};
|
||||||
|
|
||||||
enum EDrxkCoefArrayIndex {
|
enum EDrxkCoefArrayIndex {
|
||||||
DRXK_COEF_IDX_MN = 0,
|
DRXK_COEF_IDX_MN = 0,
|
||||||
DRXK_COEF_IDX_FM ,
|
DRXK_COEF_IDX_FM ,
|
||||||
|
@ -325,6 +333,9 @@ struct drxk_state {
|
||||||
|
|
||||||
enum DRXPowerMode m_currentPowerMode;
|
enum DRXPowerMode m_currentPowerMode;
|
||||||
|
|
||||||
|
/* when true, avoids other devices to use the I2C bus */
|
||||||
|
bool drxk_i2c_exclusive_lock;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Configurable parameters at the driver. They stores the values found
|
* Configurable parameters at the driver. They stores the values found
|
||||||
* at struct drxk_config.
|
* at struct drxk_config.
|
||||||
|
@ -338,7 +349,11 @@ struct drxk_state {
|
||||||
bool antenna_dvbt;
|
bool antenna_dvbt;
|
||||||
u16 antenna_gpio;
|
u16 antenna_gpio;
|
||||||
|
|
||||||
|
/* Firmware */
|
||||||
const char *microcode_name;
|
const char *microcode_name;
|
||||||
|
struct completion fw_wait_load;
|
||||||
|
const struct firmware *fw;
|
||||||
|
int qam_demod_parameter_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NEVER_LOCK 0
|
#define NEVER_LOCK 0
|
||||||
|
|
|
@ -0,0 +1,789 @@
|
||||||
|
/*
|
||||||
|
* Realtek RTL2832 DVB-T demodulator driver
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Thomas Mair <thomas.mair86@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "rtl2832_priv.h"
|
||||||
|
#include <linux/bitops.h>
|
||||||
|
|
||||||
|
int rtl2832_debug;
|
||||||
|
module_param_named(debug, rtl2832_debug, int, 0644);
|
||||||
|
MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
|
||||||
|
|
||||||
|
#define REG_MASK(b) (BIT(b + 1) - 1)
|
||||||
|
|
||||||
|
static const struct rtl2832_reg_entry registers[] = {
|
||||||
|
[DVBT_SOFT_RST] = {0x1, 0x1, 2, 2},
|
||||||
|
[DVBT_IIC_REPEAT] = {0x1, 0x1, 3, 3},
|
||||||
|
[DVBT_TR_WAIT_MIN_8K] = {0x1, 0x88, 11, 2},
|
||||||
|
[DVBT_RSD_BER_FAIL_VAL] = {0x1, 0x8f, 15, 0},
|
||||||
|
[DVBT_EN_BK_TRK] = {0x1, 0xa6, 7, 7},
|
||||||
|
[DVBT_AD_EN_REG] = {0x0, 0x8, 7, 7},
|
||||||
|
[DVBT_AD_EN_REG1] = {0x0, 0x8, 6, 6},
|
||||||
|
[DVBT_EN_BBIN] = {0x1, 0xb1, 0, 0},
|
||||||
|
[DVBT_MGD_THD0] = {0x1, 0x95, 7, 0},
|
||||||
|
[DVBT_MGD_THD1] = {0x1, 0x96, 7, 0},
|
||||||
|
[DVBT_MGD_THD2] = {0x1, 0x97, 7, 0},
|
||||||
|
[DVBT_MGD_THD3] = {0x1, 0x98, 7, 0},
|
||||||
|
[DVBT_MGD_THD4] = {0x1, 0x99, 7, 0},
|
||||||
|
[DVBT_MGD_THD5] = {0x1, 0x9a, 7, 0},
|
||||||
|
[DVBT_MGD_THD6] = {0x1, 0x9b, 7, 0},
|
||||||
|
[DVBT_MGD_THD7] = {0x1, 0x9c, 7, 0},
|
||||||
|
[DVBT_EN_CACQ_NOTCH] = {0x1, 0x61, 4, 4},
|
||||||
|
[DVBT_AD_AV_REF] = {0x0, 0x9, 6, 0},
|
||||||
|
[DVBT_REG_PI] = {0x0, 0xa, 2, 0},
|
||||||
|
[DVBT_PIP_ON] = {0x0, 0x21, 3, 3},
|
||||||
|
[DVBT_SCALE1_B92] = {0x2, 0x92, 7, 0},
|
||||||
|
[DVBT_SCALE1_B93] = {0x2, 0x93, 7, 0},
|
||||||
|
[DVBT_SCALE1_BA7] = {0x2, 0xa7, 7, 0},
|
||||||
|
[DVBT_SCALE1_BA9] = {0x2, 0xa9, 7, 0},
|
||||||
|
[DVBT_SCALE1_BAA] = {0x2, 0xaa, 7, 0},
|
||||||
|
[DVBT_SCALE1_BAB] = {0x2, 0xab, 7, 0},
|
||||||
|
[DVBT_SCALE1_BAC] = {0x2, 0xac, 7, 0},
|
||||||
|
[DVBT_SCALE1_BB0] = {0x2, 0xb0, 7, 0},
|
||||||
|
[DVBT_SCALE1_BB1] = {0x2, 0xb1, 7, 0},
|
||||||
|
[DVBT_KB_P1] = {0x1, 0x64, 3, 1},
|
||||||
|
[DVBT_KB_P2] = {0x1, 0x64, 6, 4},
|
||||||
|
[DVBT_KB_P3] = {0x1, 0x65, 2, 0},
|
||||||
|
[DVBT_OPT_ADC_IQ] = {0x0, 0x6, 5, 4},
|
||||||
|
[DVBT_AD_AVI] = {0x0, 0x9, 1, 0},
|
||||||
|
[DVBT_AD_AVQ] = {0x0, 0x9, 3, 2},
|
||||||
|
[DVBT_K1_CR_STEP12] = {0x2, 0xad, 9, 4},
|
||||||
|
[DVBT_TRK_KS_P2] = {0x1, 0x6f, 2, 0},
|
||||||
|
[DVBT_TRK_KS_I2] = {0x1, 0x70, 5, 3},
|
||||||
|
[DVBT_TR_THD_SET2] = {0x1, 0x72, 3, 0},
|
||||||
|
[DVBT_TRK_KC_P2] = {0x1, 0x73, 5, 3},
|
||||||
|
[DVBT_TRK_KC_I2] = {0x1, 0x75, 2, 0},
|
||||||
|
[DVBT_CR_THD_SET2] = {0x1, 0x76, 7, 6},
|
||||||
|
[DVBT_PSET_IFFREQ] = {0x1, 0x19, 21, 0},
|
||||||
|
[DVBT_SPEC_INV] = {0x1, 0x15, 0, 0},
|
||||||
|
[DVBT_RSAMP_RATIO] = {0x1, 0x9f, 27, 2},
|
||||||
|
[DVBT_CFREQ_OFF_RATIO] = {0x1, 0x9d, 23, 4},
|
||||||
|
[DVBT_FSM_STAGE] = {0x3, 0x51, 6, 3},
|
||||||
|
[DVBT_RX_CONSTEL] = {0x3, 0x3c, 3, 2},
|
||||||
|
[DVBT_RX_HIER] = {0x3, 0x3c, 6, 4},
|
||||||
|
[DVBT_RX_C_RATE_LP] = {0x3, 0x3d, 2, 0},
|
||||||
|
[DVBT_RX_C_RATE_HP] = {0x3, 0x3d, 5, 3},
|
||||||
|
[DVBT_GI_IDX] = {0x3, 0x51, 1, 0},
|
||||||
|
[DVBT_FFT_MODE_IDX] = {0x3, 0x51, 2, 2},
|
||||||
|
[DVBT_RSD_BER_EST] = {0x3, 0x4e, 15, 0},
|
||||||
|
[DVBT_CE_EST_EVM] = {0x4, 0xc, 15, 0},
|
||||||
|
[DVBT_RF_AGC_VAL] = {0x3, 0x5b, 13, 0},
|
||||||
|
[DVBT_IF_AGC_VAL] = {0x3, 0x59, 13, 0},
|
||||||
|
[DVBT_DAGC_VAL] = {0x3, 0x5, 7, 0},
|
||||||
|
[DVBT_SFREQ_OFF] = {0x3, 0x18, 13, 0},
|
||||||
|
[DVBT_CFREQ_OFF] = {0x3, 0x5f, 17, 0},
|
||||||
|
[DVBT_POLAR_RF_AGC] = {0x0, 0xe, 1, 1},
|
||||||
|
[DVBT_POLAR_IF_AGC] = {0x0, 0xe, 0, 0},
|
||||||
|
[DVBT_AAGC_HOLD] = {0x1, 0x4, 5, 5},
|
||||||
|
[DVBT_EN_RF_AGC] = {0x1, 0x4, 6, 6},
|
||||||
|
[DVBT_EN_IF_AGC] = {0x1, 0x4, 7, 7},
|
||||||
|
[DVBT_IF_AGC_MIN] = {0x1, 0x8, 7, 0},
|
||||||
|
[DVBT_IF_AGC_MAX] = {0x1, 0x9, 7, 0},
|
||||||
|
[DVBT_RF_AGC_MIN] = {0x1, 0xa, 7, 0},
|
||||||
|
[DVBT_RF_AGC_MAX] = {0x1, 0xb, 7, 0},
|
||||||
|
[DVBT_IF_AGC_MAN] = {0x1, 0xc, 6, 6},
|
||||||
|
[DVBT_IF_AGC_MAN_VAL] = {0x1, 0xc, 13, 0},
|
||||||
|
[DVBT_RF_AGC_MAN] = {0x1, 0xe, 6, 6},
|
||||||
|
[DVBT_RF_AGC_MAN_VAL] = {0x1, 0xe, 13, 0},
|
||||||
|
[DVBT_DAGC_TRG_VAL] = {0x1, 0x12, 7, 0},
|
||||||
|
[DVBT_AGC_TARG_VAL_0] = {0x1, 0x2, 0, 0},
|
||||||
|
[DVBT_AGC_TARG_VAL_8_1] = {0x1, 0x3, 7, 0},
|
||||||
|
[DVBT_AAGC_LOOP_GAIN] = {0x1, 0xc7, 5, 1},
|
||||||
|
[DVBT_LOOP_GAIN2_3_0] = {0x1, 0x4, 4, 1},
|
||||||
|
[DVBT_LOOP_GAIN2_4] = {0x1, 0x5, 7, 7},
|
||||||
|
[DVBT_LOOP_GAIN3] = {0x1, 0xc8, 4, 0},
|
||||||
|
[DVBT_VTOP1] = {0x1, 0x6, 5, 0},
|
||||||
|
[DVBT_VTOP2] = {0x1, 0xc9, 5, 0},
|
||||||
|
[DVBT_VTOP3] = {0x1, 0xca, 5, 0},
|
||||||
|
[DVBT_KRF1] = {0x1, 0xcb, 7, 0},
|
||||||
|
[DVBT_KRF2] = {0x1, 0x7, 7, 0},
|
||||||
|
[DVBT_KRF3] = {0x1, 0xcd, 7, 0},
|
||||||
|
[DVBT_KRF4] = {0x1, 0xce, 7, 0},
|
||||||
|
[DVBT_EN_GI_PGA] = {0x1, 0xe5, 0, 0},
|
||||||
|
[DVBT_THD_LOCK_UP] = {0x1, 0xd9, 8, 0},
|
||||||
|
[DVBT_THD_LOCK_DW] = {0x1, 0xdb, 8, 0},
|
||||||
|
[DVBT_THD_UP1] = {0x1, 0xdd, 7, 0},
|
||||||
|
[DVBT_THD_DW1] = {0x1, 0xde, 7, 0},
|
||||||
|
[DVBT_INTER_CNT_LEN] = {0x1, 0xd8, 3, 0},
|
||||||
|
[DVBT_GI_PGA_STATE] = {0x1, 0xe6, 3, 3},
|
||||||
|
[DVBT_EN_AGC_PGA] = {0x1, 0xd7, 0, 0},
|
||||||
|
[DVBT_CKOUTPAR] = {0x1, 0x7b, 5, 5},
|
||||||
|
[DVBT_CKOUT_PWR] = {0x1, 0x7b, 6, 6},
|
||||||
|
[DVBT_SYNC_DUR] = {0x1, 0x7b, 7, 7},
|
||||||
|
[DVBT_ERR_DUR] = {0x1, 0x7c, 0, 0},
|
||||||
|
[DVBT_SYNC_LVL] = {0x1, 0x7c, 1, 1},
|
||||||
|
[DVBT_ERR_LVL] = {0x1, 0x7c, 2, 2},
|
||||||
|
[DVBT_VAL_LVL] = {0x1, 0x7c, 3, 3},
|
||||||
|
[DVBT_SERIAL] = {0x1, 0x7c, 4, 4},
|
||||||
|
[DVBT_SER_LSB] = {0x1, 0x7c, 5, 5},
|
||||||
|
[DVBT_CDIV_PH0] = {0x1, 0x7d, 3, 0},
|
||||||
|
[DVBT_CDIV_PH1] = {0x1, 0x7d, 7, 4},
|
||||||
|
[DVBT_MPEG_IO_OPT_2_2] = {0x0, 0x6, 7, 7},
|
||||||
|
[DVBT_MPEG_IO_OPT_1_0] = {0x0, 0x7, 7, 6},
|
||||||
|
[DVBT_CKOUTPAR_PIP] = {0x0, 0xb7, 4, 4},
|
||||||
|
[DVBT_CKOUT_PWR_PIP] = {0x0, 0xb7, 3, 3},
|
||||||
|
[DVBT_SYNC_LVL_PIP] = {0x0, 0xb7, 2, 2},
|
||||||
|
[DVBT_ERR_LVL_PIP] = {0x0, 0xb7, 1, 1},
|
||||||
|
[DVBT_VAL_LVL_PIP] = {0x0, 0xb7, 0, 0},
|
||||||
|
[DVBT_CKOUTPAR_PID] = {0x0, 0xb9, 4, 4},
|
||||||
|
[DVBT_CKOUT_PWR_PID] = {0x0, 0xb9, 3, 3},
|
||||||
|
[DVBT_SYNC_LVL_PID] = {0x0, 0xb9, 2, 2},
|
||||||
|
[DVBT_ERR_LVL_PID] = {0x0, 0xb9, 1, 1},
|
||||||
|
[DVBT_VAL_LVL_PID] = {0x0, 0xb9, 0, 0},
|
||||||
|
[DVBT_SM_PASS] = {0x1, 0x93, 11, 0},
|
||||||
|
[DVBT_AD7_SETTING] = {0x0, 0x11, 15, 0},
|
||||||
|
[DVBT_RSSI_R] = {0x3, 0x1, 6, 0},
|
||||||
|
[DVBT_ACI_DET_IND] = {0x3, 0x12, 0, 0},
|
||||||
|
[DVBT_REG_MON] = {0x0, 0xd, 1, 0},
|
||||||
|
[DVBT_REG_MONSEL] = {0x0, 0xd, 2, 2},
|
||||||
|
[DVBT_REG_GPE] = {0x0, 0xd, 7, 7},
|
||||||
|
[DVBT_REG_GPO] = {0x0, 0x10, 0, 0},
|
||||||
|
[DVBT_REG_4MSEL] = {0x0, 0x13, 0, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
/* write multiple hardware registers */
|
||||||
|
static int rtl2832_wr(struct rtl2832_priv *priv, u8 reg, u8 *val, int len)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
u8 buf[1+len];
|
||||||
|
struct i2c_msg msg[1] = {
|
||||||
|
{
|
||||||
|
.addr = priv->cfg.i2c_addr,
|
||||||
|
.flags = 0,
|
||||||
|
.len = 1+len,
|
||||||
|
.buf = buf,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
buf[0] = reg;
|
||||||
|
memcpy(&buf[1], val, len);
|
||||||
|
|
||||||
|
ret = i2c_transfer(priv->i2c, msg, 1);
|
||||||
|
if (ret == 1) {
|
||||||
|
ret = 0;
|
||||||
|
} else {
|
||||||
|
warn("i2c wr failed=%d reg=%02x len=%d", ret, reg, len);
|
||||||
|
ret = -EREMOTEIO;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read multiple hardware registers */
|
||||||
|
static int rtl2832_rd(struct rtl2832_priv *priv, u8 reg, u8 *val, int len)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct i2c_msg msg[2] = {
|
||||||
|
{
|
||||||
|
.addr = priv->cfg.i2c_addr,
|
||||||
|
.flags = 0,
|
||||||
|
.len = 1,
|
||||||
|
.buf = ®,
|
||||||
|
}, {
|
||||||
|
.addr = priv->cfg.i2c_addr,
|
||||||
|
.flags = I2C_M_RD,
|
||||||
|
.len = len,
|
||||||
|
.buf = val,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ret = i2c_transfer(priv->i2c, msg, 2);
|
||||||
|
if (ret == 2) {
|
||||||
|
ret = 0;
|
||||||
|
} else {
|
||||||
|
warn("i2c rd failed=%d reg=%02x len=%d", ret, reg, len);
|
||||||
|
ret = -EREMOTEIO;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write multiple registers */
|
||||||
|
static int rtl2832_wr_regs(struct rtl2832_priv *priv, u8 reg, u8 page, u8 *val,
|
||||||
|
int len)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
|
||||||
|
/* switch bank if needed */
|
||||||
|
if (page != priv->page) {
|
||||||
|
ret = rtl2832_wr(priv, 0x00, &page, 1);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
priv->page = page;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rtl2832_wr(priv, reg, val, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read multiple registers */
|
||||||
|
static int rtl2832_rd_regs(struct rtl2832_priv *priv, u8 reg, u8 page, u8 *val,
|
||||||
|
int len)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* switch bank if needed */
|
||||||
|
if (page != priv->page) {
|
||||||
|
ret = rtl2832_wr(priv, 0x00, &page, 1);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
priv->page = page;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rtl2832_rd(priv, reg, val, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0 /* currently not used */
|
||||||
|
/* write single register */
|
||||||
|
static int rtl2832_wr_reg(struct rtl2832_priv *priv, u8 reg, u8 page, u8 val)
|
||||||
|
{
|
||||||
|
return rtl2832_wr_regs(priv, reg, page, &val, 1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* read single register */
|
||||||
|
static int rtl2832_rd_reg(struct rtl2832_priv *priv, u8 reg, u8 page, u8 *val)
|
||||||
|
{
|
||||||
|
return rtl2832_rd_regs(priv, reg, page, val, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtl2832_rd_demod_reg(struct rtl2832_priv *priv, int reg, u32 *val)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
u8 reg_start_addr;
|
||||||
|
u8 msb, lsb;
|
||||||
|
u8 page;
|
||||||
|
u8 reading[4];
|
||||||
|
u32 reading_tmp;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
u8 len;
|
||||||
|
u32 mask;
|
||||||
|
|
||||||
|
reg_start_addr = registers[reg].start_address;
|
||||||
|
msb = registers[reg].msb;
|
||||||
|
lsb = registers[reg].lsb;
|
||||||
|
page = registers[reg].page;
|
||||||
|
|
||||||
|
len = (msb >> 3) + 1;
|
||||||
|
mask = REG_MASK(msb - lsb);
|
||||||
|
|
||||||
|
ret = rtl2832_rd_regs(priv, reg_start_addr, page, &reading[0], len);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
reading_tmp = 0;
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
reading_tmp |= reading[i] << ((len - 1 - i) * 8);
|
||||||
|
|
||||||
|
*val = (reading_tmp >> lsb) & mask;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
err:
|
||||||
|
dbg("%s: failed=%d", __func__, ret);
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtl2832_wr_demod_reg(struct rtl2832_priv *priv, int reg, u32 val)
|
||||||
|
{
|
||||||
|
int ret, i;
|
||||||
|
u8 len;
|
||||||
|
u8 reg_start_addr;
|
||||||
|
u8 msb, lsb;
|
||||||
|
u8 page;
|
||||||
|
u32 mask;
|
||||||
|
|
||||||
|
|
||||||
|
u8 reading[4];
|
||||||
|
u8 writing[4];
|
||||||
|
u32 reading_tmp;
|
||||||
|
u32 writing_tmp;
|
||||||
|
|
||||||
|
|
||||||
|
reg_start_addr = registers[reg].start_address;
|
||||||
|
msb = registers[reg].msb;
|
||||||
|
lsb = registers[reg].lsb;
|
||||||
|
page = registers[reg].page;
|
||||||
|
|
||||||
|
len = (msb >> 3) + 1;
|
||||||
|
mask = REG_MASK(msb - lsb);
|
||||||
|
|
||||||
|
|
||||||
|
ret = rtl2832_rd_regs(priv, reg_start_addr, page, &reading[0], len);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
reading_tmp = 0;
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
reading_tmp |= reading[i] << ((len - 1 - i) * 8);
|
||||||
|
|
||||||
|
writing_tmp = reading_tmp & ~(mask << lsb);
|
||||||
|
writing_tmp |= ((val & mask) << lsb);
|
||||||
|
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
writing[i] = (writing_tmp >> ((len - 1 - i) * 8)) & 0xff;
|
||||||
|
|
||||||
|
ret = rtl2832_wr_regs(priv, reg_start_addr, page, &writing[0], len);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
err:
|
||||||
|
dbg("%s: failed=%d", __func__, ret);
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int rtl2832_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct rtl2832_priv *priv = fe->demodulator_priv;
|
||||||
|
|
||||||
|
dbg("%s: enable=%d", __func__, enable);
|
||||||
|
|
||||||
|
/* gate already open or close */
|
||||||
|
if (priv->i2c_gate_state == enable)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ret = rtl2832_wr_demod_reg(priv, DVBT_IIC_REPEAT, (enable ? 0x1 : 0x0));
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
priv->i2c_gate_state = enable;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
err:
|
||||||
|
dbg("%s: failed=%d", __func__, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int rtl2832_init(struct dvb_frontend *fe)
|
||||||
|
{
|
||||||
|
struct rtl2832_priv *priv = fe->demodulator_priv;
|
||||||
|
int i, ret;
|
||||||
|
|
||||||
|
u8 en_bbin;
|
||||||
|
u64 pset_iffreq;
|
||||||
|
|
||||||
|
/* initialization values for the demodulator registers */
|
||||||
|
struct rtl2832_reg_value rtl2832_initial_regs[] = {
|
||||||
|
{DVBT_AD_EN_REG, 0x1},
|
||||||
|
{DVBT_AD_EN_REG1, 0x1},
|
||||||
|
{DVBT_RSD_BER_FAIL_VAL, 0x2800},
|
||||||
|
{DVBT_MGD_THD0, 0x10},
|
||||||
|
{DVBT_MGD_THD1, 0x20},
|
||||||
|
{DVBT_MGD_THD2, 0x20},
|
||||||
|
{DVBT_MGD_THD3, 0x40},
|
||||||
|
{DVBT_MGD_THD4, 0x22},
|
||||||
|
{DVBT_MGD_THD5, 0x32},
|
||||||
|
{DVBT_MGD_THD6, 0x37},
|
||||||
|
{DVBT_MGD_THD7, 0x39},
|
||||||
|
{DVBT_EN_BK_TRK, 0x0},
|
||||||
|
{DVBT_EN_CACQ_NOTCH, 0x0},
|
||||||
|
{DVBT_AD_AV_REF, 0x2a},
|
||||||
|
{DVBT_REG_PI, 0x6},
|
||||||
|
{DVBT_PIP_ON, 0x0},
|
||||||
|
{DVBT_CDIV_PH0, 0x8},
|
||||||
|
{DVBT_CDIV_PH1, 0x8},
|
||||||
|
{DVBT_SCALE1_B92, 0x4},
|
||||||
|
{DVBT_SCALE1_B93, 0xb0},
|
||||||
|
{DVBT_SCALE1_BA7, 0x78},
|
||||||
|
{DVBT_SCALE1_BA9, 0x28},
|
||||||
|
{DVBT_SCALE1_BAA, 0x59},
|
||||||
|
{DVBT_SCALE1_BAB, 0x83},
|
||||||
|
{DVBT_SCALE1_BAC, 0xd4},
|
||||||
|
{DVBT_SCALE1_BB0, 0x65},
|
||||||
|
{DVBT_SCALE1_BB1, 0x43},
|
||||||
|
{DVBT_KB_P1, 0x1},
|
||||||
|
{DVBT_KB_P2, 0x4},
|
||||||
|
{DVBT_KB_P3, 0x7},
|
||||||
|
{DVBT_K1_CR_STEP12, 0xa},
|
||||||
|
{DVBT_REG_GPE, 0x1},
|
||||||
|
{DVBT_SERIAL, 0x0},
|
||||||
|
{DVBT_CDIV_PH0, 0x9},
|
||||||
|
{DVBT_CDIV_PH1, 0x9},
|
||||||
|
{DVBT_MPEG_IO_OPT_2_2, 0x0},
|
||||||
|
{DVBT_MPEG_IO_OPT_1_0, 0x0},
|
||||||
|
{DVBT_TRK_KS_P2, 0x4},
|
||||||
|
{DVBT_TRK_KS_I2, 0x7},
|
||||||
|
{DVBT_TR_THD_SET2, 0x6},
|
||||||
|
{DVBT_TRK_KC_I2, 0x5},
|
||||||
|
{DVBT_CR_THD_SET2, 0x1},
|
||||||
|
{DVBT_SPEC_INV, 0x0},
|
||||||
|
{DVBT_DAGC_TRG_VAL, 0x5a},
|
||||||
|
{DVBT_AGC_TARG_VAL_0, 0x0},
|
||||||
|
{DVBT_AGC_TARG_VAL_8_1, 0x5a},
|
||||||
|
{DVBT_AAGC_LOOP_GAIN, 0x16},
|
||||||
|
{DVBT_LOOP_GAIN2_3_0, 0x6},
|
||||||
|
{DVBT_LOOP_GAIN2_4, 0x1},
|
||||||
|
{DVBT_LOOP_GAIN3, 0x16},
|
||||||
|
{DVBT_VTOP1, 0x35},
|
||||||
|
{DVBT_VTOP2, 0x21},
|
||||||
|
{DVBT_VTOP3, 0x21},
|
||||||
|
{DVBT_KRF1, 0x0},
|
||||||
|
{DVBT_KRF2, 0x40},
|
||||||
|
{DVBT_KRF3, 0x10},
|
||||||
|
{DVBT_KRF4, 0x10},
|
||||||
|
{DVBT_IF_AGC_MIN, 0x80},
|
||||||
|
{DVBT_IF_AGC_MAX, 0x7f},
|
||||||
|
{DVBT_RF_AGC_MIN, 0x80},
|
||||||
|
{DVBT_RF_AGC_MAX, 0x7f},
|
||||||
|
{DVBT_POLAR_RF_AGC, 0x0},
|
||||||
|
{DVBT_POLAR_IF_AGC, 0x0},
|
||||||
|
{DVBT_AD7_SETTING, 0xe9bf},
|
||||||
|
{DVBT_EN_GI_PGA, 0x0},
|
||||||
|
{DVBT_THD_LOCK_UP, 0x0},
|
||||||
|
{DVBT_THD_LOCK_DW, 0x0},
|
||||||
|
{DVBT_THD_UP1, 0x11},
|
||||||
|
{DVBT_THD_DW1, 0xef},
|
||||||
|
{DVBT_INTER_CNT_LEN, 0xc},
|
||||||
|
{DVBT_GI_PGA_STATE, 0x0},
|
||||||
|
{DVBT_EN_AGC_PGA, 0x1},
|
||||||
|
{DVBT_IF_AGC_MAN, 0x0},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
dbg("%s", __func__);
|
||||||
|
|
||||||
|
en_bbin = (priv->cfg.if_dvbt == 0 ? 0x1 : 0x0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PSET_IFFREQ = - floor((IfFreqHz % CrystalFreqHz) * pow(2, 22)
|
||||||
|
* / CrystalFreqHz)
|
||||||
|
*/
|
||||||
|
pset_iffreq = priv->cfg.if_dvbt % priv->cfg.xtal;
|
||||||
|
pset_iffreq *= 0x400000;
|
||||||
|
pset_iffreq = div_u64(pset_iffreq, priv->cfg.xtal);
|
||||||
|
pset_iffreq = pset_iffreq & 0x3fffff;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(rtl2832_initial_regs); i++) {
|
||||||
|
ret = rtl2832_wr_demod_reg(priv, rtl2832_initial_regs[i].reg,
|
||||||
|
rtl2832_initial_regs[i].value);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if frequency settings */
|
||||||
|
ret = rtl2832_wr_demod_reg(priv, DVBT_EN_BBIN, en_bbin);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
ret = rtl2832_wr_demod_reg(priv, DVBT_PSET_IFFREQ, pset_iffreq);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
priv->sleeping = false;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
err:
|
||||||
|
dbg("%s: failed=%d", __func__, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtl2832_sleep(struct dvb_frontend *fe)
|
||||||
|
{
|
||||||
|
struct rtl2832_priv *priv = fe->demodulator_priv;
|
||||||
|
|
||||||
|
dbg("%s", __func__);
|
||||||
|
priv->sleeping = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtl2832_get_tune_settings(struct dvb_frontend *fe,
|
||||||
|
struct dvb_frontend_tune_settings *s)
|
||||||
|
{
|
||||||
|
dbg("%s", __func__);
|
||||||
|
s->min_delay_ms = 1000;
|
||||||
|
s->step_size = fe->ops.info.frequency_stepsize * 2;
|
||||||
|
s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtl2832_set_frontend(struct dvb_frontend *fe)
|
||||||
|
{
|
||||||
|
struct rtl2832_priv *priv = fe->demodulator_priv;
|
||||||
|
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||||
|
int ret, i, j;
|
||||||
|
u64 bw_mode, num, num2;
|
||||||
|
u32 resamp_ratio, cfreq_off_ratio;
|
||||||
|
|
||||||
|
|
||||||
|
static u8 bw_params[3][32] = {
|
||||||
|
/* 6 MHz bandwidth */
|
||||||
|
{
|
||||||
|
0xf5, 0xff, 0x15, 0x38, 0x5d, 0x6d, 0x52, 0x07, 0xfa, 0x2f,
|
||||||
|
0x53, 0xf5, 0x3f, 0xca, 0x0b, 0x91, 0xea, 0x30, 0x63, 0xb2,
|
||||||
|
0x13, 0xda, 0x0b, 0xc4, 0x18, 0x7e, 0x16, 0x66, 0x08, 0x67,
|
||||||
|
0x19, 0xe0,
|
||||||
|
},
|
||||||
|
|
||||||
|
/* 7 MHz bandwidth */
|
||||||
|
{
|
||||||
|
0xe7, 0xcc, 0xb5, 0xba, 0xe8, 0x2f, 0x67, 0x61, 0x00, 0xaf,
|
||||||
|
0x86, 0xf2, 0xbf, 0x59, 0x04, 0x11, 0xb6, 0x33, 0xa4, 0x30,
|
||||||
|
0x15, 0x10, 0x0a, 0x42, 0x18, 0xf8, 0x17, 0xd9, 0x07, 0x22,
|
||||||
|
0x19, 0x10,
|
||||||
|
},
|
||||||
|
|
||||||
|
/* 8 MHz bandwidth */
|
||||||
|
{
|
||||||
|
0x09, 0xf6, 0xd2, 0xa7, 0x9a, 0xc9, 0x27, 0x77, 0x06, 0xbf,
|
||||||
|
0xec, 0xf4, 0x4f, 0x0b, 0xfc, 0x01, 0x63, 0x35, 0x54, 0xa7,
|
||||||
|
0x16, 0x66, 0x08, 0xb4, 0x19, 0x6e, 0x19, 0x65, 0x05, 0xc8,
|
||||||
|
0x19, 0xe0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
dbg("%s: frequency=%d bandwidth_hz=%d inversion=%d", __func__,
|
||||||
|
c->frequency, c->bandwidth_hz, c->inversion);
|
||||||
|
|
||||||
|
|
||||||
|
/* program tuner */
|
||||||
|
if (fe->ops.tuner_ops.set_params)
|
||||||
|
fe->ops.tuner_ops.set_params(fe);
|
||||||
|
|
||||||
|
|
||||||
|
switch (c->bandwidth_hz) {
|
||||||
|
case 6000000:
|
||||||
|
i = 0;
|
||||||
|
bw_mode = 48000000;
|
||||||
|
break;
|
||||||
|
case 7000000:
|
||||||
|
i = 1;
|
||||||
|
bw_mode = 56000000;
|
||||||
|
break;
|
||||||
|
case 8000000:
|
||||||
|
i = 2;
|
||||||
|
bw_mode = 64000000;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dbg("invalid bandwidth");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < sizeof(bw_params[j]); j++) {
|
||||||
|
ret = rtl2832_wr_regs(priv, 0x1c+j, 1, &bw_params[i][j], 1);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* calculate and set resample ratio
|
||||||
|
* RSAMP_RATIO = floor(CrystalFreqHz * 7 * pow(2, 22)
|
||||||
|
* / ConstWithBandwidthMode)
|
||||||
|
*/
|
||||||
|
num = priv->cfg.xtal * 7;
|
||||||
|
num *= 0x400000;
|
||||||
|
num = div_u64(num, bw_mode);
|
||||||
|
resamp_ratio = num & 0x3ffffff;
|
||||||
|
ret = rtl2832_wr_demod_reg(priv, DVBT_RSAMP_RATIO, resamp_ratio);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/* calculate and set cfreq off ratio
|
||||||
|
* CFREQ_OFF_RATIO = - floor(ConstWithBandwidthMode * pow(2, 20)
|
||||||
|
* / (CrystalFreqHz * 7))
|
||||||
|
*/
|
||||||
|
num = bw_mode << 20;
|
||||||
|
num2 = priv->cfg.xtal * 7;
|
||||||
|
num = div_u64(num, num2);
|
||||||
|
num = -num;
|
||||||
|
cfreq_off_ratio = num & 0xfffff;
|
||||||
|
ret = rtl2832_wr_demod_reg(priv, DVBT_CFREQ_OFF_RATIO, cfreq_off_ratio);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
|
||||||
|
/* soft reset */
|
||||||
|
ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x1);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x0);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
err:
|
||||||
|
info("%s: failed=%d", __func__, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtl2832_read_status(struct dvb_frontend *fe, fe_status_t *status)
|
||||||
|
{
|
||||||
|
struct rtl2832_priv *priv = fe->demodulator_priv;
|
||||||
|
int ret;
|
||||||
|
u32 tmp;
|
||||||
|
*status = 0;
|
||||||
|
|
||||||
|
|
||||||
|
dbg("%s", __func__);
|
||||||
|
if (priv->sleeping)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ret = rtl2832_rd_demod_reg(priv, DVBT_FSM_STAGE, &tmp);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (tmp == 11) {
|
||||||
|
*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
|
||||||
|
FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
|
||||||
|
}
|
||||||
|
/* TODO find out if this is also true for rtl2832? */
|
||||||
|
/*else if (tmp == 10) {
|
||||||
|
*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
|
||||||
|
FE_HAS_VITERBI;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
err:
|
||||||
|
info("%s: failed=%d", __func__, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtl2832_read_snr(struct dvb_frontend *fe, u16 *snr)
|
||||||
|
{
|
||||||
|
*snr = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtl2832_read_ber(struct dvb_frontend *fe, u32 *ber)
|
||||||
|
{
|
||||||
|
*ber = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtl2832_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
|
||||||
|
{
|
||||||
|
*ucblocks = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int rtl2832_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
|
||||||
|
{
|
||||||
|
*strength = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct dvb_frontend_ops rtl2832_ops;
|
||||||
|
|
||||||
|
static void rtl2832_release(struct dvb_frontend *fe)
|
||||||
|
{
|
||||||
|
struct rtl2832_priv *priv = fe->demodulator_priv;
|
||||||
|
|
||||||
|
dbg("%s", __func__);
|
||||||
|
kfree(priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct dvb_frontend *rtl2832_attach(const struct rtl2832_config *cfg,
|
||||||
|
struct i2c_adapter *i2c)
|
||||||
|
{
|
||||||
|
struct rtl2832_priv *priv = NULL;
|
||||||
|
int ret = 0;
|
||||||
|
u8 tmp;
|
||||||
|
|
||||||
|
dbg("%s", __func__);
|
||||||
|
|
||||||
|
/* allocate memory for the internal state */
|
||||||
|
priv = kzalloc(sizeof(struct rtl2832_priv), GFP_KERNEL);
|
||||||
|
if (priv == NULL)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/* setup the priv */
|
||||||
|
priv->i2c = i2c;
|
||||||
|
priv->tuner = cfg->tuner;
|
||||||
|
memcpy(&priv->cfg, cfg, sizeof(struct rtl2832_config));
|
||||||
|
|
||||||
|
/* check if the demod is there */
|
||||||
|
ret = rtl2832_rd_reg(priv, 0x00, 0x0, &tmp);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/* create dvb_frontend */
|
||||||
|
memcpy(&priv->fe.ops, &rtl2832_ops, sizeof(struct dvb_frontend_ops));
|
||||||
|
priv->fe.demodulator_priv = priv;
|
||||||
|
|
||||||
|
/* TODO implement sleep mode */
|
||||||
|
priv->sleeping = true;
|
||||||
|
|
||||||
|
return &priv->fe;
|
||||||
|
err:
|
||||||
|
dbg("%s: failed=%d", __func__, ret);
|
||||||
|
kfree(priv);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(rtl2832_attach);
|
||||||
|
|
||||||
|
static struct dvb_frontend_ops rtl2832_ops = {
|
||||||
|
.delsys = { SYS_DVBT },
|
||||||
|
.info = {
|
||||||
|
.name = "Realtek RTL2832 (DVB-T)",
|
||||||
|
.frequency_min = 174000000,
|
||||||
|
.frequency_max = 862000000,
|
||||||
|
.frequency_stepsize = 166667,
|
||||||
|
.caps = FE_CAN_FEC_1_2 |
|
||||||
|
FE_CAN_FEC_2_3 |
|
||||||
|
FE_CAN_FEC_3_4 |
|
||||||
|
FE_CAN_FEC_5_6 |
|
||||||
|
FE_CAN_FEC_7_8 |
|
||||||
|
FE_CAN_FEC_AUTO |
|
||||||
|
FE_CAN_QPSK |
|
||||||
|
FE_CAN_QAM_16 |
|
||||||
|
FE_CAN_QAM_64 |
|
||||||
|
FE_CAN_QAM_AUTO |
|
||||||
|
FE_CAN_TRANSMISSION_MODE_AUTO |
|
||||||
|
FE_CAN_GUARD_INTERVAL_AUTO |
|
||||||
|
FE_CAN_HIERARCHY_AUTO |
|
||||||
|
FE_CAN_RECOVER |
|
||||||
|
FE_CAN_MUTE_TS
|
||||||
|
},
|
||||||
|
|
||||||
|
.release = rtl2832_release,
|
||||||
|
|
||||||
|
.init = rtl2832_init,
|
||||||
|
.sleep = rtl2832_sleep,
|
||||||
|
|
||||||
|
.get_tune_settings = rtl2832_get_tune_settings,
|
||||||
|
|
||||||
|
.set_frontend = rtl2832_set_frontend,
|
||||||
|
|
||||||
|
.read_status = rtl2832_read_status,
|
||||||
|
.read_snr = rtl2832_read_snr,
|
||||||
|
.read_ber = rtl2832_read_ber,
|
||||||
|
.read_ucblocks = rtl2832_read_ucblocks,
|
||||||
|
.read_signal_strength = rtl2832_read_signal_strength,
|
||||||
|
.i2c_gate_ctrl = rtl2832_i2c_gate_ctrl,
|
||||||
|
};
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Thomas Mair <mair.thomas86@gmail.com>");
|
||||||
|
MODULE_DESCRIPTION("Realtek RTL2832 DVB-T demodulator driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
MODULE_VERSION("0.5");
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* Realtek RTL2832 DVB-T demodulator driver
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Thomas Mair <thomas.mair86@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RTL2832_H
|
||||||
|
#define RTL2832_H
|
||||||
|
|
||||||
|
#include <linux/dvb/frontend.h>
|
||||||
|
|
||||||
|
struct rtl2832_config {
|
||||||
|
/*
|
||||||
|
* Demodulator I2C address.
|
||||||
|
*/
|
||||||
|
u8 i2c_addr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Xtal frequency.
|
||||||
|
* Hz
|
||||||
|
* 4000000, 16000000, 25000000, 28800000
|
||||||
|
*/
|
||||||
|
u32 xtal;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IFs for all used modes.
|
||||||
|
* Hz
|
||||||
|
* 4570000, 4571429, 36000000, 36125000, 36166667, 44000000
|
||||||
|
*/
|
||||||
|
u32 if_dvbt;
|
||||||
|
|
||||||
|
/*
|
||||||
|
*/
|
||||||
|
u8 tuner;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(CONFIG_DVB_RTL2832) || \
|
||||||
|
(defined(CONFIG_DVB_RTL2832_MODULE) && defined(MODULE))
|
||||||
|
extern struct dvb_frontend *rtl2832_attach(
|
||||||
|
const struct rtl2832_config *cfg,
|
||||||
|
struct i2c_adapter *i2c
|
||||||
|
);
|
||||||
|
|
||||||
|
extern struct i2c_adapter *rtl2832_get_tuner_i2c_adapter(
|
||||||
|
struct dvb_frontend *fe
|
||||||
|
);
|
||||||
|
#else
|
||||||
|
static inline struct dvb_frontend *rtl2832_attach(
|
||||||
|
const struct rtl2832_config *config,
|
||||||
|
struct i2c_adapter *i2c
|
||||||
|
)
|
||||||
|
{
|
||||||
|
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* RTL2832_H */
|
|
@ -0,0 +1,260 @@
|
||||||
|
/*
|
||||||
|
* Realtek RTL2832 DVB-T demodulator driver
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Thomas Mair <thomas.mair86@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RTL2832_PRIV_H
|
||||||
|
#define RTL2832_PRIV_H
|
||||||
|
|
||||||
|
#include "dvb_frontend.h"
|
||||||
|
#include "rtl2832.h"
|
||||||
|
|
||||||
|
#define LOG_PREFIX "rtl2832"
|
||||||
|
|
||||||
|
#undef dbg
|
||||||
|
#define dbg(f, arg...) \
|
||||||
|
do { \
|
||||||
|
if (rtl2832_debug) \
|
||||||
|
printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg); \
|
||||||
|
} while (0)
|
||||||
|
#undef err
|
||||||
|
#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg)
|
||||||
|
#undef info
|
||||||
|
#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg)
|
||||||
|
#undef warn
|
||||||
|
#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
|
||||||
|
|
||||||
|
struct rtl2832_priv {
|
||||||
|
struct i2c_adapter *i2c;
|
||||||
|
struct dvb_frontend fe;
|
||||||
|
struct rtl2832_config cfg;
|
||||||
|
|
||||||
|
bool i2c_gate_state;
|
||||||
|
bool sleeping;
|
||||||
|
|
||||||
|
u8 tuner;
|
||||||
|
u8 page; /* active register page */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rtl2832_reg_entry {
|
||||||
|
u8 page;
|
||||||
|
u8 start_address;
|
||||||
|
u8 msb;
|
||||||
|
u8 lsb;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rtl2832_reg_value {
|
||||||
|
int reg;
|
||||||
|
u32 value;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Demod register bit names */
|
||||||
|
enum DVBT_REG_BIT_NAME {
|
||||||
|
DVBT_SOFT_RST,
|
||||||
|
DVBT_IIC_REPEAT,
|
||||||
|
DVBT_TR_WAIT_MIN_8K,
|
||||||
|
DVBT_RSD_BER_FAIL_VAL,
|
||||||
|
DVBT_EN_BK_TRK,
|
||||||
|
DVBT_REG_PI,
|
||||||
|
DVBT_REG_PFREQ_1_0,
|
||||||
|
DVBT_PD_DA8,
|
||||||
|
DVBT_LOCK_TH,
|
||||||
|
DVBT_BER_PASS_SCAL,
|
||||||
|
DVBT_CE_FFSM_BYPASS,
|
||||||
|
DVBT_ALPHAIIR_N,
|
||||||
|
DVBT_ALPHAIIR_DIF,
|
||||||
|
DVBT_EN_TRK_SPAN,
|
||||||
|
DVBT_LOCK_TH_LEN,
|
||||||
|
DVBT_CCI_THRE,
|
||||||
|
DVBT_CCI_MON_SCAL,
|
||||||
|
DVBT_CCI_M0,
|
||||||
|
DVBT_CCI_M1,
|
||||||
|
DVBT_CCI_M2,
|
||||||
|
DVBT_CCI_M3,
|
||||||
|
DVBT_SPEC_INIT_0,
|
||||||
|
DVBT_SPEC_INIT_1,
|
||||||
|
DVBT_SPEC_INIT_2,
|
||||||
|
DVBT_AD_EN_REG,
|
||||||
|
DVBT_AD_EN_REG1,
|
||||||
|
DVBT_EN_BBIN,
|
||||||
|
DVBT_MGD_THD0,
|
||||||
|
DVBT_MGD_THD1,
|
||||||
|
DVBT_MGD_THD2,
|
||||||
|
DVBT_MGD_THD3,
|
||||||
|
DVBT_MGD_THD4,
|
||||||
|
DVBT_MGD_THD5,
|
||||||
|
DVBT_MGD_THD6,
|
||||||
|
DVBT_MGD_THD7,
|
||||||
|
DVBT_EN_CACQ_NOTCH,
|
||||||
|
DVBT_AD_AV_REF,
|
||||||
|
DVBT_PIP_ON,
|
||||||
|
DVBT_SCALE1_B92,
|
||||||
|
DVBT_SCALE1_B93,
|
||||||
|
DVBT_SCALE1_BA7,
|
||||||
|
DVBT_SCALE1_BA9,
|
||||||
|
DVBT_SCALE1_BAA,
|
||||||
|
DVBT_SCALE1_BAB,
|
||||||
|
DVBT_SCALE1_BAC,
|
||||||
|
DVBT_SCALE1_BB0,
|
||||||
|
DVBT_SCALE1_BB1,
|
||||||
|
DVBT_KB_P1,
|
||||||
|
DVBT_KB_P2,
|
||||||
|
DVBT_KB_P3,
|
||||||
|
DVBT_OPT_ADC_IQ,
|
||||||
|
DVBT_AD_AVI,
|
||||||
|
DVBT_AD_AVQ,
|
||||||
|
DVBT_K1_CR_STEP12,
|
||||||
|
DVBT_TRK_KS_P2,
|
||||||
|
DVBT_TRK_KS_I2,
|
||||||
|
DVBT_TR_THD_SET2,
|
||||||
|
DVBT_TRK_KC_P2,
|
||||||
|
DVBT_TRK_KC_I2,
|
||||||
|
DVBT_CR_THD_SET2,
|
||||||
|
DVBT_PSET_IFFREQ,
|
||||||
|
DVBT_SPEC_INV,
|
||||||
|
DVBT_BW_INDEX,
|
||||||
|
DVBT_RSAMP_RATIO,
|
||||||
|
DVBT_CFREQ_OFF_RATIO,
|
||||||
|
DVBT_FSM_STAGE,
|
||||||
|
DVBT_RX_CONSTEL,
|
||||||
|
DVBT_RX_HIER,
|
||||||
|
DVBT_RX_C_RATE_LP,
|
||||||
|
DVBT_RX_C_RATE_HP,
|
||||||
|
DVBT_GI_IDX,
|
||||||
|
DVBT_FFT_MODE_IDX,
|
||||||
|
DVBT_RSD_BER_EST,
|
||||||
|
DVBT_CE_EST_EVM,
|
||||||
|
DVBT_RF_AGC_VAL,
|
||||||
|
DVBT_IF_AGC_VAL,
|
||||||
|
DVBT_DAGC_VAL,
|
||||||
|
DVBT_SFREQ_OFF,
|
||||||
|
DVBT_CFREQ_OFF,
|
||||||
|
DVBT_POLAR_RF_AGC,
|
||||||
|
DVBT_POLAR_IF_AGC,
|
||||||
|
DVBT_AAGC_HOLD,
|
||||||
|
DVBT_EN_RF_AGC,
|
||||||
|
DVBT_EN_IF_AGC,
|
||||||
|
DVBT_IF_AGC_MIN,
|
||||||
|
DVBT_IF_AGC_MAX,
|
||||||
|
DVBT_RF_AGC_MIN,
|
||||||
|
DVBT_RF_AGC_MAX,
|
||||||
|
DVBT_IF_AGC_MAN,
|
||||||
|
DVBT_IF_AGC_MAN_VAL,
|
||||||
|
DVBT_RF_AGC_MAN,
|
||||||
|
DVBT_RF_AGC_MAN_VAL,
|
||||||
|
DVBT_DAGC_TRG_VAL,
|
||||||
|
DVBT_AGC_TARG_VAL,
|
||||||
|
DVBT_LOOP_GAIN_3_0,
|
||||||
|
DVBT_LOOP_GAIN_4,
|
||||||
|
DVBT_VTOP,
|
||||||
|
DVBT_KRF,
|
||||||
|
DVBT_AGC_TARG_VAL_0,
|
||||||
|
DVBT_AGC_TARG_VAL_8_1,
|
||||||
|
DVBT_AAGC_LOOP_GAIN,
|
||||||
|
DVBT_LOOP_GAIN2_3_0,
|
||||||
|
DVBT_LOOP_GAIN2_4,
|
||||||
|
DVBT_LOOP_GAIN3,
|
||||||
|
DVBT_VTOP1,
|
||||||
|
DVBT_VTOP2,
|
||||||
|
DVBT_VTOP3,
|
||||||
|
DVBT_KRF1,
|
||||||
|
DVBT_KRF2,
|
||||||
|
DVBT_KRF3,
|
||||||
|
DVBT_KRF4,
|
||||||
|
DVBT_EN_GI_PGA,
|
||||||
|
DVBT_THD_LOCK_UP,
|
||||||
|
DVBT_THD_LOCK_DW,
|
||||||
|
DVBT_THD_UP1,
|
||||||
|
DVBT_THD_DW1,
|
||||||
|
DVBT_INTER_CNT_LEN,
|
||||||
|
DVBT_GI_PGA_STATE,
|
||||||
|
DVBT_EN_AGC_PGA,
|
||||||
|
DVBT_CKOUTPAR,
|
||||||
|
DVBT_CKOUT_PWR,
|
||||||
|
DVBT_SYNC_DUR,
|
||||||
|
DVBT_ERR_DUR,
|
||||||
|
DVBT_SYNC_LVL,
|
||||||
|
DVBT_ERR_LVL,
|
||||||
|
DVBT_VAL_LVL,
|
||||||
|
DVBT_SERIAL,
|
||||||
|
DVBT_SER_LSB,
|
||||||
|
DVBT_CDIV_PH0,
|
||||||
|
DVBT_CDIV_PH1,
|
||||||
|
DVBT_MPEG_IO_OPT_2_2,
|
||||||
|
DVBT_MPEG_IO_OPT_1_0,
|
||||||
|
DVBT_CKOUTPAR_PIP,
|
||||||
|
DVBT_CKOUT_PWR_PIP,
|
||||||
|
DVBT_SYNC_LVL_PIP,
|
||||||
|
DVBT_ERR_LVL_PIP,
|
||||||
|
DVBT_VAL_LVL_PIP,
|
||||||
|
DVBT_CKOUTPAR_PID,
|
||||||
|
DVBT_CKOUT_PWR_PID,
|
||||||
|
DVBT_SYNC_LVL_PID,
|
||||||
|
DVBT_ERR_LVL_PID,
|
||||||
|
DVBT_VAL_LVL_PID,
|
||||||
|
DVBT_SM_PASS,
|
||||||
|
DVBT_UPDATE_REG_2,
|
||||||
|
DVBT_BTHD_P3,
|
||||||
|
DVBT_BTHD_D3,
|
||||||
|
DVBT_FUNC4_REG0,
|
||||||
|
DVBT_FUNC4_REG1,
|
||||||
|
DVBT_FUNC4_REG2,
|
||||||
|
DVBT_FUNC4_REG3,
|
||||||
|
DVBT_FUNC4_REG4,
|
||||||
|
DVBT_FUNC4_REG5,
|
||||||
|
DVBT_FUNC4_REG6,
|
||||||
|
DVBT_FUNC4_REG7,
|
||||||
|
DVBT_FUNC4_REG8,
|
||||||
|
DVBT_FUNC4_REG9,
|
||||||
|
DVBT_FUNC4_REG10,
|
||||||
|
DVBT_FUNC5_REG0,
|
||||||
|
DVBT_FUNC5_REG1,
|
||||||
|
DVBT_FUNC5_REG2,
|
||||||
|
DVBT_FUNC5_REG3,
|
||||||
|
DVBT_FUNC5_REG4,
|
||||||
|
DVBT_FUNC5_REG5,
|
||||||
|
DVBT_FUNC5_REG6,
|
||||||
|
DVBT_FUNC5_REG7,
|
||||||
|
DVBT_FUNC5_REG8,
|
||||||
|
DVBT_FUNC5_REG9,
|
||||||
|
DVBT_FUNC5_REG10,
|
||||||
|
DVBT_FUNC5_REG11,
|
||||||
|
DVBT_FUNC5_REG12,
|
||||||
|
DVBT_FUNC5_REG13,
|
||||||
|
DVBT_FUNC5_REG14,
|
||||||
|
DVBT_FUNC5_REG15,
|
||||||
|
DVBT_FUNC5_REG16,
|
||||||
|
DVBT_FUNC5_REG17,
|
||||||
|
DVBT_FUNC5_REG18,
|
||||||
|
DVBT_AD7_SETTING,
|
||||||
|
DVBT_RSSI_R,
|
||||||
|
DVBT_ACI_DET_IND,
|
||||||
|
DVBT_REG_MON,
|
||||||
|
DVBT_REG_MONSEL,
|
||||||
|
DVBT_REG_GPE,
|
||||||
|
DVBT_REG_GPO,
|
||||||
|
DVBT_REG_4MSEL,
|
||||||
|
DVBT_TEST_REG_1,
|
||||||
|
DVBT_TEST_REG_2,
|
||||||
|
DVBT_TEST_REG_3,
|
||||||
|
DVBT_TEST_REG_4,
|
||||||
|
DVBT_REG_BIT_NAME_ITEM_TERMINATOR,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* RTL2832_PRIV_H */
|
|
@ -634,7 +634,6 @@ static int s5h1420_set_frontend(struct dvb_frontend *fe)
|
||||||
struct s5h1420_state* state = fe->demodulator_priv;
|
struct s5h1420_state* state = fe->demodulator_priv;
|
||||||
int frequency_delta;
|
int frequency_delta;
|
||||||
struct dvb_frontend_tune_settings fesettings;
|
struct dvb_frontend_tune_settings fesettings;
|
||||||
uint8_t clock_setting;
|
|
||||||
|
|
||||||
dprintk("enter %s\n", __func__);
|
dprintk("enter %s\n", __func__);
|
||||||
|
|
||||||
|
@ -679,25 +678,6 @@ static int s5h1420_set_frontend(struct dvb_frontend *fe)
|
||||||
else
|
else
|
||||||
state->fclk = 44000000;
|
state->fclk = 44000000;
|
||||||
|
|
||||||
/* Clock */
|
|
||||||
switch (state->fclk) {
|
|
||||||
default:
|
|
||||||
case 88000000:
|
|
||||||
clock_setting = 80;
|
|
||||||
break;
|
|
||||||
case 86000000:
|
|
||||||
clock_setting = 78;
|
|
||||||
break;
|
|
||||||
case 80000000:
|
|
||||||
clock_setting = 72;
|
|
||||||
break;
|
|
||||||
case 59000000:
|
|
||||||
clock_setting = 51;
|
|
||||||
break;
|
|
||||||
case 44000000:
|
|
||||||
clock_setting = 36;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
dprintk("pll01: %d, ToneFreq: %d\n", state->fclk/1000000 - 8, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32));
|
dprintk("pll01: %d, ToneFreq: %d\n", state->fclk/1000000 - 8, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32));
|
||||||
s5h1420_writereg(state, PLL01, state->fclk/1000000 - 8);
|
s5h1420_writereg(state, PLL01, state->fclk/1000000 - 8);
|
||||||
s5h1420_writereg(state, PLL02, 0x40);
|
s5h1420_writereg(state, PLL02, 0x40);
|
||||||
|
|
|
@ -1129,7 +1129,6 @@ static int stb0899_read_ber(struct dvb_frontend *fe, u32 *ber)
|
||||||
struct stb0899_internal *internal = &state->internal;
|
struct stb0899_internal *internal = &state->internal;
|
||||||
|
|
||||||
u8 lsb, msb;
|
u8 lsb, msb;
|
||||||
u32 i;
|
|
||||||
|
|
||||||
*ber = 0;
|
*ber = 0;
|
||||||
|
|
||||||
|
@ -1137,14 +1136,9 @@ static int stb0899_read_ber(struct dvb_frontend *fe, u32 *ber)
|
||||||
case SYS_DVBS:
|
case SYS_DVBS:
|
||||||
case SYS_DSS:
|
case SYS_DSS:
|
||||||
if (internal->lock) {
|
if (internal->lock) {
|
||||||
/* average 5 BER values */
|
lsb = stb0899_read_reg(state, STB0899_ECNT1L);
|
||||||
for (i = 0; i < 5; i++) {
|
msb = stb0899_read_reg(state, STB0899_ECNT1M);
|
||||||
msleep(100);
|
*ber = MAKEWORD16(msb, lsb);
|
||||||
lsb = stb0899_read_reg(state, STB0899_ECNT1L);
|
|
||||||
msb = stb0899_read_reg(state, STB0899_ECNT1M);
|
|
||||||
*ber += MAKEWORD16(msb, lsb);
|
|
||||||
}
|
|
||||||
*ber /= 5;
|
|
||||||
/* Viterbi Check */
|
/* Viterbi Check */
|
||||||
if (STB0899_GETFIELD(VSTATUS_PRFVIT, internal->v_status)) {
|
if (STB0899_GETFIELD(VSTATUS_PRFVIT, internal->v_status)) {
|
||||||
/* Error Rate */
|
/* Error Rate */
|
||||||
|
@ -1157,13 +1151,9 @@ static int stb0899_read_ber(struct dvb_frontend *fe, u32 *ber)
|
||||||
break;
|
break;
|
||||||
case SYS_DVBS2:
|
case SYS_DVBS2:
|
||||||
if (internal->lock) {
|
if (internal->lock) {
|
||||||
/* Average 5 PER values */
|
lsb = stb0899_read_reg(state, STB0899_ECNT1L);
|
||||||
for (i = 0; i < 5; i++) {
|
msb = stb0899_read_reg(state, STB0899_ECNT1M);
|
||||||
msleep(100);
|
*ber = MAKEWORD16(msb, lsb);
|
||||||
lsb = stb0899_read_reg(state, STB0899_ECNT1L);
|
|
||||||
msb = stb0899_read_reg(state, STB0899_ECNT1M);
|
|
||||||
*ber += MAKEWORD16(msb, lsb);
|
|
||||||
}
|
|
||||||
/* ber = ber * 10 ^ 7 */
|
/* ber = ber * 10 ^ 7 */
|
||||||
*ber *= 10000000;
|
*ber *= 10000000;
|
||||||
*ber /= (-1 + (1 << (4 + 2 * STB0899_GETFIELD(NOE, internal->err_ctrl))));
|
*ber /= (-1 + (1 << (4 + 2 * STB0899_GETFIELD(NOE, internal->err_ctrl))));
|
||||||
|
|
|
@ -1584,7 +1584,7 @@ static int stv0367ter_algo(struct dvb_frontend *fe)
|
||||||
struct stv0367ter_state *ter_state = state->ter_state;
|
struct stv0367ter_state *ter_state = state->ter_state;
|
||||||
int offset = 0, tempo = 0;
|
int offset = 0, tempo = 0;
|
||||||
u8 u_var;
|
u8 u_var;
|
||||||
u8 /*constell,*/ counter, tps_rcvd[2];
|
u8 /*constell,*/ counter;
|
||||||
s8 step;
|
s8 step;
|
||||||
s32 timing_offset = 0;
|
s32 timing_offset = 0;
|
||||||
u32 trl_nomrate = 0, InternalFreq = 0, temp = 0;
|
u32 trl_nomrate = 0, InternalFreq = 0, temp = 0;
|
||||||
|
@ -1709,9 +1709,6 @@ static int stv0367ter_algo(struct dvb_frontend *fe)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ter_state->state = FE_TER_LOCKOK;
|
ter_state->state = FE_TER_LOCKOK;
|
||||||
/* update results */
|
|
||||||
tps_rcvd[0] = stv0367_readreg(state, R367TER_TPS_RCVD2);
|
|
||||||
tps_rcvd[1] = stv0367_readreg(state, R367TER_TPS_RCVD3);
|
|
||||||
|
|
||||||
ter_state->mode = stv0367_readbits(state, F367TER_SYR_MODE);
|
ter_state->mode = stv0367_readbits(state, F367TER_SYR_MODE);
|
||||||
ter_state->guard = stv0367_readbits(state, F367TER_SYR_GUARD);
|
ter_state->guard = stv0367_readbits(state, F367TER_SYR_GUARD);
|
||||||
|
|
|
@ -3172,7 +3172,7 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state)
|
||||||
enum stv090x_signal_state signal_state = STV090x_NOCARRIER;
|
enum stv090x_signal_state signal_state = STV090x_NOCARRIER;
|
||||||
u32 reg;
|
u32 reg;
|
||||||
s32 agc1_power, power_iq = 0, i;
|
s32 agc1_power, power_iq = 0, i;
|
||||||
int lock = 0, low_sr = 0, no_signal = 0;
|
int lock = 0, low_sr = 0;
|
||||||
|
|
||||||
reg = STV090x_READ_DEMOD(state, TSCFGH);
|
reg = STV090x_READ_DEMOD(state, TSCFGH);
|
||||||
STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 1); /* Stop path 1 stream merger */
|
STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 1); /* Stop path 1 stream merger */
|
||||||
|
@ -3413,7 +3413,7 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state)
|
||||||
goto err;
|
goto err;
|
||||||
} else {
|
} else {
|
||||||
signal_state = STV090x_NODATA;
|
signal_state = STV090x_NODATA;
|
||||||
no_signal = stv090x_chk_signal(state);
|
stv090x_chk_signal(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return signal_state;
|
return signal_state;
|
||||||
|
|
|
@ -20,10 +20,6 @@
|
||||||
|
|
||||||
#include "tda10071_priv.h"
|
#include "tda10071_priv.h"
|
||||||
|
|
||||||
int tda10071_debug;
|
|
||||||
module_param_named(debug, tda10071_debug, int, 0644);
|
|
||||||
MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
|
|
||||||
|
|
||||||
static struct dvb_frontend_ops tda10071_ops;
|
static struct dvb_frontend_ops tda10071_ops;
|
||||||
|
|
||||||
/* write multiple registers */
|
/* write multiple registers */
|
||||||
|
@ -48,7 +44,8 @@ static int tda10071_wr_regs(struct tda10071_priv *priv, u8 reg, u8 *val,
|
||||||
if (ret == 1) {
|
if (ret == 1) {
|
||||||
ret = 0;
|
ret = 0;
|
||||||
} else {
|
} else {
|
||||||
warn("i2c wr failed=%d reg=%02x len=%d", ret, reg, len);
|
dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \
|
||||||
|
"len=%d\n", KBUILD_MODNAME, ret, reg, len);
|
||||||
ret = -EREMOTEIO;
|
ret = -EREMOTEIO;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -79,7 +76,8 @@ static int tda10071_rd_regs(struct tda10071_priv *priv, u8 reg, u8 *val,
|
||||||
memcpy(val, buf, len);
|
memcpy(val, buf, len);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
} else {
|
} else {
|
||||||
warn("i2c rd failed=%d reg=%02x len=%d", ret, reg, len);
|
dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \
|
||||||
|
"len=%d\n", KBUILD_MODNAME, ret, reg, len);
|
||||||
ret = -EREMOTEIO;
|
ret = -EREMOTEIO;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -170,7 +168,7 @@ static int tda10071_cmd_execute(struct tda10071_priv *priv,
|
||||||
usleep_range(200, 5000);
|
usleep_range(200, 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg("%s: loop=%d", __func__, i);
|
dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i);
|
||||||
|
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
ret = -ETIMEDOUT;
|
ret = -ETIMEDOUT;
|
||||||
|
@ -179,7 +177,7 @@ static int tda10071_cmd_execute(struct tda10071_priv *priv,
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
error:
|
error:
|
||||||
dbg("%s: failed=%d", __func__, ret);
|
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,7 +194,8 @@ static int tda10071_set_tone(struct dvb_frontend *fe,
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg("%s: tone_mode=%d", __func__, fe_sec_tone_mode);
|
dev_dbg(&priv->i2c->dev, "%s: tone_mode=%d\n", __func__,
|
||||||
|
fe_sec_tone_mode);
|
||||||
|
|
||||||
switch (fe_sec_tone_mode) {
|
switch (fe_sec_tone_mode) {
|
||||||
case SEC_TONE_ON:
|
case SEC_TONE_ON:
|
||||||
|
@ -206,24 +205,25 @@ static int tda10071_set_tone(struct dvb_frontend *fe,
|
||||||
tone = 0;
|
tone = 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dbg("%s: invalid fe_sec_tone_mode", __func__);
|
dev_dbg(&priv->i2c->dev, "%s: invalid fe_sec_tone_mode\n",
|
||||||
|
__func__);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.args[0x00] = CMD_LNB_PCB_CONFIG;
|
cmd.args[0] = CMD_LNB_PCB_CONFIG;
|
||||||
cmd.args[0x01] = 0;
|
cmd.args[1] = 0;
|
||||||
cmd.args[0x02] = 0x00;
|
cmd.args[2] = 0x00;
|
||||||
cmd.args[0x03] = 0x00;
|
cmd.args[3] = 0x00;
|
||||||
cmd.args[0x04] = tone;
|
cmd.args[4] = tone;
|
||||||
cmd.len = 0x05;
|
cmd.len = 5;
|
||||||
ret = tda10071_cmd_execute(priv, &cmd);
|
ret = tda10071_cmd_execute(priv, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
error:
|
error:
|
||||||
dbg("%s: failed=%d", __func__, ret);
|
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,7 +240,7 @@ static int tda10071_set_voltage(struct dvb_frontend *fe,
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg("%s: voltage=%d", __func__, fe_sec_voltage);
|
dev_dbg(&priv->i2c->dev, "%s: voltage=%d\n", __func__, fe_sec_voltage);
|
||||||
|
|
||||||
switch (fe_sec_voltage) {
|
switch (fe_sec_voltage) {
|
||||||
case SEC_VOLTAGE_13:
|
case SEC_VOLTAGE_13:
|
||||||
|
@ -253,22 +253,23 @@ static int tda10071_set_voltage(struct dvb_frontend *fe,
|
||||||
voltage = 0;
|
voltage = 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dbg("%s: invalid fe_sec_voltage", __func__);
|
dev_dbg(&priv->i2c->dev, "%s: invalid fe_sec_voltage\n",
|
||||||
|
__func__);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto error;
|
goto error;
|
||||||
};
|
};
|
||||||
|
|
||||||
cmd.args[0x00] = CMD_LNB_SET_DC_LEVEL;
|
cmd.args[0] = CMD_LNB_SET_DC_LEVEL;
|
||||||
cmd.args[0x01] = 0;
|
cmd.args[1] = 0;
|
||||||
cmd.args[0x02] = voltage;
|
cmd.args[2] = voltage;
|
||||||
cmd.len = 0x03;
|
cmd.len = 3;
|
||||||
ret = tda10071_cmd_execute(priv, &cmd);
|
ret = tda10071_cmd_execute(priv, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
error:
|
error:
|
||||||
dbg("%s: failed=%d", __func__, ret);
|
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,9 +286,10 @@ static int tda10071_diseqc_send_master_cmd(struct dvb_frontend *fe,
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg("%s: msg_len=%d", __func__, diseqc_cmd->msg_len);
|
dev_dbg(&priv->i2c->dev, "%s: msg_len=%d\n", __func__,
|
||||||
|
diseqc_cmd->msg_len);
|
||||||
|
|
||||||
if (diseqc_cmd->msg_len < 3 || diseqc_cmd->msg_len > 16) {
|
if (diseqc_cmd->msg_len < 3 || diseqc_cmd->msg_len > 6) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -301,7 +303,7 @@ static int tda10071_diseqc_send_master_cmd(struct dvb_frontend *fe,
|
||||||
usleep_range(10000, 20000);
|
usleep_range(10000, 20000);
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg("%s: loop=%d", __func__, i);
|
dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i);
|
||||||
|
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
ret = -ETIMEDOUT;
|
ret = -ETIMEDOUT;
|
||||||
|
@ -312,22 +314,22 @@ static int tda10071_diseqc_send_master_cmd(struct dvb_frontend *fe,
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
cmd.args[0x00] = CMD_LNB_SEND_DISEQC;
|
cmd.args[0] = CMD_LNB_SEND_DISEQC;
|
||||||
cmd.args[0x01] = 0;
|
cmd.args[1] = 0;
|
||||||
cmd.args[0x02] = 0;
|
cmd.args[2] = 0;
|
||||||
cmd.args[0x03] = 0;
|
cmd.args[3] = 0;
|
||||||
cmd.args[0x04] = 2;
|
cmd.args[4] = 2;
|
||||||
cmd.args[0x05] = 0;
|
cmd.args[5] = 0;
|
||||||
cmd.args[0x06] = diseqc_cmd->msg_len;
|
cmd.args[6] = diseqc_cmd->msg_len;
|
||||||
memcpy(&cmd.args[0x07], diseqc_cmd->msg, diseqc_cmd->msg_len);
|
memcpy(&cmd.args[7], diseqc_cmd->msg, diseqc_cmd->msg_len);
|
||||||
cmd.len = 0x07 + diseqc_cmd->msg_len;
|
cmd.len = 7 + diseqc_cmd->msg_len;
|
||||||
ret = tda10071_cmd_execute(priv, &cmd);
|
ret = tda10071_cmd_execute(priv, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
error:
|
error:
|
||||||
dbg("%s: failed=%d", __func__, ret);
|
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,7 +346,7 @@ static int tda10071_diseqc_recv_slave_reply(struct dvb_frontend *fe,
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg("%s:", __func__);
|
dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
|
||||||
|
|
||||||
/* wait LNB RX */
|
/* wait LNB RX */
|
||||||
for (i = 500, tmp = 0; i && !tmp; i--) {
|
for (i = 500, tmp = 0; i && !tmp; i--) {
|
||||||
|
@ -355,7 +357,7 @@ static int tda10071_diseqc_recv_slave_reply(struct dvb_frontend *fe,
|
||||||
usleep_range(10000, 20000);
|
usleep_range(10000, 20000);
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg("%s: loop=%d", __func__, i);
|
dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i);
|
||||||
|
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
ret = -ETIMEDOUT;
|
ret = -ETIMEDOUT;
|
||||||
|
@ -372,9 +374,9 @@ static int tda10071_diseqc_recv_slave_reply(struct dvb_frontend *fe,
|
||||||
reply->msg_len = sizeof(reply->msg); /* truncate API max */
|
reply->msg_len = sizeof(reply->msg); /* truncate API max */
|
||||||
|
|
||||||
/* read reply */
|
/* read reply */
|
||||||
cmd.args[0x00] = CMD_LNB_UPDATE_REPLY;
|
cmd.args[0] = CMD_LNB_UPDATE_REPLY;
|
||||||
cmd.args[0x01] = 0;
|
cmd.args[1] = 0;
|
||||||
cmd.len = 0x02;
|
cmd.len = 2;
|
||||||
ret = tda10071_cmd_execute(priv, &cmd);
|
ret = tda10071_cmd_execute(priv, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -385,7 +387,7 @@ static int tda10071_diseqc_recv_slave_reply(struct dvb_frontend *fe,
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
error:
|
error:
|
||||||
dbg("%s: failed=%d", __func__, ret);
|
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -402,7 +404,8 @@ static int tda10071_diseqc_send_burst(struct dvb_frontend *fe,
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg("%s: fe_sec_mini_cmd=%d", __func__, fe_sec_mini_cmd);
|
dev_dbg(&priv->i2c->dev, "%s: fe_sec_mini_cmd=%d\n", __func__,
|
||||||
|
fe_sec_mini_cmd);
|
||||||
|
|
||||||
switch (fe_sec_mini_cmd) {
|
switch (fe_sec_mini_cmd) {
|
||||||
case SEC_MINI_A:
|
case SEC_MINI_A:
|
||||||
|
@ -412,7 +415,8 @@ static int tda10071_diseqc_send_burst(struct dvb_frontend *fe,
|
||||||
burst = 1;
|
burst = 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dbg("%s: invalid fe_sec_mini_cmd", __func__);
|
dev_dbg(&priv->i2c->dev, "%s: invalid fe_sec_mini_cmd\n",
|
||||||
|
__func__);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -426,7 +430,7 @@ static int tda10071_diseqc_send_burst(struct dvb_frontend *fe,
|
||||||
usleep_range(10000, 20000);
|
usleep_range(10000, 20000);
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg("%s: loop=%d", __func__, i);
|
dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i);
|
||||||
|
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
ret = -ETIMEDOUT;
|
ret = -ETIMEDOUT;
|
||||||
|
@ -437,17 +441,17 @@ static int tda10071_diseqc_send_burst(struct dvb_frontend *fe,
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
cmd.args[0x00] = CMD_LNB_SEND_TONEBURST;
|
cmd.args[0] = CMD_LNB_SEND_TONEBURST;
|
||||||
cmd.args[0x01] = 0;
|
cmd.args[1] = 0;
|
||||||
cmd.args[0x02] = burst;
|
cmd.args[2] = burst;
|
||||||
cmd.len = 0x03;
|
cmd.len = 3;
|
||||||
ret = tda10071_cmd_execute(priv, &cmd);
|
ret = tda10071_cmd_execute(priv, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
error:
|
error:
|
||||||
dbg("%s: failed=%d", __func__, ret);
|
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -481,7 +485,7 @@ static int tda10071_read_status(struct dvb_frontend *fe, fe_status_t *status)
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
error:
|
error:
|
||||||
dbg("%s: failed=%d", __func__, ret);
|
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -506,7 +510,7 @@ static int tda10071_read_snr(struct dvb_frontend *fe, u16 *snr)
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
error:
|
error:
|
||||||
dbg("%s: failed=%d", __func__, ret);
|
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -523,9 +527,9 @@ static int tda10071_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.args[0x00] = CMD_GET_AGCACC;
|
cmd.args[0] = CMD_GET_AGCACC;
|
||||||
cmd.args[0x01] = 0;
|
cmd.args[1] = 0;
|
||||||
cmd.len = 0x02;
|
cmd.len = 2;
|
||||||
ret = tda10071_cmd_execute(priv, &cmd);
|
ret = tda10071_cmd_execute(priv, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -545,7 +549,7 @@ static int tda10071_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
error:
|
error:
|
||||||
dbg("%s: failed=%d", __func__, ret);
|
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -583,17 +587,18 @@ static int tda10071_read_ber(struct dvb_frontend *fe, u32 *ber)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (priv->meas_count[i] == tmp) {
|
if (priv->meas_count[i] == tmp) {
|
||||||
dbg("%s: meas not ready=%02x", __func__, tmp);
|
dev_dbg(&priv->i2c->dev, "%s: meas not ready=%02x\n", __func__,
|
||||||
|
tmp);
|
||||||
*ber = priv->ber;
|
*ber = priv->ber;
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
priv->meas_count[i] = tmp;
|
priv->meas_count[i] = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.args[0x00] = CMD_BER_UPDATE_COUNTERS;
|
cmd.args[0] = CMD_BER_UPDATE_COUNTERS;
|
||||||
cmd.args[0x01] = 0;
|
cmd.args[1] = 0;
|
||||||
cmd.args[0x02] = i;
|
cmd.args[2] = i;
|
||||||
cmd.len = 0x03;
|
cmd.len = 3;
|
||||||
ret = tda10071_cmd_execute(priv, &cmd);
|
ret = tda10071_cmd_execute(priv, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -612,7 +617,7 @@ static int tda10071_read_ber(struct dvb_frontend *fe, u32 *ber)
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
error:
|
error:
|
||||||
dbg("%s: failed=%d", __func__, ret);
|
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -632,7 +637,7 @@ static int tda10071_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
error:
|
error:
|
||||||
dbg("%s: failed=%d", __func__, ret);
|
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -644,10 +649,11 @@ static int tda10071_set_frontend(struct dvb_frontend *fe)
|
||||||
int ret, i;
|
int ret, i;
|
||||||
u8 mode, rolloff, pilot, inversion, div;
|
u8 mode, rolloff, pilot, inversion, div;
|
||||||
|
|
||||||
dbg("%s: delivery_system=%d modulation=%d frequency=%d " \
|
dev_dbg(&priv->i2c->dev, "%s: delivery_system=%d modulation=%d " \
|
||||||
"symbol_rate=%d inversion=%d pilot=%d rolloff=%d", __func__,
|
"frequency=%d symbol_rate=%d inversion=%d pilot=%d " \
|
||||||
c->delivery_system, c->modulation, c->frequency,
|
"rolloff=%d\n", __func__, c->delivery_system, c->modulation,
|
||||||
c->symbol_rate, c->inversion, c->pilot, c->rolloff);
|
c->frequency, c->symbol_rate, c->inversion, c->pilot,
|
||||||
|
c->rolloff);
|
||||||
|
|
||||||
priv->delivery_system = SYS_UNDEFINED;
|
priv->delivery_system = SYS_UNDEFINED;
|
||||||
|
|
||||||
|
@ -669,7 +675,7 @@ static int tda10071_set_frontend(struct dvb_frontend *fe)
|
||||||
inversion = 3;
|
inversion = 3;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dbg("%s: invalid inversion", __func__);
|
dev_dbg(&priv->i2c->dev, "%s: invalid inversion\n", __func__);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -692,7 +698,8 @@ static int tda10071_set_frontend(struct dvb_frontend *fe)
|
||||||
break;
|
break;
|
||||||
case ROLLOFF_AUTO:
|
case ROLLOFF_AUTO:
|
||||||
default:
|
default:
|
||||||
dbg("%s: invalid rolloff", __func__);
|
dev_dbg(&priv->i2c->dev, "%s: invalid rolloff\n",
|
||||||
|
__func__);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -708,13 +715,15 @@ static int tda10071_set_frontend(struct dvb_frontend *fe)
|
||||||
pilot = 2;
|
pilot = 2;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dbg("%s: invalid pilot", __func__);
|
dev_dbg(&priv->i2c->dev, "%s: invalid pilot\n",
|
||||||
|
__func__);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dbg("%s: invalid delivery_system", __func__);
|
dev_dbg(&priv->i2c->dev, "%s: invalid delivery_system\n",
|
||||||
|
__func__);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -724,13 +733,15 @@ static int tda10071_set_frontend(struct dvb_frontend *fe)
|
||||||
c->modulation == TDA10071_MODCOD[i].modulation &&
|
c->modulation == TDA10071_MODCOD[i].modulation &&
|
||||||
c->fec_inner == TDA10071_MODCOD[i].fec) {
|
c->fec_inner == TDA10071_MODCOD[i].fec) {
|
||||||
mode = TDA10071_MODCOD[i].val;
|
mode = TDA10071_MODCOD[i].val;
|
||||||
dbg("%s: mode found=%02x", __func__, mode);
|
dev_dbg(&priv->i2c->dev, "%s: mode found=%02x\n",
|
||||||
|
__func__, mode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode == 0xff) {
|
if (mode == 0xff) {
|
||||||
dbg("%s: invalid parameter combination", __func__);
|
dev_dbg(&priv->i2c->dev, "%s: invalid parameter combination\n",
|
||||||
|
__func__);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -748,22 +759,22 @@ static int tda10071_set_frontend(struct dvb_frontend *fe)
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
cmd.args[0x00] = CMD_CHANGE_CHANNEL;
|
cmd.args[0] = CMD_CHANGE_CHANNEL;
|
||||||
cmd.args[0x01] = 0;
|
cmd.args[1] = 0;
|
||||||
cmd.args[0x02] = mode;
|
cmd.args[2] = mode;
|
||||||
cmd.args[0x03] = (c->frequency >> 16) & 0xff;
|
cmd.args[3] = (c->frequency >> 16) & 0xff;
|
||||||
cmd.args[0x04] = (c->frequency >> 8) & 0xff;
|
cmd.args[4] = (c->frequency >> 8) & 0xff;
|
||||||
cmd.args[0x05] = (c->frequency >> 0) & 0xff;
|
cmd.args[5] = (c->frequency >> 0) & 0xff;
|
||||||
cmd.args[0x06] = ((c->symbol_rate / 1000) >> 8) & 0xff;
|
cmd.args[6] = ((c->symbol_rate / 1000) >> 8) & 0xff;
|
||||||
cmd.args[0x07] = ((c->symbol_rate / 1000) >> 0) & 0xff;
|
cmd.args[7] = ((c->symbol_rate / 1000) >> 0) & 0xff;
|
||||||
cmd.args[0x08] = (tda10071_ops.info.frequency_tolerance >> 8) & 0xff;
|
cmd.args[8] = (tda10071_ops.info.frequency_tolerance >> 8) & 0xff;
|
||||||
cmd.args[0x09] = (tda10071_ops.info.frequency_tolerance >> 0) & 0xff;
|
cmd.args[9] = (tda10071_ops.info.frequency_tolerance >> 0) & 0xff;
|
||||||
cmd.args[0x0a] = rolloff;
|
cmd.args[10] = rolloff;
|
||||||
cmd.args[0x0b] = inversion;
|
cmd.args[11] = inversion;
|
||||||
cmd.args[0x0c] = pilot;
|
cmd.args[12] = pilot;
|
||||||
cmd.args[0x0d] = 0x00;
|
cmd.args[13] = 0x00;
|
||||||
cmd.args[0x0e] = 0x00;
|
cmd.args[14] = 0x00;
|
||||||
cmd.len = 0x0f;
|
cmd.len = 15;
|
||||||
ret = tda10071_cmd_execute(priv, &cmd);
|
ret = tda10071_cmd_execute(priv, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -772,7 +783,7 @@ static int tda10071_set_frontend(struct dvb_frontend *fe)
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
error:
|
error:
|
||||||
dbg("%s: failed=%d", __func__, ret);
|
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -829,7 +840,7 @@ static int tda10071_get_frontend(struct dvb_frontend *fe)
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
error:
|
error:
|
||||||
dbg("%s: failed=%d", __func__, ret);
|
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -915,10 +926,10 @@ static int tda10071_init(struct dvb_frontend *fe)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.args[0x00] = CMD_SET_SLEEP_MODE;
|
cmd.args[0] = CMD_SET_SLEEP_MODE;
|
||||||
cmd.args[0x01] = 0;
|
cmd.args[1] = 0;
|
||||||
cmd.args[0x02] = 0;
|
cmd.args[2] = 0;
|
||||||
cmd.len = 0x03;
|
cmd.len = 3;
|
||||||
ret = tda10071_cmd_execute(priv, &cmd);
|
ret = tda10071_cmd_execute(priv, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -929,10 +940,11 @@ static int tda10071_init(struct dvb_frontend *fe)
|
||||||
/* request the firmware, this will block and timeout */
|
/* request the firmware, this will block and timeout */
|
||||||
ret = request_firmware(&fw, fw_file, priv->i2c->dev.parent);
|
ret = request_firmware(&fw, fw_file, priv->i2c->dev.parent);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
err("did not find the firmware file. (%s) "
|
dev_err(&priv->i2c->dev, "%s: did not find the " \
|
||||||
"Please see linux/Documentation/dvb/ for more" \
|
"firmware file. (%s) Please see " \
|
||||||
" details on firmware-problems. (%d)",
|
"linux/Documentation/dvb/ for more " \
|
||||||
fw_file, ret);
|
"details on firmware-problems. (%d)\n",
|
||||||
|
KBUILD_MODNAME, fw_file, ret);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -961,10 +973,11 @@ static int tda10071_init(struct dvb_frontend *fe)
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error_release_firmware;
|
goto error_release_firmware;
|
||||||
|
|
||||||
info("found a '%s' in cold state, will try to load a firmware",
|
dev_info(&priv->i2c->dev, "%s: found a '%s' in cold state, " \
|
||||||
tda10071_ops.info.name);
|
"will try to load a firmware\n", KBUILD_MODNAME,
|
||||||
|
tda10071_ops.info.name);
|
||||||
info("downloading firmware from file '%s'", fw_file);
|
dev_info(&priv->i2c->dev, "%s: downloading firmware from " \
|
||||||
|
"file '%s'\n", KBUILD_MODNAME, fw_file);
|
||||||
|
|
||||||
/* do not download last byte */
|
/* do not download last byte */
|
||||||
fw_size = fw->size - 1;
|
fw_size = fw->size - 1;
|
||||||
|
@ -978,7 +991,9 @@ static int tda10071_init(struct dvb_frontend *fe)
|
||||||
ret = tda10071_wr_regs(priv, 0xfa,
|
ret = tda10071_wr_regs(priv, 0xfa,
|
||||||
(u8 *) &fw->data[fw_size - remaining], len);
|
(u8 *) &fw->data[fw_size - remaining], len);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
err("firmware download failed=%d", ret);
|
dev_err(&priv->i2c->dev, "%s: firmware " \
|
||||||
|
"download failed=%d\n",
|
||||||
|
KBUILD_MODNAME, ret);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error_release_firmware;
|
goto error_release_firmware;
|
||||||
}
|
}
|
||||||
|
@ -1002,15 +1017,16 @@ static int tda10071_init(struct dvb_frontend *fe)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (tmp) {
|
if (tmp) {
|
||||||
info("firmware did not run");
|
dev_info(&priv->i2c->dev, "%s: firmware did not run\n",
|
||||||
|
KBUILD_MODNAME);
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
goto error;
|
goto error;
|
||||||
} else {
|
} else {
|
||||||
priv->warm = 1;
|
priv->warm = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.args[0x00] = CMD_GET_FW_VERSION;
|
cmd.args[0] = CMD_GET_FW_VERSION;
|
||||||
cmd.len = 0x01;
|
cmd.len = 1;
|
||||||
ret = tda10071_cmd_execute(priv, &cmd);
|
ret = tda10071_cmd_execute(priv, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -1019,54 +1035,55 @@ static int tda10071_init(struct dvb_frontend *fe)
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
info("firmware version %d.%d.%d.%d",
|
dev_info(&priv->i2c->dev, "%s: firmware version %d.%d.%d.%d\n",
|
||||||
buf[0], buf[1], buf[2], buf[3]);
|
KBUILD_MODNAME, buf[0], buf[1], buf[2], buf[3]);
|
||||||
info("found a '%s' in warm state.", tda10071_ops.info.name);
|
dev_info(&priv->i2c->dev, "%s: found a '%s' in warm state\n",
|
||||||
|
KBUILD_MODNAME, tda10071_ops.info.name);
|
||||||
|
|
||||||
ret = tda10071_rd_regs(priv, 0x81, buf, 2);
|
ret = tda10071_rd_regs(priv, 0x81, buf, 2);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
cmd.args[0x00] = CMD_DEMOD_INIT;
|
cmd.args[0] = CMD_DEMOD_INIT;
|
||||||
cmd.args[0x01] = ((priv->cfg.xtal / 1000) >> 8) & 0xff;
|
cmd.args[1] = ((priv->cfg.xtal / 1000) >> 8) & 0xff;
|
||||||
cmd.args[0x02] = ((priv->cfg.xtal / 1000) >> 0) & 0xff;
|
cmd.args[2] = ((priv->cfg.xtal / 1000) >> 0) & 0xff;
|
||||||
cmd.args[0x03] = buf[0];
|
cmd.args[3] = buf[0];
|
||||||
cmd.args[0x04] = buf[1];
|
cmd.args[4] = buf[1];
|
||||||
cmd.args[0x05] = priv->cfg.pll_multiplier;
|
cmd.args[5] = priv->cfg.pll_multiplier;
|
||||||
cmd.args[0x06] = priv->cfg.spec_inv;
|
cmd.args[6] = priv->cfg.spec_inv;
|
||||||
cmd.args[0x07] = 0x00;
|
cmd.args[7] = 0x00;
|
||||||
cmd.len = 0x08;
|
cmd.len = 8;
|
||||||
ret = tda10071_cmd_execute(priv, &cmd);
|
ret = tda10071_cmd_execute(priv, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
cmd.args[0x00] = CMD_TUNER_INIT;
|
cmd.args[0] = CMD_TUNER_INIT;
|
||||||
cmd.args[0x01] = 0x00;
|
cmd.args[1] = 0x00;
|
||||||
cmd.args[0x02] = 0x00;
|
cmd.args[2] = 0x00;
|
||||||
cmd.args[0x03] = 0x00;
|
cmd.args[3] = 0x00;
|
||||||
cmd.args[0x04] = 0x00;
|
cmd.args[4] = 0x00;
|
||||||
cmd.args[0x05] = 0x14;
|
cmd.args[5] = 0x14;
|
||||||
cmd.args[0x06] = 0x00;
|
cmd.args[6] = 0x00;
|
||||||
cmd.args[0x07] = 0x03;
|
cmd.args[7] = 0x03;
|
||||||
cmd.args[0x08] = 0x02;
|
cmd.args[8] = 0x02;
|
||||||
cmd.args[0x09] = 0x02;
|
cmd.args[9] = 0x02;
|
||||||
cmd.args[0x0a] = 0x00;
|
cmd.args[10] = 0x00;
|
||||||
cmd.args[0x0b] = 0x00;
|
cmd.args[11] = 0x00;
|
||||||
cmd.args[0x0c] = 0x00;
|
cmd.args[12] = 0x00;
|
||||||
cmd.args[0x0d] = 0x00;
|
cmd.args[13] = 0x00;
|
||||||
cmd.args[0x0e] = 0x00;
|
cmd.args[14] = 0x00;
|
||||||
cmd.len = 0x0f;
|
cmd.len = 15;
|
||||||
ret = tda10071_cmd_execute(priv, &cmd);
|
ret = tda10071_cmd_execute(priv, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
cmd.args[0x00] = CMD_MPEG_CONFIG;
|
cmd.args[0] = CMD_MPEG_CONFIG;
|
||||||
cmd.args[0x01] = 0;
|
cmd.args[1] = 0;
|
||||||
cmd.args[0x02] = priv->cfg.ts_mode;
|
cmd.args[2] = priv->cfg.ts_mode;
|
||||||
cmd.args[0x03] = 0x00;
|
cmd.args[3] = 0x00;
|
||||||
cmd.args[0x04] = 0x04;
|
cmd.args[4] = 0x04;
|
||||||
cmd.args[0x05] = 0x00;
|
cmd.args[5] = 0x00;
|
||||||
cmd.len = 0x06;
|
cmd.len = 6;
|
||||||
ret = tda10071_cmd_execute(priv, &cmd);
|
ret = tda10071_cmd_execute(priv, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -1075,27 +1092,27 @@ static int tda10071_init(struct dvb_frontend *fe)
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
cmd.args[0x00] = CMD_LNB_CONFIG;
|
cmd.args[0] = CMD_LNB_CONFIG;
|
||||||
cmd.args[0x01] = 0;
|
cmd.args[1] = 0;
|
||||||
cmd.args[0x02] = 150;
|
cmd.args[2] = 150;
|
||||||
cmd.args[0x03] = 3;
|
cmd.args[3] = 3;
|
||||||
cmd.args[0x04] = 22;
|
cmd.args[4] = 22;
|
||||||
cmd.args[0x05] = 1;
|
cmd.args[5] = 1;
|
||||||
cmd.args[0x06] = 1;
|
cmd.args[6] = 1;
|
||||||
cmd.args[0x07] = 30;
|
cmd.args[7] = 30;
|
||||||
cmd.args[0x08] = 30;
|
cmd.args[8] = 30;
|
||||||
cmd.args[0x09] = 30;
|
cmd.args[9] = 30;
|
||||||
cmd.args[0x0a] = 30;
|
cmd.args[10] = 30;
|
||||||
cmd.len = 0x0b;
|
cmd.len = 11;
|
||||||
ret = tda10071_cmd_execute(priv, &cmd);
|
ret = tda10071_cmd_execute(priv, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
cmd.args[0x00] = CMD_BER_CONTROL;
|
cmd.args[0] = CMD_BER_CONTROL;
|
||||||
cmd.args[0x01] = 0;
|
cmd.args[1] = 0;
|
||||||
cmd.args[0x02] = 14;
|
cmd.args[2] = 14;
|
||||||
cmd.args[0x03] = 14;
|
cmd.args[3] = 14;
|
||||||
cmd.len = 0x04;
|
cmd.len = 4;
|
||||||
ret = tda10071_cmd_execute(priv, &cmd);
|
ret = tda10071_cmd_execute(priv, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -1105,7 +1122,7 @@ static int tda10071_init(struct dvb_frontend *fe)
|
||||||
error_release_firmware:
|
error_release_firmware:
|
||||||
release_firmware(fw);
|
release_firmware(fw);
|
||||||
error:
|
error:
|
||||||
dbg("%s: failed=%d", __func__, ret);
|
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1132,10 +1149,10 @@ static int tda10071_sleep(struct dvb_frontend *fe)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.args[0x00] = CMD_SET_SLEEP_MODE;
|
cmd.args[0] = CMD_SET_SLEEP_MODE;
|
||||||
cmd.args[0x01] = 0;
|
cmd.args[1] = 0;
|
||||||
cmd.args[0x02] = 1;
|
cmd.args[2] = 1;
|
||||||
cmd.len = 0x03;
|
cmd.len = 3;
|
||||||
ret = tda10071_cmd_execute(priv, &cmd);
|
ret = tda10071_cmd_execute(priv, &cmd);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -1149,7 +1166,7 @@ static int tda10071_sleep(struct dvb_frontend *fe)
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
error:
|
error:
|
||||||
dbg("%s: failed=%d", __func__, ret);
|
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1208,7 +1225,7 @@ struct dvb_frontend *tda10071_attach(const struct tda10071_config *config,
|
||||||
|
|
||||||
return &priv->fe;
|
return &priv->fe;
|
||||||
error:
|
error:
|
||||||
dbg("%s: failed=%d", __func__, ret);
|
dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||||
kfree(priv);
|
kfree(priv);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,19 +25,6 @@
|
||||||
#include "tda10071.h"
|
#include "tda10071.h"
|
||||||
#include <linux/firmware.h>
|
#include <linux/firmware.h>
|
||||||
|
|
||||||
#define LOG_PREFIX "tda10071"
|
|
||||||
|
|
||||||
#undef dbg
|
|
||||||
#define dbg(f, arg...) \
|
|
||||||
if (tda10071_debug) \
|
|
||||||
printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg)
|
|
||||||
#undef err
|
|
||||||
#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg)
|
|
||||||
#undef info
|
|
||||||
#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg)
|
|
||||||
#undef warn
|
|
||||||
#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
|
|
||||||
|
|
||||||
struct tda10071_priv {
|
struct tda10071_priv {
|
||||||
struct i2c_adapter *i2c;
|
struct i2c_adapter *i2c;
|
||||||
struct dvb_frontend fe;
|
struct dvb_frontend fe;
|
||||||
|
@ -112,7 +99,7 @@ struct tda10071_reg_val_mask {
|
||||||
#define CMD_BER_UPDATE_COUNTERS 0x3f
|
#define CMD_BER_UPDATE_COUNTERS 0x3f
|
||||||
|
|
||||||
/* firmare command struct */
|
/* firmare command struct */
|
||||||
#define TDA10071_ARGLEN 0x1e
|
#define TDA10071_ARGLEN 30
|
||||||
struct tda10071_cmd {
|
struct tda10071_cmd {
|
||||||
u8 args[TDA10071_ARGLEN];
|
u8 args[TDA10071_ARGLEN];
|
||||||
u8 len;
|
u8 len;
|
||||||
|
|
|
@ -217,6 +217,7 @@ static int demod_attach_drxk(struct ngene_channel *chan,
|
||||||
|
|
||||||
memset(&config, 0, sizeof(config));
|
memset(&config, 0, sizeof(config));
|
||||||
config.microcode_name = "drxk_a3.mc";
|
config.microcode_name = "drxk_a3.mc";
|
||||||
|
config.qam_demod_parameter_count = 4;
|
||||||
config.adr = 0x29 + (chan->number ^ 2);
|
config.adr = 0x29 + (chan->number ^ 2);
|
||||||
|
|
||||||
chan->fe = dvb_attach(drxk_attach, &config, i2c);
|
chan->fe = dvb_attach(drxk_attach, &config, i2c);
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
menuconfig RADIO_ADAPTERS
|
menuconfig RADIO_ADAPTERS
|
||||||
bool "Radio Adapters"
|
bool "Radio Adapters"
|
||||||
depends on VIDEO_V4L2
|
depends on VIDEO_V4L2
|
||||||
|
depends on MEDIA_RADIO_SUPPORT
|
||||||
default y
|
default y
|
||||||
---help---
|
---help---
|
||||||
Say Y here to enable selecting AM/FM radio adapters.
|
Say Y here to enable selecting AM/FM radio adapters.
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
#ifndef __LM7000_H
|
||||||
|
#define __LM7000_H
|
||||||
|
|
||||||
|
/* Sanyo LM7000 tuner chip control
|
||||||
|
*
|
||||||
|
* Copyright 2012 Ondrej Zary <linux@rainbow-software.org>
|
||||||
|
* based on radio-aimslab.c by M. Kirkwood
|
||||||
|
* and radio-sf16fmi.c by M. Kirkwood and Petr Vandrovec
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LM7000_DATA (1 << 0)
|
||||||
|
#define LM7000_CLK (1 << 1)
|
||||||
|
#define LM7000_CE (1 << 2)
|
||||||
|
|
||||||
|
#define LM7000_FM_100 (0 << 20)
|
||||||
|
#define LM7000_FM_50 (1 << 20)
|
||||||
|
#define LM7000_FM_25 (2 << 20)
|
||||||
|
#define LM7000_BIT_FM (1 << 23)
|
||||||
|
|
||||||
|
static inline void lm7000_set_freq(u32 freq, void *handle,
|
||||||
|
void (*set_pins)(void *handle, u8 pins))
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
u8 data;
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
freq += 171200; /* Add 10.7 MHz IF */
|
||||||
|
freq /= 400; /* Convert to 25 kHz units */
|
||||||
|
val = freq | LM7000_FM_25 | LM7000_BIT_FM;
|
||||||
|
/* write the 24-bit register, starting with LSB */
|
||||||
|
for (i = 0; i < 24; i++) {
|
||||||
|
data = val & (1 << i) ? LM7000_DATA : 0;
|
||||||
|
set_pins(handle, data | LM7000_CE);
|
||||||
|
udelay(2);
|
||||||
|
set_pins(handle, data | LM7000_CE | LM7000_CLK);
|
||||||
|
udelay(2);
|
||||||
|
set_pins(handle, data | LM7000_CE);
|
||||||
|
udelay(2);
|
||||||
|
}
|
||||||
|
set_pins(handle, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __LM7000_H */
|
|
@ -37,6 +37,7 @@
|
||||||
#include <media/v4l2-ioctl.h>
|
#include <media/v4l2-ioctl.h>
|
||||||
#include <media/v4l2-ctrls.h>
|
#include <media/v4l2-ctrls.h>
|
||||||
#include "radio-isa.h"
|
#include "radio-isa.h"
|
||||||
|
#include "lm7000.h"
|
||||||
|
|
||||||
MODULE_AUTHOR("M. Kirkwood");
|
MODULE_AUTHOR("M. Kirkwood");
|
||||||
MODULE_DESCRIPTION("A driver for the RadioTrack/RadioReveal radio card.");
|
MODULE_DESCRIPTION("A driver for the RadioTrack/RadioReveal radio card.");
|
||||||
|
@ -72,55 +73,38 @@ static struct radio_isa_card *rtrack_alloc(void)
|
||||||
return rt ? &rt->isa : NULL;
|
return rt ? &rt->isa : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The 128+64 on these outb's is to keep the volume stable while tuning.
|
#define AIMS_BIT_TUN_CE (1 << 0)
|
||||||
* Without them, the volume _will_ creep up with each frequency change
|
#define AIMS_BIT_TUN_CLK (1 << 1)
|
||||||
* and bit 4 (+16) is to keep the signal strength meter enabled.
|
#define AIMS_BIT_TUN_DATA (1 << 2)
|
||||||
*/
|
#define AIMS_BIT_VOL_CE (1 << 3)
|
||||||
|
#define AIMS_BIT_TUN_STRQ (1 << 4)
|
||||||
|
/* bit 5 is not connected */
|
||||||
|
#define AIMS_BIT_VOL_UP (1 << 6) /* active low */
|
||||||
|
#define AIMS_BIT_VOL_DN (1 << 7) /* active low */
|
||||||
|
|
||||||
static void send_0_byte(struct radio_isa_card *isa, int on)
|
void rtrack_set_pins(void *handle, u8 pins)
|
||||||
{
|
{
|
||||||
outb_p(128+64+16+on+1, isa->io); /* wr-enable + data low */
|
struct radio_isa_card *isa = handle;
|
||||||
outb_p(128+64+16+on+2+1, isa->io); /* clock */
|
struct rtrack *rt = container_of(isa, struct rtrack, isa);
|
||||||
msleep(1);
|
u8 bits = AIMS_BIT_VOL_DN | AIMS_BIT_VOL_UP | AIMS_BIT_TUN_STRQ;
|
||||||
}
|
|
||||||
|
|
||||||
static void send_1_byte(struct radio_isa_card *isa, int on)
|
if (!v4l2_ctrl_g_ctrl(rt->isa.mute))
|
||||||
{
|
bits |= AIMS_BIT_VOL_CE;
|
||||||
outb_p(128+64+16+on+4+1, isa->io); /* wr-enable+data high */
|
|
||||||
outb_p(128+64+16+on+4+2+1, isa->io); /* clock */
|
if (pins & LM7000_DATA)
|
||||||
msleep(1);
|
bits |= AIMS_BIT_TUN_DATA;
|
||||||
|
if (pins & LM7000_CLK)
|
||||||
|
bits |= AIMS_BIT_TUN_CLK;
|
||||||
|
if (pins & LM7000_CE)
|
||||||
|
bits |= AIMS_BIT_TUN_CE;
|
||||||
|
|
||||||
|
outb_p(bits, rt->isa.io);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rtrack_s_frequency(struct radio_isa_card *isa, u32 freq)
|
static int rtrack_s_frequency(struct radio_isa_card *isa, u32 freq)
|
||||||
{
|
{
|
||||||
int on = v4l2_ctrl_g_ctrl(isa->mute) ? 0 : 8;
|
lm7000_set_freq(freq, isa, rtrack_set_pins);
|
||||||
int i;
|
|
||||||
|
|
||||||
freq += 171200; /* Add 10.7 MHz IF */
|
|
||||||
freq /= 800; /* Convert to 50 kHz units */
|
|
||||||
|
|
||||||
send_0_byte(isa, on); /* 0: LSB of frequency */
|
|
||||||
|
|
||||||
for (i = 0; i < 13; i++) /* : frequency bits (1-13) */
|
|
||||||
if (freq & (1 << i))
|
|
||||||
send_1_byte(isa, on);
|
|
||||||
else
|
|
||||||
send_0_byte(isa, on);
|
|
||||||
|
|
||||||
send_0_byte(isa, on); /* 14: test bit - always 0 */
|
|
||||||
send_0_byte(isa, on); /* 15: test bit - always 0 */
|
|
||||||
|
|
||||||
send_0_byte(isa, on); /* 16: band data 0 - always 0 */
|
|
||||||
send_0_byte(isa, on); /* 17: band data 1 - always 0 */
|
|
||||||
send_0_byte(isa, on); /* 18: band data 2 - always 0 */
|
|
||||||
send_0_byte(isa, on); /* 19: time base - always 0 */
|
|
||||||
|
|
||||||
send_0_byte(isa, on); /* 20: spacing (0 = 25 kHz) */
|
|
||||||
send_1_byte(isa, on); /* 21: spacing (1 = 25 kHz) */
|
|
||||||
send_0_byte(isa, on); /* 22: spacing (0 = 25 kHz) */
|
|
||||||
send_1_byte(isa, on); /* 23: AM/FM (FM = 1, always) */
|
|
||||||
|
|
||||||
outb(0xd0 + on, isa->io); /* volume steady + sigstr */
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -295,7 +295,8 @@ static int vidioc_g_tuner(struct file *file, void *priv,
|
||||||
v->type = V4L2_TUNER_RADIO;
|
v->type = V4L2_TUNER_RADIO;
|
||||||
v->rangelow = FREQ_MIN * FREQ_MUL;
|
v->rangelow = FREQ_MIN * FREQ_MUL;
|
||||||
v->rangehigh = FREQ_MAX * FREQ_MUL;
|
v->rangehigh = FREQ_MAX * FREQ_MUL;
|
||||||
v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
|
v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
|
||||||
|
V4L2_TUNER_CAP_HWSEEK_WRAP;
|
||||||
v->rxsubchans = is_stereo ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO;
|
v->rxsubchans = is_stereo ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO;
|
||||||
v->audmode = radio->stereo ?
|
v->audmode = radio->stereo ?
|
||||||
V4L2_TUNER_MODE_STEREO : V4L2_TUNER_MODE_MONO;
|
V4L2_TUNER_MODE_STEREO : V4L2_TUNER_MODE_MONO;
|
||||||
|
@ -372,7 +373,7 @@ static int vidioc_s_hw_freq_seek(struct file *file, void *priv,
|
||||||
timeout = jiffies + msecs_to_jiffies(30000);
|
timeout = jiffies + msecs_to_jiffies(30000);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (time_after(jiffies, timeout)) {
|
if (time_after(jiffies, timeout)) {
|
||||||
retval = -EAGAIN;
|
retval = -ENODATA;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (schedule_timeout_interruptible(msecs_to_jiffies(10))) {
|
if (schedule_timeout_interruptible(msecs_to_jiffies(10))) {
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <linux/io.h> /* outb, outb_p */
|
#include <linux/io.h> /* outb, outb_p */
|
||||||
#include <media/v4l2-device.h>
|
#include <media/v4l2-device.h>
|
||||||
#include <media/v4l2-ioctl.h>
|
#include <media/v4l2-ioctl.h>
|
||||||
|
#include "lm7000.h"
|
||||||
|
|
||||||
MODULE_AUTHOR("Petr Vandrovec, vandrove@vc.cvut.cz and M. Kirkwood");
|
MODULE_AUTHOR("Petr Vandrovec, vandrove@vc.cvut.cz and M. Kirkwood");
|
||||||
MODULE_DESCRIPTION("A driver for the SF16-FMI, SF16-FMP and SF16-FMD radio.");
|
MODULE_DESCRIPTION("A driver for the SF16-FMI, SF16-FMP and SF16-FMD radio.");
|
||||||
|
@ -54,31 +55,33 @@ static struct fmi fmi_card;
|
||||||
static struct pnp_dev *dev;
|
static struct pnp_dev *dev;
|
||||||
bool pnp_attached;
|
bool pnp_attached;
|
||||||
|
|
||||||
/* freq is in 1/16 kHz to internal number, hw precision is 50 kHz */
|
|
||||||
/* It is only useful to give freq in interval of 800 (=0.05Mhz),
|
|
||||||
* other bits will be truncated, e.g 92.7400016 -> 92.7, but
|
|
||||||
* 92.7400017 -> 92.75
|
|
||||||
*/
|
|
||||||
#define RSF16_ENCODE(x) ((x) / 800 + 214)
|
|
||||||
#define RSF16_MINFREQ (87 * 16000)
|
#define RSF16_MINFREQ (87 * 16000)
|
||||||
#define RSF16_MAXFREQ (108 * 16000)
|
#define RSF16_MAXFREQ (108 * 16000)
|
||||||
|
|
||||||
static void outbits(int bits, unsigned int data, int io)
|
#define FMI_BIT_TUN_CE (1 << 0)
|
||||||
|
#define FMI_BIT_TUN_CLK (1 << 1)
|
||||||
|
#define FMI_BIT_TUN_DATA (1 << 2)
|
||||||
|
#define FMI_BIT_VOL_SW (1 << 3)
|
||||||
|
#define FMI_BIT_TUN_STRQ (1 << 4)
|
||||||
|
|
||||||
|
void fmi_set_pins(void *handle, u8 pins)
|
||||||
{
|
{
|
||||||
while (bits--) {
|
struct fmi *fmi = handle;
|
||||||
if (data & 1) {
|
u8 bits = FMI_BIT_TUN_STRQ;
|
||||||
outb(5, io);
|
|
||||||
udelay(6);
|
if (!fmi->mute)
|
||||||
outb(7, io);
|
bits |= FMI_BIT_VOL_SW;
|
||||||
udelay(6);
|
|
||||||
} else {
|
if (pins & LM7000_DATA)
|
||||||
outb(1, io);
|
bits |= FMI_BIT_TUN_DATA;
|
||||||
udelay(6);
|
if (pins & LM7000_CLK)
|
||||||
outb(3, io);
|
bits |= FMI_BIT_TUN_CLK;
|
||||||
udelay(6);
|
if (pins & LM7000_CE)
|
||||||
}
|
bits |= FMI_BIT_TUN_CE;
|
||||||
data >>= 1;
|
|
||||||
}
|
mutex_lock(&fmi->lock);
|
||||||
|
outb_p(bits, fmi->io);
|
||||||
|
mutex_unlock(&fmi->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void fmi_mute(struct fmi *fmi)
|
static inline void fmi_mute(struct fmi *fmi)
|
||||||
|
@ -95,20 +98,6 @@ static inline void fmi_unmute(struct fmi *fmi)
|
||||||
mutex_unlock(&fmi->lock);
|
mutex_unlock(&fmi->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int fmi_setfreq(struct fmi *fmi, unsigned long freq)
|
|
||||||
{
|
|
||||||
mutex_lock(&fmi->lock);
|
|
||||||
fmi->curfreq = freq;
|
|
||||||
|
|
||||||
outbits(16, RSF16_ENCODE(freq), fmi->io);
|
|
||||||
outbits(8, 0xC0, fmi->io);
|
|
||||||
msleep(143); /* was schedule_timeout(HZ/7) */
|
|
||||||
mutex_unlock(&fmi->lock);
|
|
||||||
if (!fmi->mute)
|
|
||||||
fmi_unmute(fmi);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int fmi_getsigstr(struct fmi *fmi)
|
static inline int fmi_getsigstr(struct fmi *fmi)
|
||||||
{
|
{
|
||||||
int val;
|
int val;
|
||||||
|
@ -173,7 +162,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
/* rounding in steps of 800 to match the freq
|
/* rounding in steps of 800 to match the freq
|
||||||
that will be used */
|
that will be used */
|
||||||
fmi_setfreq(fmi, (f->frequency / 800) * 800);
|
lm7000_set_freq((f->frequency / 800) * 800, fmi, fmi_set_pins);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1514,7 +1514,8 @@ static int wl1273_fm_vidioc_g_tuner(struct file *file, void *priv,
|
||||||
tuner->rangehigh = WL1273_FREQ(WL1273_BAND_OTHER_HIGH);
|
tuner->rangehigh = WL1273_FREQ(WL1273_BAND_OTHER_HIGH);
|
||||||
|
|
||||||
tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_RDS |
|
tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_RDS |
|
||||||
V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS_BLOCK_IO;
|
V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS_BLOCK_IO |
|
||||||
|
V4L2_TUNER_CAP_HWSEEK_BOUNDED | V4L2_TUNER_CAP_HWSEEK_WRAP;
|
||||||
|
|
||||||
if (radio->stereo)
|
if (radio->stereo)
|
||||||
tuner->audmode = V4L2_TUNER_MODE_STEREO;
|
tuner->audmode = V4L2_TUNER_MODE_STEREO;
|
||||||
|
|
|
@ -363,7 +363,7 @@ stop:
|
||||||
|
|
||||||
/* try again, if timed out */
|
/* try again, if timed out */
|
||||||
if (retval == 0 && timed_out)
|
if (retval == 0 && timed_out)
|
||||||
return -EAGAIN;
|
return -ENODATA;
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -596,7 +596,9 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
|
||||||
strcpy(tuner->name, "FM");
|
strcpy(tuner->name, "FM");
|
||||||
tuner->type = V4L2_TUNER_RADIO;
|
tuner->type = V4L2_TUNER_RADIO;
|
||||||
tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
|
tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
|
||||||
V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO;
|
V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO |
|
||||||
|
V4L2_TUNER_CAP_HWSEEK_BOUNDED |
|
||||||
|
V4L2_TUNER_CAP_HWSEEK_WRAP;
|
||||||
|
|
||||||
/* range limits */
|
/* range limits */
|
||||||
switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) {
|
switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) {
|
||||||
|
|
|
@ -251,7 +251,7 @@ again:
|
||||||
if (!timeleft) {
|
if (!timeleft) {
|
||||||
fmerr("Timeout(%d sec),didn't get tune ended int\n",
|
fmerr("Timeout(%d sec),didn't get tune ended int\n",
|
||||||
jiffies_to_msecs(FM_DRV_RX_SEEK_TIMEOUT) / 1000);
|
jiffies_to_msecs(FM_DRV_RX_SEEK_TIMEOUT) / 1000);
|
||||||
return -ETIMEDOUT;
|
return -ENODATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
int_reason = fmdev->irq_info.flag & (FM_TUNE_COMPLETE | FM_BAND_LIMIT);
|
int_reason = fmdev->irq_info.flag & (FM_TUNE_COMPLETE | FM_BAND_LIMIT);
|
||||||
|
|
|
@ -285,7 +285,9 @@ static int fm_v4l2_vidioc_g_tuner(struct file *file, void *priv,
|
||||||
tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO |
|
tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO |
|
||||||
((fmdev->rx.rds.flag == FM_RDS_ENABLE) ? V4L2_TUNER_SUB_RDS : 0);
|
((fmdev->rx.rds.flag == FM_RDS_ENABLE) ? V4L2_TUNER_SUB_RDS : 0);
|
||||||
tuner->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS |
|
tuner->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS |
|
||||||
V4L2_TUNER_CAP_LOW;
|
V4L2_TUNER_CAP_LOW |
|
||||||
|
V4L2_TUNER_CAP_HWSEEK_BOUNDED |
|
||||||
|
V4L2_TUNER_CAP_HWSEEK_WRAP;
|
||||||
tuner->audmode = (stereo_mono_mode ?
|
tuner->audmode = (stereo_mono_mode ?
|
||||||
V4L2_TUNER_MODE_MONO : V4L2_TUNER_MODE_STEREO);
|
V4L2_TUNER_MODE_MONO : V4L2_TUNER_MODE_STEREO);
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,21 @@
|
||||||
menuconfig RC_CORE
|
config RC_CORE
|
||||||
tristate "Remote Controller adapters"
|
|
||||||
depends on INPUT
|
|
||||||
default INPUT
|
|
||||||
---help---
|
|
||||||
Enable support for Remote Controllers on Linux. This is
|
|
||||||
needed in order to support several video capture adapters,
|
|
||||||
standalone IR receivers/transmitters, and RF receivers.
|
|
||||||
|
|
||||||
Enable this option if you have a video capture board even
|
|
||||||
if you don't need IR, as otherwise, you may not be able to
|
|
||||||
compile the driver for your adapter.
|
|
||||||
|
|
||||||
if RC_CORE
|
|
||||||
|
|
||||||
config LIRC
|
|
||||||
tristate
|
tristate
|
||||||
|
depends on MEDIA_RC_SUPPORT
|
||||||
|
depends on INPUT
|
||||||
default y
|
default y
|
||||||
|
|
||||||
|
source "drivers/media/rc/keymaps/Kconfig"
|
||||||
|
|
||||||
|
menuconfig RC_DECODERS
|
||||||
|
bool "Remote controller decoders"
|
||||||
|
depends on RC_CORE
|
||||||
|
default y
|
||||||
|
|
||||||
|
if RC_DECODERS
|
||||||
|
config LIRC
|
||||||
|
tristate "LIRC interface driver"
|
||||||
|
depends on RC_CORE
|
||||||
|
|
||||||
---help---
|
---help---
|
||||||
Enable this option to build the Linux Infrared Remote
|
Enable this option to build the Linux Infrared Remote
|
||||||
Control (LIRC) core device interface driver. The LIRC
|
Control (LIRC) core device interface driver. The LIRC
|
||||||
|
@ -24,7 +23,16 @@ config LIRC
|
||||||
LIRC daemon handles protocol decoding for IR reception and
|
LIRC daemon handles protocol decoding for IR reception and
|
||||||
encoding for IR transmitting (aka "blasting").
|
encoding for IR transmitting (aka "blasting").
|
||||||
|
|
||||||
source "drivers/media/rc/keymaps/Kconfig"
|
config IR_LIRC_CODEC
|
||||||
|
tristate "Enable IR to LIRC bridge"
|
||||||
|
depends on RC_CORE
|
||||||
|
depends on LIRC
|
||||||
|
default y
|
||||||
|
|
||||||
|
---help---
|
||||||
|
Enable this option to pass raw IR to and from userspace via
|
||||||
|
the LIRC interface.
|
||||||
|
|
||||||
|
|
||||||
config IR_NEC_DECODER
|
config IR_NEC_DECODER
|
||||||
tristate "Enable IR raw decoder for the NEC protocol"
|
tristate "Enable IR raw decoder for the NEC protocol"
|
||||||
|
@ -108,16 +116,13 @@ config IR_MCE_KBD_DECODER
|
||||||
Enable this option if you have a Microsoft Remote Keyboard for
|
Enable this option if you have a Microsoft Remote Keyboard for
|
||||||
Windows Media Center Edition, which you would like to use with
|
Windows Media Center Edition, which you would like to use with
|
||||||
a raw IR receiver in your system.
|
a raw IR receiver in your system.
|
||||||
|
endif #RC_DECODERS
|
||||||
|
|
||||||
config IR_LIRC_CODEC
|
menuconfig RC_DEVICES
|
||||||
tristate "Enable IR to LIRC bridge"
|
bool "Remote Controller devices"
|
||||||
depends on RC_CORE
|
depends on RC_CORE
|
||||||
depends on LIRC
|
|
||||||
default y
|
|
||||||
|
|
||||||
---help---
|
if RC_DEVICES
|
||||||
Enable this option to pass raw IR to and from userspace via
|
|
||||||
the LIRC interface.
|
|
||||||
|
|
||||||
config RC_ATI_REMOTE
|
config RC_ATI_REMOTE
|
||||||
tristate "ATI / X10 based USB RF remote controls"
|
tristate "ATI / X10 based USB RF remote controls"
|
||||||
|
@ -276,4 +281,4 @@ config IR_GPIO_CIR
|
||||||
To compile this driver as a module, choose M here: the module will
|
To compile this driver as a module, choose M here: the module will
|
||||||
be called gpio-ir-recv.
|
be called gpio-ir-recv.
|
||||||
|
|
||||||
endif #RC_CORE
|
endif #RC_DEVICES
|
||||||
|
|
|
@ -1018,6 +1018,8 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
|
||||||
|
|
||||||
spin_lock_init(&dev->hw_lock);
|
spin_lock_init(&dev->hw_lock);
|
||||||
|
|
||||||
|
dev->hw_io = pnp_port_start(pnp_dev, 0);
|
||||||
|
|
||||||
pnp_set_drvdata(pnp_dev, dev);
|
pnp_set_drvdata(pnp_dev, dev);
|
||||||
dev->pnp_dev = pnp_dev;
|
dev->pnp_dev = pnp_dev;
|
||||||
|
|
||||||
|
@ -1072,7 +1074,6 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
|
||||||
|
|
||||||
/* claim the resources */
|
/* claim the resources */
|
||||||
error = -EBUSY;
|
error = -EBUSY;
|
||||||
dev->hw_io = pnp_port_start(pnp_dev, 0);
|
|
||||||
if (!request_region(dev->hw_io, ENE_IO_SIZE, ENE_DRIVER_NAME)) {
|
if (!request_region(dev->hw_io, ENE_IO_SIZE, ENE_DRIVER_NAME)) {
|
||||||
dev->hw_io = -1;
|
dev->hw_io = -1;
|
||||||
dev->irq = -1;
|
dev->irq = -1;
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
* USA
|
* USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/pnp.h>
|
#include <linux/pnp.h>
|
||||||
|
@ -110,30 +112,32 @@ static u8 fintek_cir_reg_read(struct fintek_dev *fintek, u8 offset)
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define pr_reg(text, ...) \
|
|
||||||
printk(KERN_INFO KBUILD_MODNAME ": " text, ## __VA_ARGS__)
|
|
||||||
|
|
||||||
/* dump current cir register contents */
|
/* dump current cir register contents */
|
||||||
static void cir_dump_regs(struct fintek_dev *fintek)
|
static void cir_dump_regs(struct fintek_dev *fintek)
|
||||||
{
|
{
|
||||||
fintek_config_mode_enable(fintek);
|
fintek_config_mode_enable(fintek);
|
||||||
fintek_select_logical_dev(fintek, fintek->logical_dev_cir);
|
fintek_select_logical_dev(fintek, fintek->logical_dev_cir);
|
||||||
|
|
||||||
pr_reg("%s: Dump CIR logical device registers:\n", FINTEK_DRIVER_NAME);
|
pr_info("%s: Dump CIR logical device registers:\n", FINTEK_DRIVER_NAME);
|
||||||
pr_reg(" * CR CIR BASE ADDR: 0x%x\n",
|
pr_info(" * CR CIR BASE ADDR: 0x%x\n",
|
||||||
(fintek_cr_read(fintek, CIR_CR_BASE_ADDR_HI) << 8) |
|
(fintek_cr_read(fintek, CIR_CR_BASE_ADDR_HI) << 8) |
|
||||||
fintek_cr_read(fintek, CIR_CR_BASE_ADDR_LO));
|
fintek_cr_read(fintek, CIR_CR_BASE_ADDR_LO));
|
||||||
pr_reg(" * CR CIR IRQ NUM: 0x%x\n",
|
pr_info(" * CR CIR IRQ NUM: 0x%x\n",
|
||||||
fintek_cr_read(fintek, CIR_CR_IRQ_SEL));
|
fintek_cr_read(fintek, CIR_CR_IRQ_SEL));
|
||||||
|
|
||||||
fintek_config_mode_disable(fintek);
|
fintek_config_mode_disable(fintek);
|
||||||
|
|
||||||
pr_reg("%s: Dump CIR registers:\n", FINTEK_DRIVER_NAME);
|
pr_info("%s: Dump CIR registers:\n", FINTEK_DRIVER_NAME);
|
||||||
pr_reg(" * STATUS: 0x%x\n", fintek_cir_reg_read(fintek, CIR_STATUS));
|
pr_info(" * STATUS: 0x%x\n",
|
||||||
pr_reg(" * CONTROL: 0x%x\n", fintek_cir_reg_read(fintek, CIR_CONTROL));
|
fintek_cir_reg_read(fintek, CIR_STATUS));
|
||||||
pr_reg(" * RX_DATA: 0x%x\n", fintek_cir_reg_read(fintek, CIR_RX_DATA));
|
pr_info(" * CONTROL: 0x%x\n",
|
||||||
pr_reg(" * TX_CONTROL: 0x%x\n", fintek_cir_reg_read(fintek, CIR_TX_CONTROL));
|
fintek_cir_reg_read(fintek, CIR_CONTROL));
|
||||||
pr_reg(" * TX_DATA: 0x%x\n", fintek_cir_reg_read(fintek, CIR_TX_DATA));
|
pr_info(" * RX_DATA: 0x%x\n",
|
||||||
|
fintek_cir_reg_read(fintek, CIR_RX_DATA));
|
||||||
|
pr_info(" * TX_CONTROL: 0x%x\n",
|
||||||
|
fintek_cir_reg_read(fintek, CIR_TX_CONTROL));
|
||||||
|
pr_info(" * TX_DATA: 0x%x\n",
|
||||||
|
fintek_cir_reg_read(fintek, CIR_TX_DATA));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* detect hardware features */
|
/* detect hardware features */
|
||||||
|
|
|
@ -82,12 +82,21 @@ static int __devinit gpio_ir_recv_probe(struct platform_device *pdev)
|
||||||
goto err_allocate_device;
|
goto err_allocate_device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rcdev->priv = gpio_dev;
|
||||||
rcdev->driver_type = RC_DRIVER_IR_RAW;
|
rcdev->driver_type = RC_DRIVER_IR_RAW;
|
||||||
rcdev->allowed_protos = RC_TYPE_ALL;
|
|
||||||
rcdev->input_name = GPIO_IR_DEVICE_NAME;
|
rcdev->input_name = GPIO_IR_DEVICE_NAME;
|
||||||
|
rcdev->input_phys = GPIO_IR_DEVICE_NAME "/input0";
|
||||||
rcdev->input_id.bustype = BUS_HOST;
|
rcdev->input_id.bustype = BUS_HOST;
|
||||||
|
rcdev->input_id.vendor = 0x0001;
|
||||||
|
rcdev->input_id.product = 0x0001;
|
||||||
|
rcdev->input_id.version = 0x0100;
|
||||||
|
rcdev->dev.parent = &pdev->dev;
|
||||||
rcdev->driver_name = GPIO_IR_DRIVER_NAME;
|
rcdev->driver_name = GPIO_IR_DRIVER_NAME;
|
||||||
rcdev->map_name = RC_MAP_EMPTY;
|
if (pdata->allowed_protos)
|
||||||
|
rcdev->allowed_protos = pdata->allowed_protos;
|
||||||
|
else
|
||||||
|
rcdev->allowed_protos = RC_TYPE_ALL;
|
||||||
|
rcdev->map_name = pdata->map_name ?: RC_MAP_EMPTY;
|
||||||
|
|
||||||
gpio_dev->rcdev = rcdev;
|
gpio_dev->rcdev = rcdev;
|
||||||
gpio_dev->gpio_nr = pdata->gpio_nr;
|
gpio_dev->gpio_nr = pdata->gpio_nr;
|
||||||
|
@ -188,18 +197,7 @@ static struct platform_driver gpio_ir_recv_driver = {
|
||||||
#endif
|
#endif
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
module_platform_driver(gpio_ir_recv_driver);
|
||||||
static int __init gpio_ir_recv_init(void)
|
|
||||||
{
|
|
||||||
return platform_driver_register(&gpio_ir_recv_driver);
|
|
||||||
}
|
|
||||||
module_init(gpio_ir_recv_init);
|
|
||||||
|
|
||||||
static void __exit gpio_ir_recv_exit(void)
|
|
||||||
{
|
|
||||||
platform_driver_unregister(&gpio_ir_recv_driver);
|
|
||||||
}
|
|
||||||
module_exit(gpio_ir_recv_exit);
|
|
||||||
|
|
||||||
MODULE_DESCRIPTION("GPIO IR Receiver driver");
|
MODULE_DESCRIPTION("GPIO IR Receiver driver");
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
* USA
|
* USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/pnp.h>
|
#include <linux/pnp.h>
|
||||||
|
@ -123,43 +125,40 @@ static u8 nvt_cir_wake_reg_read(struct nvt_dev *nvt, u8 offset)
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define pr_reg(text, ...) \
|
|
||||||
printk(KERN_INFO KBUILD_MODNAME ": " text, ## __VA_ARGS__)
|
|
||||||
|
|
||||||
/* dump current cir register contents */
|
/* dump current cir register contents */
|
||||||
static void cir_dump_regs(struct nvt_dev *nvt)
|
static void cir_dump_regs(struct nvt_dev *nvt)
|
||||||
{
|
{
|
||||||
nvt_efm_enable(nvt);
|
nvt_efm_enable(nvt);
|
||||||
nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
|
nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
|
||||||
|
|
||||||
pr_reg("%s: Dump CIR logical device registers:\n", NVT_DRIVER_NAME);
|
pr_info("%s: Dump CIR logical device registers:\n", NVT_DRIVER_NAME);
|
||||||
pr_reg(" * CR CIR ACTIVE : 0x%x\n",
|
pr_info(" * CR CIR ACTIVE : 0x%x\n",
|
||||||
nvt_cr_read(nvt, CR_LOGICAL_DEV_EN));
|
nvt_cr_read(nvt, CR_LOGICAL_DEV_EN));
|
||||||
pr_reg(" * CR CIR BASE ADDR: 0x%x\n",
|
pr_info(" * CR CIR BASE ADDR: 0x%x\n",
|
||||||
(nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8) |
|
(nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8) |
|
||||||
nvt_cr_read(nvt, CR_CIR_BASE_ADDR_LO));
|
nvt_cr_read(nvt, CR_CIR_BASE_ADDR_LO));
|
||||||
pr_reg(" * CR CIR IRQ NUM: 0x%x\n",
|
pr_info(" * CR CIR IRQ NUM: 0x%x\n",
|
||||||
nvt_cr_read(nvt, CR_CIR_IRQ_RSRC));
|
nvt_cr_read(nvt, CR_CIR_IRQ_RSRC));
|
||||||
|
|
||||||
nvt_efm_disable(nvt);
|
nvt_efm_disable(nvt);
|
||||||
|
|
||||||
pr_reg("%s: Dump CIR registers:\n", NVT_DRIVER_NAME);
|
pr_info("%s: Dump CIR registers:\n", NVT_DRIVER_NAME);
|
||||||
pr_reg(" * IRCON: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRCON));
|
pr_info(" * IRCON: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRCON));
|
||||||
pr_reg(" * IRSTS: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRSTS));
|
pr_info(" * IRSTS: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRSTS));
|
||||||
pr_reg(" * IREN: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IREN));
|
pr_info(" * IREN: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IREN));
|
||||||
pr_reg(" * RXFCONT: 0x%x\n", nvt_cir_reg_read(nvt, CIR_RXFCONT));
|
pr_info(" * RXFCONT: 0x%x\n", nvt_cir_reg_read(nvt, CIR_RXFCONT));
|
||||||
pr_reg(" * CP: 0x%x\n", nvt_cir_reg_read(nvt, CIR_CP));
|
pr_info(" * CP: 0x%x\n", nvt_cir_reg_read(nvt, CIR_CP));
|
||||||
pr_reg(" * CC: 0x%x\n", nvt_cir_reg_read(nvt, CIR_CC));
|
pr_info(" * CC: 0x%x\n", nvt_cir_reg_read(nvt, CIR_CC));
|
||||||
pr_reg(" * SLCH: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SLCH));
|
pr_info(" * SLCH: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SLCH));
|
||||||
pr_reg(" * SLCL: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SLCL));
|
pr_info(" * SLCL: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SLCL));
|
||||||
pr_reg(" * FIFOCON: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FIFOCON));
|
pr_info(" * FIFOCON: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FIFOCON));
|
||||||
pr_reg(" * IRFIFOSTS: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRFIFOSTS));
|
pr_info(" * IRFIFOSTS: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRFIFOSTS));
|
||||||
pr_reg(" * SRXFIFO: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SRXFIFO));
|
pr_info(" * SRXFIFO: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SRXFIFO));
|
||||||
pr_reg(" * TXFCONT: 0x%x\n", nvt_cir_reg_read(nvt, CIR_TXFCONT));
|
pr_info(" * TXFCONT: 0x%x\n", nvt_cir_reg_read(nvt, CIR_TXFCONT));
|
||||||
pr_reg(" * STXFIFO: 0x%x\n", nvt_cir_reg_read(nvt, CIR_STXFIFO));
|
pr_info(" * STXFIFO: 0x%x\n", nvt_cir_reg_read(nvt, CIR_STXFIFO));
|
||||||
pr_reg(" * FCCH: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FCCH));
|
pr_info(" * FCCH: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FCCH));
|
||||||
pr_reg(" * FCCL: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FCCL));
|
pr_info(" * FCCL: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FCCL));
|
||||||
pr_reg(" * IRFSM: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRFSM));
|
pr_info(" * IRFSM: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRFSM));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* dump current cir wake register contents */
|
/* dump current cir wake register contents */
|
||||||
|
@ -170,59 +169,59 @@ static void cir_wake_dump_regs(struct nvt_dev *nvt)
|
||||||
nvt_efm_enable(nvt);
|
nvt_efm_enable(nvt);
|
||||||
nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE);
|
nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE);
|
||||||
|
|
||||||
pr_reg("%s: Dump CIR WAKE logical device registers:\n",
|
pr_info("%s: Dump CIR WAKE logical device registers:\n",
|
||||||
NVT_DRIVER_NAME);
|
NVT_DRIVER_NAME);
|
||||||
pr_reg(" * CR CIR WAKE ACTIVE : 0x%x\n",
|
pr_info(" * CR CIR WAKE ACTIVE : 0x%x\n",
|
||||||
nvt_cr_read(nvt, CR_LOGICAL_DEV_EN));
|
nvt_cr_read(nvt, CR_LOGICAL_DEV_EN));
|
||||||
pr_reg(" * CR CIR WAKE BASE ADDR: 0x%x\n",
|
pr_info(" * CR CIR WAKE BASE ADDR: 0x%x\n",
|
||||||
(nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8) |
|
(nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8) |
|
||||||
nvt_cr_read(nvt, CR_CIR_BASE_ADDR_LO));
|
nvt_cr_read(nvt, CR_CIR_BASE_ADDR_LO));
|
||||||
pr_reg(" * CR CIR WAKE IRQ NUM: 0x%x\n",
|
pr_info(" * CR CIR WAKE IRQ NUM: 0x%x\n",
|
||||||
nvt_cr_read(nvt, CR_CIR_IRQ_RSRC));
|
nvt_cr_read(nvt, CR_CIR_IRQ_RSRC));
|
||||||
|
|
||||||
nvt_efm_disable(nvt);
|
nvt_efm_disable(nvt);
|
||||||
|
|
||||||
pr_reg("%s: Dump CIR WAKE registers\n", NVT_DRIVER_NAME);
|
pr_info("%s: Dump CIR WAKE registers\n", NVT_DRIVER_NAME);
|
||||||
pr_reg(" * IRCON: 0x%x\n",
|
pr_info(" * IRCON: 0x%x\n",
|
||||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRCON));
|
nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRCON));
|
||||||
pr_reg(" * IRSTS: 0x%x\n",
|
pr_info(" * IRSTS: 0x%x\n",
|
||||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS));
|
nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS));
|
||||||
pr_reg(" * IREN: 0x%x\n",
|
pr_info(" * IREN: 0x%x\n",
|
||||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN));
|
nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN));
|
||||||
pr_reg(" * FIFO CMP DEEP: 0x%x\n",
|
pr_info(" * FIFO CMP DEEP: 0x%x\n",
|
||||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_CMP_DEEP));
|
nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_CMP_DEEP));
|
||||||
pr_reg(" * FIFO CMP TOL: 0x%x\n",
|
pr_info(" * FIFO CMP TOL: 0x%x\n",
|
||||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_CMP_TOL));
|
nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_CMP_TOL));
|
||||||
pr_reg(" * FIFO COUNT: 0x%x\n",
|
pr_info(" * FIFO COUNT: 0x%x\n",
|
||||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT));
|
nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT));
|
||||||
pr_reg(" * SLCH: 0x%x\n",
|
pr_info(" * SLCH: 0x%x\n",
|
||||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_SLCH));
|
nvt_cir_wake_reg_read(nvt, CIR_WAKE_SLCH));
|
||||||
pr_reg(" * SLCL: 0x%x\n",
|
pr_info(" * SLCL: 0x%x\n",
|
||||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_SLCL));
|
nvt_cir_wake_reg_read(nvt, CIR_WAKE_SLCL));
|
||||||
pr_reg(" * FIFOCON: 0x%x\n",
|
pr_info(" * FIFOCON: 0x%x\n",
|
||||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFOCON));
|
nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFOCON));
|
||||||
pr_reg(" * SRXFSTS: 0x%x\n",
|
pr_info(" * SRXFSTS: 0x%x\n",
|
||||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_SRXFSTS));
|
nvt_cir_wake_reg_read(nvt, CIR_WAKE_SRXFSTS));
|
||||||
pr_reg(" * SAMPLE RX FIFO: 0x%x\n",
|
pr_info(" * SAMPLE RX FIFO: 0x%x\n",
|
||||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_SAMPLE_RX_FIFO));
|
nvt_cir_wake_reg_read(nvt, CIR_WAKE_SAMPLE_RX_FIFO));
|
||||||
pr_reg(" * WR FIFO DATA: 0x%x\n",
|
pr_info(" * WR FIFO DATA: 0x%x\n",
|
||||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_WR_FIFO_DATA));
|
nvt_cir_wake_reg_read(nvt, CIR_WAKE_WR_FIFO_DATA));
|
||||||
pr_reg(" * RD FIFO ONLY: 0x%x\n",
|
pr_info(" * RD FIFO ONLY: 0x%x\n",
|
||||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY));
|
nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY));
|
||||||
pr_reg(" * RD FIFO ONLY IDX: 0x%x\n",
|
pr_info(" * RD FIFO ONLY IDX: 0x%x\n",
|
||||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY_IDX));
|
nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY_IDX));
|
||||||
pr_reg(" * FIFO IGNORE: 0x%x\n",
|
pr_info(" * FIFO IGNORE: 0x%x\n",
|
||||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_IGNORE));
|
nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_IGNORE));
|
||||||
pr_reg(" * IRFSM: 0x%x\n",
|
pr_info(" * IRFSM: 0x%x\n",
|
||||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRFSM));
|
nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRFSM));
|
||||||
|
|
||||||
fifo_len = nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT);
|
fifo_len = nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT);
|
||||||
pr_reg("%s: Dump CIR WAKE FIFO (len %d)\n", NVT_DRIVER_NAME, fifo_len);
|
pr_info("%s: Dump CIR WAKE FIFO (len %d)\n", NVT_DRIVER_NAME, fifo_len);
|
||||||
pr_reg("* Contents = ");
|
pr_info("* Contents =");
|
||||||
for (i = 0; i < fifo_len; i++)
|
for (i = 0; i < fifo_len; i++)
|
||||||
printk(KERN_CONT "%02x ",
|
pr_cont(" %02x",
|
||||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY));
|
nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY));
|
||||||
printk(KERN_CONT "\n");
|
pr_cont("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* detect hardware features */
|
/* detect hardware features */
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
config VIDEO_V4L2
|
config VIDEO_V4L2
|
||||||
tristate
|
tristate
|
||||||
depends on VIDEO_DEV && VIDEO_V4L2_COMMON
|
depends on VIDEO_DEV && VIDEO_V4L2_COMMON
|
||||||
default VIDEO_DEV && VIDEO_V4L2_COMMON
|
default y
|
||||||
|
|
||||||
config VIDEOBUF_GEN
|
config VIDEOBUF_GEN
|
||||||
tristate
|
tristate
|
||||||
|
@ -73,6 +73,7 @@ config VIDEOBUF2_DMA_SG
|
||||||
menuconfig VIDEO_CAPTURE_DRIVERS
|
menuconfig VIDEO_CAPTURE_DRIVERS
|
||||||
bool "Video capture adapters"
|
bool "Video capture adapters"
|
||||||
depends on VIDEO_V4L2
|
depends on VIDEO_V4L2
|
||||||
|
depends on MEDIA_CAMERA_SUPPORT || MEDIA_ANALOG_TV_SUPPORT
|
||||||
default y
|
default y
|
||||||
---help---
|
---help---
|
||||||
Say Y here to enable selecting the video adapters for
|
Say Y here to enable selecting the video adapters for
|
||||||
|
@ -461,6 +462,15 @@ config VIDEO_ADV7343
|
||||||
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 adv7343.
|
module will be called adv7343.
|
||||||
|
|
||||||
|
config VIDEO_ADV7393
|
||||||
|
tristate "ADV7393 video encoder"
|
||||||
|
depends on I2C
|
||||||
|
help
|
||||||
|
Support for Analog Devices I2C bus based ADV7393 encoder.
|
||||||
|
|
||||||
|
To compile this driver as a module, choose M here: the
|
||||||
|
module will be called adv7393.
|
||||||
|
|
||||||
config VIDEO_AK881X
|
config VIDEO_AK881X
|
||||||
tristate "AK8813/AK8814 video encoders"
|
tristate "AK8813/AK8814 video encoders"
|
||||||
depends on I2C
|
depends on I2C
|
||||||
|
@ -478,6 +488,7 @@ config VIDEO_SMIAPP_PLL
|
||||||
config VIDEO_OV7670
|
config VIDEO_OV7670
|
||||||
tristate "OmniVision OV7670 sensor support"
|
tristate "OmniVision OV7670 sensor support"
|
||||||
depends on I2C && VIDEO_V4L2
|
depends on I2C && VIDEO_V4L2
|
||||||
|
depends on MEDIA_CAMERA_SUPPORT
|
||||||
---help---
|
---help---
|
||||||
This is a Video4Linux2 sensor-level driver for the OmniVision
|
This is a Video4Linux2 sensor-level driver for the OmniVision
|
||||||
OV7670 VGA camera. It currently only works with the M88ALP01
|
OV7670 VGA camera. It currently only works with the M88ALP01
|
||||||
|
@ -486,6 +497,7 @@ config VIDEO_OV7670
|
||||||
config VIDEO_VS6624
|
config VIDEO_VS6624
|
||||||
tristate "ST VS6624 sensor support"
|
tristate "ST VS6624 sensor support"
|
||||||
depends on VIDEO_V4L2 && I2C
|
depends on VIDEO_V4L2 && I2C
|
||||||
|
depends on MEDIA_CAMERA_SUPPORT
|
||||||
---help---
|
---help---
|
||||||
This is a Video4Linux2 sensor-level driver for the ST VS6624
|
This is a Video4Linux2 sensor-level driver for the ST VS6624
|
||||||
camera.
|
camera.
|
||||||
|
@ -496,6 +508,7 @@ config VIDEO_VS6624
|
||||||
config VIDEO_MT9M032
|
config VIDEO_MT9M032
|
||||||
tristate "MT9M032 camera sensor support"
|
tristate "MT9M032 camera sensor support"
|
||||||
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
|
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
|
||||||
|
depends on MEDIA_CAMERA_SUPPORT
|
||||||
select VIDEO_APTINA_PLL
|
select VIDEO_APTINA_PLL
|
||||||
---help---
|
---help---
|
||||||
This driver supports MT9M032 camera sensors from Aptina, monochrome
|
This driver supports MT9M032 camera sensors from Aptina, monochrome
|
||||||
|
@ -504,6 +517,7 @@ config VIDEO_MT9M032
|
||||||
config VIDEO_MT9P031
|
config VIDEO_MT9P031
|
||||||
tristate "Aptina MT9P031 support"
|
tristate "Aptina MT9P031 support"
|
||||||
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
|
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
|
||||||
|
depends on MEDIA_CAMERA_SUPPORT
|
||||||
select VIDEO_APTINA_PLL
|
select VIDEO_APTINA_PLL
|
||||||
---help---
|
---help---
|
||||||
This is a Video4Linux2 sensor-level driver for the Aptina
|
This is a Video4Linux2 sensor-level driver for the Aptina
|
||||||
|
@ -512,6 +526,7 @@ config VIDEO_MT9P031
|
||||||
config VIDEO_MT9T001
|
config VIDEO_MT9T001
|
||||||
tristate "Aptina MT9T001 support"
|
tristate "Aptina MT9T001 support"
|
||||||
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
|
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
|
||||||
|
depends on MEDIA_CAMERA_SUPPORT
|
||||||
---help---
|
---help---
|
||||||
This is a Video4Linux2 sensor-level driver for the Aptina
|
This is a Video4Linux2 sensor-level driver for the Aptina
|
||||||
(Micron) mt0t001 3 Mpixel camera.
|
(Micron) mt0t001 3 Mpixel camera.
|
||||||
|
@ -519,6 +534,7 @@ config VIDEO_MT9T001
|
||||||
config VIDEO_MT9V011
|
config VIDEO_MT9V011
|
||||||
tristate "Micron mt9v011 sensor support"
|
tristate "Micron mt9v011 sensor support"
|
||||||
depends on I2C && VIDEO_V4L2
|
depends on I2C && VIDEO_V4L2
|
||||||
|
depends on MEDIA_CAMERA_SUPPORT
|
||||||
---help---
|
---help---
|
||||||
This is a Video4Linux2 sensor-level driver for the Micron
|
This is a Video4Linux2 sensor-level driver for the Micron
|
||||||
mt0v011 1.3 Mpixel camera. It currently only works with the
|
mt0v011 1.3 Mpixel camera. It currently only works with the
|
||||||
|
@ -527,6 +543,7 @@ config VIDEO_MT9V011
|
||||||
config VIDEO_MT9V032
|
config VIDEO_MT9V032
|
||||||
tristate "Micron MT9V032 sensor support"
|
tristate "Micron MT9V032 sensor support"
|
||||||
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
|
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
|
||||||
|
depends on MEDIA_CAMERA_SUPPORT
|
||||||
---help---
|
---help---
|
||||||
This is a Video4Linux2 sensor-level driver for the Micron
|
This is a Video4Linux2 sensor-level driver for the Micron
|
||||||
MT9V032 752x480 CMOS sensor.
|
MT9V032 752x480 CMOS sensor.
|
||||||
|
@ -534,6 +551,7 @@ config VIDEO_MT9V032
|
||||||
config VIDEO_TCM825X
|
config VIDEO_TCM825X
|
||||||
tristate "TCM825x camera sensor support"
|
tristate "TCM825x camera sensor support"
|
||||||
depends on I2C && VIDEO_V4L2
|
depends on I2C && VIDEO_V4L2
|
||||||
|
depends on MEDIA_CAMERA_SUPPORT
|
||||||
---help---
|
---help---
|
||||||
This is a driver for the Toshiba TCM825x VGA camera sensor.
|
This is a driver for the Toshiba TCM825x VGA camera sensor.
|
||||||
It is used for example in Nokia N800.
|
It is used for example in Nokia N800.
|
||||||
|
@ -541,12 +559,14 @@ config VIDEO_TCM825X
|
||||||
config VIDEO_SR030PC30
|
config VIDEO_SR030PC30
|
||||||
tristate "Siliconfile SR030PC30 sensor support"
|
tristate "Siliconfile SR030PC30 sensor support"
|
||||||
depends on I2C && VIDEO_V4L2
|
depends on I2C && VIDEO_V4L2
|
||||||
|
depends on MEDIA_CAMERA_SUPPORT
|
||||||
---help---
|
---help---
|
||||||
This driver supports SR030PC30 VGA camera from Siliconfile
|
This driver supports SR030PC30 VGA camera from Siliconfile
|
||||||
|
|
||||||
config VIDEO_NOON010PC30
|
config VIDEO_NOON010PC30
|
||||||
tristate "Siliconfile NOON010PC30 sensor support"
|
tristate "Siliconfile NOON010PC30 sensor support"
|
||||||
depends on I2C && VIDEO_V4L2 && EXPERIMENTAL && VIDEO_V4L2_SUBDEV_API
|
depends on I2C && VIDEO_V4L2 && EXPERIMENTAL && VIDEO_V4L2_SUBDEV_API
|
||||||
|
depends on MEDIA_CAMERA_SUPPORT
|
||||||
---help---
|
---help---
|
||||||
This driver supports NOON010PC30 CIF camera from Siliconfile
|
This driver supports NOON010PC30 CIF camera from Siliconfile
|
||||||
|
|
||||||
|
@ -554,6 +574,7 @@ source "drivers/media/video/m5mols/Kconfig"
|
||||||
|
|
||||||
config VIDEO_S5K6AA
|
config VIDEO_S5K6AA
|
||||||
tristate "Samsung S5K6AAFX sensor support"
|
tristate "Samsung S5K6AAFX sensor support"
|
||||||
|
depends on MEDIA_CAMERA_SUPPORT
|
||||||
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
|
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
|
||||||
---help---
|
---help---
|
||||||
This is a V4L2 sensor-level driver for Samsung S5K6AA(FX) 1.3M
|
This is a V4L2 sensor-level driver for Samsung S5K6AA(FX) 1.3M
|
||||||
|
@ -566,6 +587,7 @@ comment "Flash devices"
|
||||||
config VIDEO_ADP1653
|
config VIDEO_ADP1653
|
||||||
tristate "ADP1653 flash support"
|
tristate "ADP1653 flash support"
|
||||||
depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
|
depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
|
||||||
|
depends on MEDIA_CAMERA_SUPPORT
|
||||||
---help---
|
---help---
|
||||||
This is a driver for the ADP1653 flash controller. It is used for
|
This is a driver for the ADP1653 flash controller. It is used for
|
||||||
example in Nokia N900.
|
example in Nokia N900.
|
||||||
|
@ -573,6 +595,7 @@ config VIDEO_ADP1653
|
||||||
config VIDEO_AS3645A
|
config VIDEO_AS3645A
|
||||||
tristate "AS3645A flash driver support"
|
tristate "AS3645A flash driver support"
|
||||||
depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
|
depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
|
||||||
|
depends on MEDIA_CAMERA_SUPPORT
|
||||||
---help---
|
---help---
|
||||||
This is a driver for the AS3645A and LM3555 flash controllers. It has
|
This is a driver for the AS3645A and LM3555 flash controllers. It has
|
||||||
build in control for flash, torch and indicator LEDs.
|
build in control for flash, torch and indicator LEDs.
|
||||||
|
@ -647,30 +670,14 @@ menuconfig V4L_USB_DRIVERS
|
||||||
depends on USB
|
depends on USB
|
||||||
default y
|
default y
|
||||||
|
|
||||||
if V4L_USB_DRIVERS
|
if V4L_USB_DRIVERS && MEDIA_CAMERA_SUPPORT
|
||||||
|
|
||||||
source "drivers/media/video/au0828/Kconfig"
|
comment "Webcam devices"
|
||||||
|
|
||||||
source "drivers/media/video/uvc/Kconfig"
|
source "drivers/media/video/uvc/Kconfig"
|
||||||
|
|
||||||
source "drivers/media/video/gspca/Kconfig"
|
source "drivers/media/video/gspca/Kconfig"
|
||||||
|
|
||||||
source "drivers/media/video/pvrusb2/Kconfig"
|
|
||||||
|
|
||||||
source "drivers/media/video/hdpvr/Kconfig"
|
|
||||||
|
|
||||||
source "drivers/media/video/em28xx/Kconfig"
|
|
||||||
|
|
||||||
source "drivers/media/video/tlg2300/Kconfig"
|
|
||||||
|
|
||||||
source "drivers/media/video/cx231xx/Kconfig"
|
|
||||||
|
|
||||||
source "drivers/media/video/tm6000/Kconfig"
|
|
||||||
|
|
||||||
source "drivers/media/video/usbvision/Kconfig"
|
|
||||||
|
|
||||||
source "drivers/media/video/sn9c102/Kconfig"
|
|
||||||
|
|
||||||
source "drivers/media/video/pwc/Kconfig"
|
source "drivers/media/video/pwc/Kconfig"
|
||||||
|
|
||||||
source "drivers/media/video/cpia2/Kconfig"
|
source "drivers/media/video/cpia2/Kconfig"
|
||||||
|
@ -711,15 +718,46 @@ config USB_S2255
|
||||||
Say Y here if you want support for the Sensoray 2255 USB device.
|
Say Y here if you want support for the Sensoray 2255 USB device.
|
||||||
This driver can be compiled as a module, called s2255drv.
|
This driver can be compiled as a module, called s2255drv.
|
||||||
|
|
||||||
|
source "drivers/media/video/sn9c102/Kconfig"
|
||||||
|
|
||||||
|
endif # V4L_USB_DRIVERS && MEDIA_CAMERA_SUPPORT
|
||||||
|
|
||||||
|
if V4L_USB_DRIVERS
|
||||||
|
|
||||||
|
comment "Webcam and/or TV USB devices"
|
||||||
|
|
||||||
|
source "drivers/media/video/em28xx/Kconfig"
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
if V4L_USB_DRIVERS && MEDIA_ANALOG_TV_SUPPORT
|
||||||
|
|
||||||
|
comment "TV USB devices"
|
||||||
|
|
||||||
|
source "drivers/media/video/au0828/Kconfig"
|
||||||
|
|
||||||
|
source "drivers/media/video/pvrusb2/Kconfig"
|
||||||
|
|
||||||
|
source "drivers/media/video/hdpvr/Kconfig"
|
||||||
|
|
||||||
|
source "drivers/media/video/tlg2300/Kconfig"
|
||||||
|
|
||||||
|
source "drivers/media/video/cx231xx/Kconfig"
|
||||||
|
|
||||||
|
source "drivers/media/video/tm6000/Kconfig"
|
||||||
|
|
||||||
|
source "drivers/media/video/usbvision/Kconfig"
|
||||||
|
|
||||||
endif # V4L_USB_DRIVERS
|
endif # V4L_USB_DRIVERS
|
||||||
|
|
||||||
#
|
#
|
||||||
# PCI drivers configuration
|
# PCI drivers configuration - No devices here are for webcams
|
||||||
#
|
#
|
||||||
|
|
||||||
menuconfig V4L_PCI_DRIVERS
|
menuconfig V4L_PCI_DRIVERS
|
||||||
bool "V4L PCI(e) devices"
|
bool "V4L PCI(e) devices"
|
||||||
depends on PCI
|
depends on PCI
|
||||||
|
depends on MEDIA_ANALOG_TV_SUPPORT
|
||||||
default y
|
default y
|
||||||
---help---
|
---help---
|
||||||
Say Y here to enable support for these PCI(e) drivers.
|
Say Y here to enable support for these PCI(e) drivers.
|
||||||
|
@ -814,11 +852,13 @@ endif # V4L_PCI_DRIVERS
|
||||||
|
|
||||||
#
|
#
|
||||||
# ISA & parallel port drivers configuration
|
# ISA & parallel port drivers configuration
|
||||||
|
# All devices here are webcam or grabber devices
|
||||||
#
|
#
|
||||||
|
|
||||||
menuconfig V4L_ISA_PARPORT_DRIVERS
|
menuconfig V4L_ISA_PARPORT_DRIVERS
|
||||||
bool "V4L ISA and parallel port devices"
|
bool "V4L ISA and parallel port devices"
|
||||||
depends on ISA || PARPORT
|
depends on ISA || PARPORT
|
||||||
|
depends on MEDIA_CAMERA_SUPPORT
|
||||||
default n
|
default n
|
||||||
---help---
|
---help---
|
||||||
Say Y here to enable support for these ISA and parallel port drivers.
|
Say Y here to enable support for these ISA and parallel port drivers.
|
||||||
|
@ -871,8 +911,13 @@ config VIDEO_W9966
|
||||||
|
|
||||||
endif # V4L_ISA_PARPORT_DRIVERS
|
endif # V4L_ISA_PARPORT_DRIVERS
|
||||||
|
|
||||||
|
#
|
||||||
|
# Platform drivers
|
||||||
|
# All drivers here are currently for webcam support
|
||||||
|
|
||||||
menuconfig V4L_PLATFORM_DRIVERS
|
menuconfig V4L_PLATFORM_DRIVERS
|
||||||
bool "V4L platform devices"
|
bool "V4L platform devices"
|
||||||
|
depends on MEDIA_CAMERA_SUPPORT
|
||||||
default n
|
default n
|
||||||
---help---
|
---help---
|
||||||
Say Y here to enable support for platform-specific V4L drivers.
|
Say Y here to enable support for platform-specific V4L drivers.
|
||||||
|
|
|
@ -45,6 +45,7 @@ obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o
|
||||||
obj-$(CONFIG_VIDEO_ADV7180) += adv7180.o
|
obj-$(CONFIG_VIDEO_ADV7180) += adv7180.o
|
||||||
obj-$(CONFIG_VIDEO_ADV7183) += adv7183.o
|
obj-$(CONFIG_VIDEO_ADV7183) += adv7183.o
|
||||||
obj-$(CONFIG_VIDEO_ADV7343) += adv7343.o
|
obj-$(CONFIG_VIDEO_ADV7343) += adv7343.o
|
||||||
|
obj-$(CONFIG_VIDEO_ADV7393) += adv7393.o
|
||||||
obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o
|
obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o
|
||||||
obj-$(CONFIG_VIDEO_VS6624) += vs6624.o
|
obj-$(CONFIG_VIDEO_VS6624) += vs6624.o
|
||||||
obj-$(CONFIG_VIDEO_BT819) += bt819.o
|
obj-$(CONFIG_VIDEO_BT819) += bt819.o
|
||||||
|
|
|
@ -0,0 +1,487 @@
|
||||||
|
/*
|
||||||
|
* adv7393 - ADV7393 Video Encoder Driver
|
||||||
|
*
|
||||||
|
* The encoder hardware does not support SECAM.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010-2012 ADVANSEE - http://www.advansee.com/
|
||||||
|
* Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
|
||||||
|
*
|
||||||
|
* Based on ADV7343 driver,
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation version 2.
|
||||||
|
*
|
||||||
|
* This program is distributed .as is. WITHOUT ANY WARRANTY of any
|
||||||
|
* kind, whether express or implied; without even the implied warranty
|
||||||
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/ctype.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/videodev2.h>
|
||||||
|
#include <linux/uaccess.h>
|
||||||
|
|
||||||
|
#include <media/adv7393.h>
|
||||||
|
#include <media/v4l2-device.h>
|
||||||
|
#include <media/v4l2-chip-ident.h>
|
||||||
|
#include <media/v4l2-ctrls.h>
|
||||||
|
|
||||||
|
#include "adv7393_regs.h"
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION("ADV7393 video encoder driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
|
static bool debug;
|
||||||
|
module_param(debug, bool, 0644);
|
||||||
|
MODULE_PARM_DESC(debug, "Debug level 0-1");
|
||||||
|
|
||||||
|
struct adv7393_state {
|
||||||
|
struct v4l2_subdev sd;
|
||||||
|
struct v4l2_ctrl_handler hdl;
|
||||||
|
u8 reg00;
|
||||||
|
u8 reg01;
|
||||||
|
u8 reg02;
|
||||||
|
u8 reg35;
|
||||||
|
u8 reg80;
|
||||||
|
u8 reg82;
|
||||||
|
u32 output;
|
||||||
|
v4l2_std_id std;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline struct adv7393_state *to_state(struct v4l2_subdev *sd)
|
||||||
|
{
|
||||||
|
return container_of(sd, struct adv7393_state, sd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
|
||||||
|
{
|
||||||
|
return &container_of(ctrl->handler, struct adv7393_state, hdl)->sd;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int adv7393_write(struct v4l2_subdev *sd, u8 reg, u8 value)
|
||||||
|
{
|
||||||
|
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||||
|
|
||||||
|
return i2c_smbus_write_byte_data(client, reg, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const u8 adv7393_init_reg_val[] = {
|
||||||
|
ADV7393_SOFT_RESET, ADV7393_SOFT_RESET_DEFAULT,
|
||||||
|
ADV7393_POWER_MODE_REG, ADV7393_POWER_MODE_REG_DEFAULT,
|
||||||
|
|
||||||
|
ADV7393_HD_MODE_REG1, ADV7393_HD_MODE_REG1_DEFAULT,
|
||||||
|
ADV7393_HD_MODE_REG2, ADV7393_HD_MODE_REG2_DEFAULT,
|
||||||
|
ADV7393_HD_MODE_REG3, ADV7393_HD_MODE_REG3_DEFAULT,
|
||||||
|
ADV7393_HD_MODE_REG4, ADV7393_HD_MODE_REG4_DEFAULT,
|
||||||
|
ADV7393_HD_MODE_REG5, ADV7393_HD_MODE_REG5_DEFAULT,
|
||||||
|
ADV7393_HD_MODE_REG6, ADV7393_HD_MODE_REG6_DEFAULT,
|
||||||
|
ADV7393_HD_MODE_REG7, ADV7393_HD_MODE_REG7_DEFAULT,
|
||||||
|
|
||||||
|
ADV7393_SD_MODE_REG1, ADV7393_SD_MODE_REG1_DEFAULT,
|
||||||
|
ADV7393_SD_MODE_REG2, ADV7393_SD_MODE_REG2_DEFAULT,
|
||||||
|
ADV7393_SD_MODE_REG3, ADV7393_SD_MODE_REG3_DEFAULT,
|
||||||
|
ADV7393_SD_MODE_REG4, ADV7393_SD_MODE_REG4_DEFAULT,
|
||||||
|
ADV7393_SD_MODE_REG5, ADV7393_SD_MODE_REG5_DEFAULT,
|
||||||
|
ADV7393_SD_MODE_REG6, ADV7393_SD_MODE_REG6_DEFAULT,
|
||||||
|
ADV7393_SD_MODE_REG7, ADV7393_SD_MODE_REG7_DEFAULT,
|
||||||
|
ADV7393_SD_MODE_REG8, ADV7393_SD_MODE_REG8_DEFAULT,
|
||||||
|
|
||||||
|
ADV7393_SD_TIMING_REG0, ADV7393_SD_TIMING_REG0_DEFAULT,
|
||||||
|
|
||||||
|
ADV7393_SD_HUE_ADJUST, ADV7393_SD_HUE_ADJUST_DEFAULT,
|
||||||
|
ADV7393_SD_CGMS_WSS0, ADV7393_SD_CGMS_WSS0_DEFAULT,
|
||||||
|
ADV7393_SD_BRIGHTNESS_WSS, ADV7393_SD_BRIGHTNESS_WSS_DEFAULT,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 2^32
|
||||||
|
* FSC(reg) = FSC (HZ) * --------
|
||||||
|
* 27000000
|
||||||
|
*/
|
||||||
|
static const struct adv7393_std_info stdinfo[] = {
|
||||||
|
{
|
||||||
|
/* FSC(Hz) = 4,433,618.75 Hz */
|
||||||
|
SD_STD_NTSC, 705268427, V4L2_STD_NTSC_443,
|
||||||
|
}, {
|
||||||
|
/* FSC(Hz) = 3,579,545.45 Hz */
|
||||||
|
SD_STD_NTSC, 569408542, V4L2_STD_NTSC,
|
||||||
|
}, {
|
||||||
|
/* FSC(Hz) = 3,575,611.00 Hz */
|
||||||
|
SD_STD_PAL_M, 568782678, V4L2_STD_PAL_M,
|
||||||
|
}, {
|
||||||
|
/* FSC(Hz) = 3,582,056.00 Hz */
|
||||||
|
SD_STD_PAL_N, 569807903, V4L2_STD_PAL_Nc,
|
||||||
|
}, {
|
||||||
|
/* FSC(Hz) = 4,433,618.75 Hz */
|
||||||
|
SD_STD_PAL_N, 705268427, V4L2_STD_PAL_N,
|
||||||
|
}, {
|
||||||
|
/* FSC(Hz) = 4,433,618.75 Hz */
|
||||||
|
SD_STD_PAL_M, 705268427, V4L2_STD_PAL_60,
|
||||||
|
}, {
|
||||||
|
/* FSC(Hz) = 4,433,618.75 Hz */
|
||||||
|
SD_STD_PAL_BDGHI, 705268427, V4L2_STD_PAL,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static int adv7393_setstd(struct v4l2_subdev *sd, v4l2_std_id std)
|
||||||
|
{
|
||||||
|
struct adv7393_state *state = to_state(sd);
|
||||||
|
const struct adv7393_std_info *std_info;
|
||||||
|
int num_std;
|
||||||
|
u8 reg;
|
||||||
|
u32 val;
|
||||||
|
int err = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
num_std = ARRAY_SIZE(stdinfo);
|
||||||
|
|
||||||
|
for (i = 0; i < num_std; i++) {
|
||||||
|
if (stdinfo[i].stdid & std)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == num_std) {
|
||||||
|
v4l2_dbg(1, debug, sd,
|
||||||
|
"Invalid std or std is not supported: %llx\n",
|
||||||
|
(unsigned long long)std);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
std_info = &stdinfo[i];
|
||||||
|
|
||||||
|
/* Set the standard */
|
||||||
|
val = state->reg80 & ~SD_STD_MASK;
|
||||||
|
val |= std_info->standard_val3;
|
||||||
|
err = adv7393_write(sd, ADV7393_SD_MODE_REG1, val);
|
||||||
|
if (err < 0)
|
||||||
|
goto setstd_exit;
|
||||||
|
|
||||||
|
state->reg80 = val;
|
||||||
|
|
||||||
|
/* Configure the input mode register */
|
||||||
|
val = state->reg01 & ~INPUT_MODE_MASK;
|
||||||
|
val |= SD_INPUT_MODE;
|
||||||
|
err = adv7393_write(sd, ADV7393_MODE_SELECT_REG, val);
|
||||||
|
if (err < 0)
|
||||||
|
goto setstd_exit;
|
||||||
|
|
||||||
|
state->reg01 = val;
|
||||||
|
|
||||||
|
/* Program the sub carrier frequency registers */
|
||||||
|
val = std_info->fsc_val;
|
||||||
|
for (reg = ADV7393_FSC_REG0; reg <= ADV7393_FSC_REG3; reg++) {
|
||||||
|
err = adv7393_write(sd, reg, val);
|
||||||
|
if (err < 0)
|
||||||
|
goto setstd_exit;
|
||||||
|
val >>= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
val = state->reg82;
|
||||||
|
|
||||||
|
/* Pedestal settings */
|
||||||
|
if (std & (V4L2_STD_NTSC | V4L2_STD_NTSC_443))
|
||||||
|
val |= SD_PEDESTAL_EN;
|
||||||
|
else
|
||||||
|
val &= SD_PEDESTAL_DI;
|
||||||
|
|
||||||
|
err = adv7393_write(sd, ADV7393_SD_MODE_REG2, val);
|
||||||
|
if (err < 0)
|
||||||
|
goto setstd_exit;
|
||||||
|
|
||||||
|
state->reg82 = val;
|
||||||
|
|
||||||
|
setstd_exit:
|
||||||
|
if (err != 0)
|
||||||
|
v4l2_err(sd, "Error setting std, write failed\n");
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int adv7393_setoutput(struct v4l2_subdev *sd, u32 output_type)
|
||||||
|
{
|
||||||
|
struct adv7393_state *state = to_state(sd);
|
||||||
|
u8 val;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
if (output_type > ADV7393_SVIDEO_ID) {
|
||||||
|
v4l2_dbg(1, debug, sd,
|
||||||
|
"Invalid output type or output type not supported:%d\n",
|
||||||
|
output_type);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enable Appropriate DAC */
|
||||||
|
val = state->reg00 & 0x03;
|
||||||
|
|
||||||
|
if (output_type == ADV7393_COMPOSITE_ID)
|
||||||
|
val |= ADV7393_COMPOSITE_POWER_VALUE;
|
||||||
|
else if (output_type == ADV7393_COMPONENT_ID)
|
||||||
|
val |= ADV7393_COMPONENT_POWER_VALUE;
|
||||||
|
else
|
||||||
|
val |= ADV7393_SVIDEO_POWER_VALUE;
|
||||||
|
|
||||||
|
err = adv7393_write(sd, ADV7393_POWER_MODE_REG, val);
|
||||||
|
if (err < 0)
|
||||||
|
goto setoutput_exit;
|
||||||
|
|
||||||
|
state->reg00 = val;
|
||||||
|
|
||||||
|
/* Enable YUV output */
|
||||||
|
val = state->reg02 | YUV_OUTPUT_SELECT;
|
||||||
|
err = adv7393_write(sd, ADV7393_MODE_REG0, val);
|
||||||
|
if (err < 0)
|
||||||
|
goto setoutput_exit;
|
||||||
|
|
||||||
|
state->reg02 = val;
|
||||||
|
|
||||||
|
/* configure SD DAC Output 1 bit */
|
||||||
|
val = state->reg82;
|
||||||
|
if (output_type == ADV7393_COMPONENT_ID)
|
||||||
|
val &= SD_DAC_OUT1_DI;
|
||||||
|
else
|
||||||
|
val |= SD_DAC_OUT1_EN;
|
||||||
|
err = adv7393_write(sd, ADV7393_SD_MODE_REG2, val);
|
||||||
|
if (err < 0)
|
||||||
|
goto setoutput_exit;
|
||||||
|
|
||||||
|
state->reg82 = val;
|
||||||
|
|
||||||
|
/* configure ED/HD Color DAC Swap bit to zero */
|
||||||
|
val = state->reg35 & HD_DAC_SWAP_DI;
|
||||||
|
err = adv7393_write(sd, ADV7393_HD_MODE_REG6, val);
|
||||||
|
if (err < 0)
|
||||||
|
goto setoutput_exit;
|
||||||
|
|
||||||
|
state->reg35 = val;
|
||||||
|
|
||||||
|
setoutput_exit:
|
||||||
|
if (err != 0)
|
||||||
|
v4l2_err(sd, "Error setting output, write failed\n");
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int adv7393_log_status(struct v4l2_subdev *sd)
|
||||||
|
{
|
||||||
|
struct adv7393_state *state = to_state(sd);
|
||||||
|
|
||||||
|
v4l2_info(sd, "Standard: %llx\n", (unsigned long long)state->std);
|
||||||
|
v4l2_info(sd, "Output: %s\n", (state->output == 0) ? "Composite" :
|
||||||
|
((state->output == 1) ? "Component" : "S-Video"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int adv7393_s_ctrl(struct v4l2_ctrl *ctrl)
|
||||||
|
{
|
||||||
|
struct v4l2_subdev *sd = to_sd(ctrl);
|
||||||
|
|
||||||
|
switch (ctrl->id) {
|
||||||
|
case V4L2_CID_BRIGHTNESS:
|
||||||
|
return adv7393_write(sd, ADV7393_SD_BRIGHTNESS_WSS,
|
||||||
|
ctrl->val & SD_BRIGHTNESS_VALUE_MASK);
|
||||||
|
|
||||||
|
case V4L2_CID_HUE:
|
||||||
|
return adv7393_write(sd, ADV7393_SD_HUE_ADJUST,
|
||||||
|
ctrl->val - ADV7393_HUE_MIN);
|
||||||
|
|
||||||
|
case V4L2_CID_GAIN:
|
||||||
|
return adv7393_write(sd, ADV7393_DAC123_OUTPUT_LEVEL,
|
||||||
|
ctrl->val);
|
||||||
|
}
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int adv7393_g_chip_ident(struct v4l2_subdev *sd,
|
||||||
|
struct v4l2_dbg_chip_ident *chip)
|
||||||
|
{
|
||||||
|
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||||
|
|
||||||
|
return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7393, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct v4l2_ctrl_ops adv7393_ctrl_ops = {
|
||||||
|
.s_ctrl = adv7393_s_ctrl,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct v4l2_subdev_core_ops adv7393_core_ops = {
|
||||||
|
.log_status = adv7393_log_status,
|
||||||
|
.g_chip_ident = adv7393_g_chip_ident,
|
||||||
|
.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
|
||||||
|
.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
|
||||||
|
.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
|
||||||
|
.g_ctrl = v4l2_subdev_g_ctrl,
|
||||||
|
.s_ctrl = v4l2_subdev_s_ctrl,
|
||||||
|
.queryctrl = v4l2_subdev_queryctrl,
|
||||||
|
.querymenu = v4l2_subdev_querymenu,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int adv7393_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
|
||||||
|
{
|
||||||
|
struct adv7393_state *state = to_state(sd);
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
if (state->std == std)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err = adv7393_setstd(sd, std);
|
||||||
|
if (!err)
|
||||||
|
state->std = std;
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int adv7393_s_routing(struct v4l2_subdev *sd,
|
||||||
|
u32 input, u32 output, u32 config)
|
||||||
|
{
|
||||||
|
struct adv7393_state *state = to_state(sd);
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
if (state->output == output)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err = adv7393_setoutput(sd, output);
|
||||||
|
if (!err)
|
||||||
|
state->output = output;
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct v4l2_subdev_video_ops adv7393_video_ops = {
|
||||||
|
.s_std_output = adv7393_s_std_output,
|
||||||
|
.s_routing = adv7393_s_routing,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct v4l2_subdev_ops adv7393_ops = {
|
||||||
|
.core = &adv7393_core_ops,
|
||||||
|
.video = &adv7393_video_ops,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int adv7393_initialize(struct v4l2_subdev *sd)
|
||||||
|
{
|
||||||
|
struct adv7393_state *state = to_state(sd);
|
||||||
|
int err = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(adv7393_init_reg_val); i += 2) {
|
||||||
|
|
||||||
|
err = adv7393_write(sd, adv7393_init_reg_val[i],
|
||||||
|
adv7393_init_reg_val[i+1]);
|
||||||
|
if (err) {
|
||||||
|
v4l2_err(sd, "Error initializing\n");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Configure for default video standard */
|
||||||
|
err = adv7393_setoutput(sd, state->output);
|
||||||
|
if (err < 0) {
|
||||||
|
v4l2_err(sd, "Error setting output during init\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = adv7393_setstd(sd, state->std);
|
||||||
|
if (err < 0) {
|
||||||
|
v4l2_err(sd, "Error setting std during init\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int adv7393_probe(struct i2c_client *client,
|
||||||
|
const struct i2c_device_id *id)
|
||||||
|
{
|
||||||
|
struct adv7393_state *state;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
v4l_info(client, "chip found @ 0x%x (%s)\n",
|
||||||
|
client->addr << 1, client->adapter->name);
|
||||||
|
|
||||||
|
state = kzalloc(sizeof(struct adv7393_state), GFP_KERNEL);
|
||||||
|
if (state == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
state->reg00 = ADV7393_POWER_MODE_REG_DEFAULT;
|
||||||
|
state->reg01 = 0x00;
|
||||||
|
state->reg02 = 0x20;
|
||||||
|
state->reg35 = ADV7393_HD_MODE_REG6_DEFAULT;
|
||||||
|
state->reg80 = ADV7393_SD_MODE_REG1_DEFAULT;
|
||||||
|
state->reg82 = ADV7393_SD_MODE_REG2_DEFAULT;
|
||||||
|
|
||||||
|
state->output = ADV7393_COMPOSITE_ID;
|
||||||
|
state->std = V4L2_STD_NTSC;
|
||||||
|
|
||||||
|
v4l2_i2c_subdev_init(&state->sd, client, &adv7393_ops);
|
||||||
|
|
||||||
|
v4l2_ctrl_handler_init(&state->hdl, 3);
|
||||||
|
v4l2_ctrl_new_std(&state->hdl, &adv7393_ctrl_ops,
|
||||||
|
V4L2_CID_BRIGHTNESS, ADV7393_BRIGHTNESS_MIN,
|
||||||
|
ADV7393_BRIGHTNESS_MAX, 1,
|
||||||
|
ADV7393_BRIGHTNESS_DEF);
|
||||||
|
v4l2_ctrl_new_std(&state->hdl, &adv7393_ctrl_ops,
|
||||||
|
V4L2_CID_HUE, ADV7393_HUE_MIN,
|
||||||
|
ADV7393_HUE_MAX, 1,
|
||||||
|
ADV7393_HUE_DEF);
|
||||||
|
v4l2_ctrl_new_std(&state->hdl, &adv7393_ctrl_ops,
|
||||||
|
V4L2_CID_GAIN, ADV7393_GAIN_MIN,
|
||||||
|
ADV7393_GAIN_MAX, 1,
|
||||||
|
ADV7393_GAIN_DEF);
|
||||||
|
state->sd.ctrl_handler = &state->hdl;
|
||||||
|
if (state->hdl.error) {
|
||||||
|
int err = state->hdl.error;
|
||||||
|
|
||||||
|
v4l2_ctrl_handler_free(&state->hdl);
|
||||||
|
kfree(state);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
v4l2_ctrl_handler_setup(&state->hdl);
|
||||||
|
|
||||||
|
err = adv7393_initialize(&state->sd);
|
||||||
|
if (err) {
|
||||||
|
v4l2_ctrl_handler_free(&state->hdl);
|
||||||
|
kfree(state);
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int adv7393_remove(struct i2c_client *client)
|
||||||
|
{
|
||||||
|
struct v4l2_subdev *sd = i2c_get_clientdata(client);
|
||||||
|
struct adv7393_state *state = to_state(sd);
|
||||||
|
|
||||||
|
v4l2_device_unregister_subdev(sd);
|
||||||
|
v4l2_ctrl_handler_free(&state->hdl);
|
||||||
|
kfree(state);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct i2c_device_id adv7393_id[] = {
|
||||||
|
{"adv7393", 0},
|
||||||
|
{},
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(i2c, adv7393_id);
|
||||||
|
|
||||||
|
static struct i2c_driver adv7393_driver = {
|
||||||
|
.driver = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.name = "adv7393",
|
||||||
|
},
|
||||||
|
.probe = adv7393_probe,
|
||||||
|
.remove = adv7393_remove,
|
||||||
|
.id_table = adv7393_id,
|
||||||
|
};
|
||||||
|
module_i2c_driver(adv7393_driver);
|
|
@ -0,0 +1,188 @@
|
||||||
|
/*
|
||||||
|
* ADV7393 encoder related structure and register definitions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010-2012 ADVANSEE - http://www.advansee.com/
|
||||||
|
* Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
|
||||||
|
*
|
||||||
|
* Based on ADV7343 driver,
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation version 2.
|
||||||
|
*
|
||||||
|
* This program is distributed .as is. WITHOUT ANY WARRANTY of any
|
||||||
|
* kind, whether express or implied; without even the implied warranty
|
||||||
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ADV7393_REGS_H
|
||||||
|
#define ADV7393_REGS_H
|
||||||
|
|
||||||
|
struct adv7393_std_info {
|
||||||
|
u32 standard_val3;
|
||||||
|
u32 fsc_val;
|
||||||
|
v4l2_std_id stdid;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Register offset macros */
|
||||||
|
#define ADV7393_POWER_MODE_REG (0x00)
|
||||||
|
#define ADV7393_MODE_SELECT_REG (0x01)
|
||||||
|
#define ADV7393_MODE_REG0 (0x02)
|
||||||
|
|
||||||
|
#define ADV7393_DAC123_OUTPUT_LEVEL (0x0B)
|
||||||
|
|
||||||
|
#define ADV7393_SOFT_RESET (0x17)
|
||||||
|
|
||||||
|
#define ADV7393_HD_MODE_REG1 (0x30)
|
||||||
|
#define ADV7393_HD_MODE_REG2 (0x31)
|
||||||
|
#define ADV7393_HD_MODE_REG3 (0x32)
|
||||||
|
#define ADV7393_HD_MODE_REG4 (0x33)
|
||||||
|
#define ADV7393_HD_MODE_REG5 (0x34)
|
||||||
|
#define ADV7393_HD_MODE_REG6 (0x35)
|
||||||
|
|
||||||
|
#define ADV7393_HD_MODE_REG7 (0x39)
|
||||||
|
|
||||||
|
#define ADV7393_SD_MODE_REG1 (0x80)
|
||||||
|
#define ADV7393_SD_MODE_REG2 (0x82)
|
||||||
|
#define ADV7393_SD_MODE_REG3 (0x83)
|
||||||
|
#define ADV7393_SD_MODE_REG4 (0x84)
|
||||||
|
#define ADV7393_SD_MODE_REG5 (0x86)
|
||||||
|
#define ADV7393_SD_MODE_REG6 (0x87)
|
||||||
|
#define ADV7393_SD_MODE_REG7 (0x88)
|
||||||
|
#define ADV7393_SD_MODE_REG8 (0x89)
|
||||||
|
|
||||||
|
#define ADV7393_SD_TIMING_REG0 (0x8A)
|
||||||
|
|
||||||
|
#define ADV7393_FSC_REG0 (0x8C)
|
||||||
|
#define ADV7393_FSC_REG1 (0x8D)
|
||||||
|
#define ADV7393_FSC_REG2 (0x8E)
|
||||||
|
#define ADV7393_FSC_REG3 (0x8F)
|
||||||
|
|
||||||
|
#define ADV7393_SD_CGMS_WSS0 (0x99)
|
||||||
|
|
||||||
|
#define ADV7393_SD_HUE_ADJUST (0xA0)
|
||||||
|
#define ADV7393_SD_BRIGHTNESS_WSS (0xA1)
|
||||||
|
|
||||||
|
/* Default values for the registers */
|
||||||
|
#define ADV7393_POWER_MODE_REG_DEFAULT (0x10)
|
||||||
|
#define ADV7393_HD_MODE_REG1_DEFAULT (0x3C) /* Changed Default
|
||||||
|
720p EAV/SAV code*/
|
||||||
|
#define ADV7393_HD_MODE_REG2_DEFAULT (0x01) /* Changed Pixel data
|
||||||
|
valid */
|
||||||
|
#define ADV7393_HD_MODE_REG3_DEFAULT (0x00) /* Color delay 0 clks */
|
||||||
|
#define ADV7393_HD_MODE_REG4_DEFAULT (0xEC) /* Changed */
|
||||||
|
#define ADV7393_HD_MODE_REG5_DEFAULT (0x08)
|
||||||
|
#define ADV7393_HD_MODE_REG6_DEFAULT (0x00)
|
||||||
|
#define ADV7393_HD_MODE_REG7_DEFAULT (0x00)
|
||||||
|
#define ADV7393_SOFT_RESET_DEFAULT (0x02)
|
||||||
|
#define ADV7393_COMPOSITE_POWER_VALUE (0x10)
|
||||||
|
#define ADV7393_COMPONENT_POWER_VALUE (0x1C)
|
||||||
|
#define ADV7393_SVIDEO_POWER_VALUE (0x0C)
|
||||||
|
#define ADV7393_SD_HUE_ADJUST_DEFAULT (0x80)
|
||||||
|
#define ADV7393_SD_BRIGHTNESS_WSS_DEFAULT (0x00)
|
||||||
|
|
||||||
|
#define ADV7393_SD_CGMS_WSS0_DEFAULT (0x10)
|
||||||
|
|
||||||
|
#define ADV7393_SD_MODE_REG1_DEFAULT (0x10)
|
||||||
|
#define ADV7393_SD_MODE_REG2_DEFAULT (0xC9)
|
||||||
|
#define ADV7393_SD_MODE_REG3_DEFAULT (0x00)
|
||||||
|
#define ADV7393_SD_MODE_REG4_DEFAULT (0x00)
|
||||||
|
#define ADV7393_SD_MODE_REG5_DEFAULT (0x02)
|
||||||
|
#define ADV7393_SD_MODE_REG6_DEFAULT (0x8C)
|
||||||
|
#define ADV7393_SD_MODE_REG7_DEFAULT (0x14)
|
||||||
|
#define ADV7393_SD_MODE_REG8_DEFAULT (0x00)
|
||||||
|
|
||||||
|
#define ADV7393_SD_TIMING_REG0_DEFAULT (0x0C)
|
||||||
|
|
||||||
|
/* Bit masks for Mode Select Register */
|
||||||
|
#define INPUT_MODE_MASK (0x70)
|
||||||
|
#define SD_INPUT_MODE (0x00)
|
||||||
|
#define HD_720P_INPUT_MODE (0x10)
|
||||||
|
#define HD_1080I_INPUT_MODE (0x10)
|
||||||
|
|
||||||
|
/* Bit masks for Mode Register 0 */
|
||||||
|
#define TEST_PATTERN_BLACK_BAR_EN (0x04)
|
||||||
|
#define YUV_OUTPUT_SELECT (0x20)
|
||||||
|
#define RGB_OUTPUT_SELECT (0xDF)
|
||||||
|
|
||||||
|
/* Bit masks for SD brightness/WSS */
|
||||||
|
#define SD_BRIGHTNESS_VALUE_MASK (0x7F)
|
||||||
|
#define SD_BLANK_WSS_DATA_MASK (0x80)
|
||||||
|
|
||||||
|
/* Bit masks for soft reset register */
|
||||||
|
#define SOFT_RESET (0x02)
|
||||||
|
|
||||||
|
/* Bit masks for HD Mode Register 1 */
|
||||||
|
#define OUTPUT_STD_MASK (0x03)
|
||||||
|
#define OUTPUT_STD_SHIFT (0)
|
||||||
|
#define OUTPUT_STD_EIA0_2 (0x00)
|
||||||
|
#define OUTPUT_STD_EIA0_1 (0x01)
|
||||||
|
#define OUTPUT_STD_FULL (0x02)
|
||||||
|
#define EMBEDDED_SYNC (0x04)
|
||||||
|
#define EXTERNAL_SYNC (0xFB)
|
||||||
|
#define STD_MODE_MASK (0x1F)
|
||||||
|
#define STD_MODE_SHIFT (3)
|
||||||
|
#define STD_MODE_720P (0x05)
|
||||||
|
#define STD_MODE_720P_25 (0x08)
|
||||||
|
#define STD_MODE_720P_30 (0x07)
|
||||||
|
#define STD_MODE_720P_50 (0x06)
|
||||||
|
#define STD_MODE_1080I (0x0D)
|
||||||
|
#define STD_MODE_1080I_25 (0x0E)
|
||||||
|
#define STD_MODE_1080P_24 (0x11)
|
||||||
|
#define STD_MODE_1080P_25 (0x10)
|
||||||
|
#define STD_MODE_1080P_30 (0x0F)
|
||||||
|
#define STD_MODE_525P (0x00)
|
||||||
|
#define STD_MODE_625P (0x03)
|
||||||
|
|
||||||
|
/* Bit masks for SD Mode Register 1 */
|
||||||
|
#define SD_STD_MASK (0x03)
|
||||||
|
#define SD_STD_NTSC (0x00)
|
||||||
|
#define SD_STD_PAL_BDGHI (0x01)
|
||||||
|
#define SD_STD_PAL_M (0x02)
|
||||||
|
#define SD_STD_PAL_N (0x03)
|
||||||
|
#define SD_LUMA_FLTR_MASK (0x07)
|
||||||
|
#define SD_LUMA_FLTR_SHIFT (2)
|
||||||
|
#define SD_CHROMA_FLTR_MASK (0x07)
|
||||||
|
#define SD_CHROMA_FLTR_SHIFT (5)
|
||||||
|
|
||||||
|
/* Bit masks for SD Mode Register 2 */
|
||||||
|
#define SD_PRPB_SSAF_EN (0x01)
|
||||||
|
#define SD_PRPB_SSAF_DI (0xFE)
|
||||||
|
#define SD_DAC_OUT1_EN (0x02)
|
||||||
|
#define SD_DAC_OUT1_DI (0xFD)
|
||||||
|
#define SD_PEDESTAL_EN (0x08)
|
||||||
|
#define SD_PEDESTAL_DI (0xF7)
|
||||||
|
#define SD_SQUARE_PIXEL_EN (0x10)
|
||||||
|
#define SD_SQUARE_PIXEL_DI (0xEF)
|
||||||
|
#define SD_PIXEL_DATA_VALID (0x40)
|
||||||
|
#define SD_ACTIVE_EDGE_EN (0x80)
|
||||||
|
#define SD_ACTIVE_EDGE_DI (0x7F)
|
||||||
|
|
||||||
|
/* Bit masks for HD Mode Register 6 */
|
||||||
|
#define HD_PRPB_SYNC_EN (0x04)
|
||||||
|
#define HD_PRPB_SYNC_DI (0xFB)
|
||||||
|
#define HD_DAC_SWAP_EN (0x08)
|
||||||
|
#define HD_DAC_SWAP_DI (0xF7)
|
||||||
|
#define HD_GAMMA_CURVE_A (0xEF)
|
||||||
|
#define HD_GAMMA_CURVE_B (0x10)
|
||||||
|
#define HD_GAMMA_EN (0x20)
|
||||||
|
#define HD_GAMMA_DI (0xDF)
|
||||||
|
#define HD_ADPT_FLTR_MODEA (0xBF)
|
||||||
|
#define HD_ADPT_FLTR_MODEB (0x40)
|
||||||
|
#define HD_ADPT_FLTR_EN (0x80)
|
||||||
|
#define HD_ADPT_FLTR_DI (0x7F)
|
||||||
|
|
||||||
|
#define ADV7393_BRIGHTNESS_MAX (63)
|
||||||
|
#define ADV7393_BRIGHTNESS_MIN (-64)
|
||||||
|
#define ADV7393_BRIGHTNESS_DEF (0)
|
||||||
|
#define ADV7393_HUE_MAX (127)
|
||||||
|
#define ADV7393_HUE_MIN (-128)
|
||||||
|
#define ADV7393_HUE_DEF (0)
|
||||||
|
#define ADV7393_GAIN_MAX (64)
|
||||||
|
#define ADV7393_GAIN_MIN (-64)
|
||||||
|
#define ADV7393_GAIN_DEF (0)
|
||||||
|
|
||||||
|
#endif
|
|
@ -676,6 +676,7 @@ struct tvcard bttv_tvcards[] = {
|
||||||
.tuner_type = UNSET,
|
.tuner_type = UNSET,
|
||||||
.tuner_addr = ADDR_UNSET,
|
.tuner_addr = ADDR_UNSET,
|
||||||
.has_remote = 1,
|
.has_remote = 1,
|
||||||
|
.has_radio = 1, /* not every card has radio */
|
||||||
},
|
},
|
||||||
[BTTV_BOARD_VOBIS_BOOSTAR] = {
|
[BTTV_BOARD_VOBIS_BOOSTAR] = {
|
||||||
.name = "Terratec TerraTV+ Version 1.0 (Bt848)/ Terra TValue Version 1.0/ Vobis TV-Boostar",
|
.name = "Terratec TerraTV+ Version 1.0 (Bt848)/ Terra TValue Version 1.0/ Vobis TV-Boostar",
|
||||||
|
|
|
@ -557,12 +557,6 @@ static const struct bttv_format formats[] = {
|
||||||
.btformat = BT848_COLOR_FMT_YUY2,
|
.btformat = BT848_COLOR_FMT_YUY2,
|
||||||
.depth = 16,
|
.depth = 16,
|
||||||
.flags = FORMAT_FLAGS_PACKED,
|
.flags = FORMAT_FLAGS_PACKED,
|
||||||
},{
|
|
||||||
.name = "4:2:2, packed, YUYV",
|
|
||||||
.fourcc = V4L2_PIX_FMT_YUYV,
|
|
||||||
.btformat = BT848_COLOR_FMT_YUY2,
|
|
||||||
.depth = 16,
|
|
||||||
.flags = FORMAT_FLAGS_PACKED,
|
|
||||||
},{
|
},{
|
||||||
.name = "4:2:2, packed, UYVY",
|
.name = "4:2:2, packed, UYVY",
|
||||||
.fourcc = V4L2_PIX_FMT_UYVY,
|
.fourcc = V4L2_PIX_FMT_UYVY,
|
||||||
|
|
|
@ -932,7 +932,7 @@ static int cpia2_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
|
||||||
buf->sequence = cam->buffers[buf->index].seq;
|
buf->sequence = cam->buffers[buf->index].seq;
|
||||||
buf->m.offset = cam->buffers[buf->index].data - cam->frame_buffer;
|
buf->m.offset = cam->buffers[buf->index].data - cam->frame_buffer;
|
||||||
buf->length = cam->frame_size;
|
buf->length = cam->frame_size;
|
||||||
buf->input = 0;
|
buf->reserved2 = 0;
|
||||||
buf->reserved = 0;
|
buf->reserved = 0;
|
||||||
memset(&buf->timecode, 0, sizeof(buf->timecode));
|
memset(&buf->timecode, 0, sizeof(buf->timecode));
|
||||||
|
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
/* cs8420.h - cs8420 initializations
|
|
||||||
Copyright (C) 1999 Nathan Laredo (laredo@gnu.org)
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
|
|
||||||
*/
|
|
||||||
#ifndef __CS8420_H__
|
|
||||||
#define __CS8420_H__
|
|
||||||
|
|
||||||
/* Initialization Sequence */
|
|
||||||
|
|
||||||
static __u8 init8420[] = {
|
|
||||||
1, 0x01, 2, 0x02, 3, 0x00, 4, 0x46,
|
|
||||||
5, 0x24, 6, 0x84, 18, 0x18, 19, 0x13,
|
|
||||||
};
|
|
||||||
|
|
||||||
#define INIT8420LEN (sizeof(init8420)/2)
|
|
||||||
|
|
||||||
static __u8 mode8420pro[] = { /* professional output mode */
|
|
||||||
32, 0xa1, 33, 0x00, 34, 0x00, 35, 0x00,
|
|
||||||
36, 0x00, 37, 0x00, 38, 0x00, 39, 0x00,
|
|
||||||
40, 0x00, 41, 0x00, 42, 0x00, 43, 0x00,
|
|
||||||
44, 0x00, 45, 0x00, 46, 0x00, 47, 0x00,
|
|
||||||
48, 0x00, 49, 0x00, 50, 0x00, 51, 0x00,
|
|
||||||
52, 0x00, 53, 0x00, 54, 0x00, 55, 0x00,
|
|
||||||
};
|
|
||||||
#define MODE8420LEN (sizeof(mode8420pro)/2)
|
|
||||||
|
|
||||||
static __u8 mode8420con[] = { /* consumer output mode */
|
|
||||||
32, 0x20, 33, 0x00, 34, 0x00, 35, 0x48,
|
|
||||||
36, 0x00, 37, 0x00, 38, 0x00, 39, 0x00,
|
|
||||||
40, 0x00, 41, 0x00, 42, 0x00, 43, 0x00,
|
|
||||||
44, 0x00, 45, 0x00, 46, 0x00, 47, 0x00,
|
|
||||||
48, 0x00, 49, 0x00, 50, 0x00, 51, 0x00,
|
|
||||||
52, 0x00, 53, 0x00, 54, 0x00, 55, 0x00,
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1142,24 +1142,6 @@ static long cx18_default(struct file *file, void *fh, bool valid_prio,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
long cx18_v4l2_ioctl(struct file *filp, unsigned int cmd,
|
|
||||||
unsigned long arg)
|
|
||||||
{
|
|
||||||
struct video_device *vfd = video_devdata(filp);
|
|
||||||
struct cx18_open_id *id = file2id(filp);
|
|
||||||
struct cx18 *cx = id->cx;
|
|
||||||
long res;
|
|
||||||
|
|
||||||
mutex_lock(&cx->serialize_lock);
|
|
||||||
|
|
||||||
if (cx18_debug & CX18_DBGFLG_IOCTL)
|
|
||||||
vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
|
|
||||||
res = video_ioctl2(filp, cmd, arg);
|
|
||||||
vfd->debug = 0;
|
|
||||||
mutex_unlock(&cx->serialize_lock);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct v4l2_ioctl_ops cx18_ioctl_ops = {
|
static const struct v4l2_ioctl_ops cx18_ioctl_ops = {
|
||||||
.vidioc_querycap = cx18_querycap,
|
.vidioc_querycap = cx18_querycap,
|
||||||
.vidioc_s_audio = cx18_s_audio,
|
.vidioc_s_audio = cx18_s_audio,
|
||||||
|
|
|
@ -29,5 +29,3 @@ void cx18_set_funcs(struct video_device *vdev);
|
||||||
int cx18_s_std(struct file *file, void *fh, v4l2_std_id *std);
|
int cx18_s_std(struct file *file, void *fh, v4l2_std_id *std);
|
||||||
int cx18_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf);
|
int cx18_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf);
|
||||||
int cx18_s_input(struct file *file, void *fh, unsigned int inp);
|
int cx18_s_input(struct file *file, void *fh, unsigned int inp);
|
||||||
long cx18_v4l2_ioctl(struct file *filp, unsigned int cmd,
|
|
||||||
unsigned long arg);
|
|
||||||
|
|
|
@ -40,8 +40,7 @@ static struct v4l2_file_operations cx18_v4l2_enc_fops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.read = cx18_v4l2_read,
|
.read = cx18_v4l2_read,
|
||||||
.open = cx18_v4l2_open,
|
.open = cx18_v4l2_open,
|
||||||
/* FIXME change to video_ioctl2 if serialization lock can be removed */
|
.unlocked_ioctl = video_ioctl2,
|
||||||
.unlocked_ioctl = cx18_v4l2_ioctl,
|
|
||||||
.release = cx18_v4l2_close,
|
.release = cx18_v4l2_close,
|
||||||
.poll = cx18_v4l2_enc_poll,
|
.poll = cx18_v4l2_enc_poll,
|
||||||
.mmap = cx18_v4l2_mmap,
|
.mmap = cx18_v4l2_mmap,
|
||||||
|
@ -376,6 +375,7 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
|
||||||
s->video_dev->fops = &cx18_v4l2_enc_fops;
|
s->video_dev->fops = &cx18_v4l2_enc_fops;
|
||||||
s->video_dev->release = video_device_release;
|
s->video_dev->release = video_device_release;
|
||||||
s->video_dev->tvnorms = V4L2_STD_ALL;
|
s->video_dev->tvnorms = V4L2_STD_ALL;
|
||||||
|
s->video_dev->lock = &cx->serialize_lock;
|
||||||
set_bit(V4L2_FL_USE_FH_PRIO, &s->video_dev->flags);
|
set_bit(V4L2_FL_USE_FH_PRIO, &s->video_dev->flags);
|
||||||
cx18_set_funcs(s->video_dev);
|
cx18_set_funcs(s->video_dev);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -89,7 +89,7 @@ void initGPIO(struct cx231xx *dev)
|
||||||
verve_read_byte(dev, 0x07, &val);
|
verve_read_byte(dev, 0x07, &val);
|
||||||
cx231xx_info(" verve_read_byte address0x07=0x%x\n", val);
|
cx231xx_info(" verve_read_byte address0x07=0x%x\n", val);
|
||||||
|
|
||||||
cx231xx_capture_start(dev, 1, 2);
|
cx231xx_capture_start(dev, 1, Vbi);
|
||||||
|
|
||||||
cx231xx_mode_register(dev, EP_MODE_SET, 0x0500FE00);
|
cx231xx_mode_register(dev, EP_MODE_SET, 0x0500FE00);
|
||||||
cx231xx_mode_register(dev, GBULK_BIT_EN, 0xFFFDFFFF);
|
cx231xx_mode_register(dev, GBULK_BIT_EN, 0xFFFDFFFF);
|
||||||
|
@ -99,7 +99,7 @@ void uninitGPIO(struct cx231xx *dev)
|
||||||
{
|
{
|
||||||
u8 value[4] = { 0, 0, 0, 0 };
|
u8 value[4] = { 0, 0, 0, 0 };
|
||||||
|
|
||||||
cx231xx_capture_start(dev, 0, 2);
|
cx231xx_capture_start(dev, 0, Vbi);
|
||||||
verve_write_byte(dev, 0x07, 0x14);
|
verve_write_byte(dev, 0x07, 0x14);
|
||||||
cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
|
cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
|
||||||
0x68, value, 4);
|
0x68, value, 4);
|
||||||
|
@ -2516,29 +2516,29 @@ int cx231xx_initialize_stream_xfer(struct cx231xx *dev, u32 media_type)
|
||||||
|
|
||||||
if (dev->udev->speed == USB_SPEED_HIGH) {
|
if (dev->udev->speed == USB_SPEED_HIGH) {
|
||||||
switch (media_type) {
|
switch (media_type) {
|
||||||
case 81: /* audio */
|
case Audio:
|
||||||
cx231xx_info("%s: Audio enter HANC\n", __func__);
|
cx231xx_info("%s: Audio enter HANC\n", __func__);
|
||||||
status =
|
status =
|
||||||
cx231xx_mode_register(dev, TS_MODE_REG, 0x9300);
|
cx231xx_mode_register(dev, TS_MODE_REG, 0x9300);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: /* vbi */
|
case Vbi:
|
||||||
cx231xx_info("%s: set vanc registers\n", __func__);
|
cx231xx_info("%s: set vanc registers\n", __func__);
|
||||||
status = cx231xx_mode_register(dev, TS_MODE_REG, 0x300);
|
status = cx231xx_mode_register(dev, TS_MODE_REG, 0x300);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3: /* sliced cc */
|
case Sliced_cc:
|
||||||
cx231xx_info("%s: set hanc registers\n", __func__);
|
cx231xx_info("%s: set hanc registers\n", __func__);
|
||||||
status =
|
status =
|
||||||
cx231xx_mode_register(dev, TS_MODE_REG, 0x1300);
|
cx231xx_mode_register(dev, TS_MODE_REG, 0x1300);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0: /* video */
|
case Raw_Video:
|
||||||
cx231xx_info("%s: set video registers\n", __func__);
|
cx231xx_info("%s: set video registers\n", __func__);
|
||||||
status = cx231xx_mode_register(dev, TS_MODE_REG, 0x100);
|
status = cx231xx_mode_register(dev, TS_MODE_REG, 0x100);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4: /* ts1 */
|
case TS1_serial_mode:
|
||||||
cx231xx_info("%s: set ts1 registers", __func__);
|
cx231xx_info("%s: set ts1 registers", __func__);
|
||||||
|
|
||||||
if (dev->board.has_417) {
|
if (dev->board.has_417) {
|
||||||
|
@ -2569,7 +2569,7 @@ int cx231xx_initialize_stream_xfer(struct cx231xx *dev, u32 media_type)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 6: /* ts1 parallel mode */
|
case TS1_parallel_mode:
|
||||||
cx231xx_info("%s: set ts1 parallel mode registers\n",
|
cx231xx_info("%s: set ts1 parallel mode registers\n",
|
||||||
__func__);
|
__func__);
|
||||||
status = cx231xx_mode_register(dev, TS_MODE_REG, 0x100);
|
status = cx231xx_mode_register(dev, TS_MODE_REG, 0x100);
|
||||||
|
@ -2592,52 +2592,28 @@ int cx231xx_capture_start(struct cx231xx *dev, int start, u8 media_type)
|
||||||
/* get EP for media type */
|
/* get EP for media type */
|
||||||
pcb_config = (struct pcb_config *)&dev->current_pcb_config;
|
pcb_config = (struct pcb_config *)&dev->current_pcb_config;
|
||||||
|
|
||||||
if (pcb_config->config_num == 1) {
|
if (pcb_config->config_num) {
|
||||||
switch (media_type) {
|
switch (media_type) {
|
||||||
case 0: /* Video */
|
case Raw_Video:
|
||||||
ep_mask = ENABLE_EP4; /* ep4 [00:1000] */
|
ep_mask = ENABLE_EP4; /* ep4 [00:1000] */
|
||||||
break;
|
break;
|
||||||
case 1: /* Audio */
|
case Audio:
|
||||||
ep_mask = ENABLE_EP3; /* ep3 [00:0100] */
|
ep_mask = ENABLE_EP3; /* ep3 [00:0100] */
|
||||||
break;
|
break;
|
||||||
case 2: /* Vbi */
|
case Vbi:
|
||||||
ep_mask = ENABLE_EP5; /* ep5 [01:0000] */
|
ep_mask = ENABLE_EP5; /* ep5 [01:0000] */
|
||||||
break;
|
break;
|
||||||
case 3: /* Sliced_cc */
|
case Sliced_cc:
|
||||||
ep_mask = ENABLE_EP6; /* ep6 [10:0000] */
|
ep_mask = ENABLE_EP6; /* ep6 [10:0000] */
|
||||||
break;
|
break;
|
||||||
case 4: /* ts1 */
|
case TS1_serial_mode:
|
||||||
case 6: /* ts1 parallel mode */
|
case TS1_parallel_mode:
|
||||||
ep_mask = ENABLE_EP1; /* ep1 [00:0001] */
|
ep_mask = ENABLE_EP1; /* ep1 [00:0001] */
|
||||||
break;
|
break;
|
||||||
case 5: /* ts2 */
|
case TS2:
|
||||||
ep_mask = ENABLE_EP2; /* ep2 [00:0010] */
|
ep_mask = ENABLE_EP2; /* ep2 [00:0010] */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (pcb_config->config_num > 1) {
|
|
||||||
switch (media_type) {
|
|
||||||
case 0: /* Video */
|
|
||||||
ep_mask = ENABLE_EP4; /* ep4 [00:1000] */
|
|
||||||
break;
|
|
||||||
case 1: /* Audio */
|
|
||||||
ep_mask = ENABLE_EP3; /* ep3 [00:0100] */
|
|
||||||
break;
|
|
||||||
case 2: /* Vbi */
|
|
||||||
ep_mask = ENABLE_EP5; /* ep5 [01:0000] */
|
|
||||||
break;
|
|
||||||
case 3: /* Sliced_cc */
|
|
||||||
ep_mask = ENABLE_EP6; /* ep6 [10:0000] */
|
|
||||||
break;
|
|
||||||
case 4: /* ts1 */
|
|
||||||
case 6: /* ts1 parallel mode */
|
|
||||||
ep_mask = ENABLE_EP1; /* ep1 [00:0001] */
|
|
||||||
break;
|
|
||||||
case 5: /* ts2 */
|
|
||||||
ep_mask = ENABLE_EP2; /* ep2 [00:0010] */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (start) {
|
if (start) {
|
||||||
|
|
|
@ -1023,7 +1023,6 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
|
||||||
int nr = 0, ifnum;
|
int nr = 0, ifnum;
|
||||||
int i, isoc_pipe = 0;
|
int i, isoc_pipe = 0;
|
||||||
char *speed;
|
char *speed;
|
||||||
char descr[255] = "";
|
|
||||||
struct usb_interface_assoc_descriptor *assoc_desc;
|
struct usb_interface_assoc_descriptor *assoc_desc;
|
||||||
|
|
||||||
udev = usb_get_dev(interface_to_usbdev(interface));
|
udev = usb_get_dev(interface_to_usbdev(interface));
|
||||||
|
@ -1098,20 +1097,10 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
|
||||||
speed = "unknown";
|
speed = "unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (udev->manufacturer)
|
cx231xx_info("New device %s %s @ %s Mbps "
|
||||||
strlcpy(descr, udev->manufacturer, sizeof(descr));
|
|
||||||
|
|
||||||
if (udev->product) {
|
|
||||||
if (*descr)
|
|
||||||
strlcat(descr, " ", sizeof(descr));
|
|
||||||
strlcat(descr, udev->product, sizeof(descr));
|
|
||||||
}
|
|
||||||
if (*descr)
|
|
||||||
strlcat(descr, " ", sizeof(descr));
|
|
||||||
|
|
||||||
cx231xx_info("New device %s@ %s Mbps "
|
|
||||||
"(%04x:%04x) with %d interfaces\n",
|
"(%04x:%04x) with %d interfaces\n",
|
||||||
descr,
|
udev->manufacturer ? udev->manufacturer : "",
|
||||||
|
udev->product ? udev->product : "",
|
||||||
speed,
|
speed,
|
||||||
le16_to_cpu(udev->descriptor.idVendor),
|
le16_to_cpu(udev->descriptor.idVendor),
|
||||||
le16_to_cpu(udev->descriptor.idProduct),
|
le16_to_cpu(udev->descriptor.idProduct),
|
||||||
|
|
|
@ -585,13 +585,10 @@ static void snd_cx88_wm8775_volume_put(struct snd_kcontrol *kcontrol,
|
||||||
{
|
{
|
||||||
snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
|
snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
|
||||||
struct cx88_core *core = chip->core;
|
struct cx88_core *core = chip->core;
|
||||||
struct v4l2_control client_ctl;
|
|
||||||
int left = value->value.integer.value[0];
|
int left = value->value.integer.value[0];
|
||||||
int right = value->value.integer.value[1];
|
int right = value->value.integer.value[1];
|
||||||
int v, b;
|
int v, b;
|
||||||
|
|
||||||
memset(&client_ctl, 0, sizeof(client_ctl));
|
|
||||||
|
|
||||||
/* Pass volume & balance onto any WM8775 */
|
/* Pass volume & balance onto any WM8775 */
|
||||||
if (left >= right) {
|
if (left >= right) {
|
||||||
v = left << 10;
|
v = left << 10;
|
||||||
|
@ -600,13 +597,8 @@ static void snd_cx88_wm8775_volume_put(struct snd_kcontrol *kcontrol,
|
||||||
v = right << 10;
|
v = right << 10;
|
||||||
b = right ? 0xffff - (0x8000 * left) / right : 0x8000;
|
b = right ? 0xffff - (0x8000 * left) / right : 0x8000;
|
||||||
}
|
}
|
||||||
client_ctl.value = v;
|
wm8775_s_ctrl(core, V4L2_CID_AUDIO_VOLUME, v);
|
||||||
client_ctl.id = V4L2_CID_AUDIO_VOLUME;
|
wm8775_s_ctrl(core, V4L2_CID_AUDIO_BALANCE, b);
|
||||||
call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
|
|
||||||
|
|
||||||
client_ctl.value = b;
|
|
||||||
client_ctl.id = V4L2_CID_AUDIO_BALANCE;
|
|
||||||
call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* OK - TODO: test it */
|
/* OK - TODO: test it */
|
||||||
|
@ -687,14 +679,8 @@ static int snd_cx88_switch_put(struct snd_kcontrol *kcontrol,
|
||||||
cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, vol);
|
cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, vol);
|
||||||
/* Pass mute onto any WM8775 */
|
/* Pass mute onto any WM8775 */
|
||||||
if ((core->board.audio_chip == V4L2_IDENT_WM8775) &&
|
if ((core->board.audio_chip == V4L2_IDENT_WM8775) &&
|
||||||
((1<<6) == bit)) {
|
((1<<6) == bit))
|
||||||
struct v4l2_control client_ctl;
|
wm8775_s_ctrl(core, V4L2_CID_AUDIO_MUTE, 0 != (vol & bit));
|
||||||
|
|
||||||
memset(&client_ctl, 0, sizeof(client_ctl));
|
|
||||||
client_ctl.value = 0 != (vol & bit);
|
|
||||||
client_ctl.id = V4L2_CID_AUDIO_MUTE;
|
|
||||||
call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
|
|
||||||
}
|
|
||||||
ret = 1;
|
ret = 1;
|
||||||
}
|
}
|
||||||
spin_unlock_irq(&chip->reg_lock);
|
spin_unlock_irq(&chip->reg_lock);
|
||||||
|
@ -724,13 +710,10 @@ static int snd_cx88_alc_get(struct snd_kcontrol *kcontrol,
|
||||||
{
|
{
|
||||||
snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
|
snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
|
||||||
struct cx88_core *core = chip->core;
|
struct cx88_core *core = chip->core;
|
||||||
struct v4l2_control client_ctl;
|
s32 val;
|
||||||
|
|
||||||
memset(&client_ctl, 0, sizeof(client_ctl));
|
|
||||||
client_ctl.id = V4L2_CID_AUDIO_LOUDNESS;
|
|
||||||
call_hw(core, WM8775_GID, core, g_ctrl, &client_ctl);
|
|
||||||
value->value.integer.value[0] = client_ctl.value ? 1 : 0;
|
|
||||||
|
|
||||||
|
val = wm8775_g_ctrl(core, V4L2_CID_AUDIO_LOUDNESS);
|
||||||
|
value->value.integer.value[0] = val ? 1 : 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include <linux/firmware.h>
|
#include <linux/firmware.h>
|
||||||
#include <media/v4l2-common.h>
|
#include <media/v4l2-common.h>
|
||||||
#include <media/v4l2-ioctl.h>
|
#include <media/v4l2-ioctl.h>
|
||||||
|
#include <media/v4l2-event.h>
|
||||||
#include <media/cx2341x.h>
|
#include <media/cx2341x.h>
|
||||||
|
|
||||||
#include "cx88.h"
|
#include "cx88.h"
|
||||||
|
@ -523,11 +524,10 @@ static void blackbird_codec_settings(struct cx8802_dev *dev)
|
||||||
blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
|
blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
|
||||||
dev->height, dev->width);
|
dev->height, dev->width);
|
||||||
|
|
||||||
dev->params.width = dev->width;
|
dev->cxhdl.width = dev->width;
|
||||||
dev->params.height = dev->height;
|
dev->cxhdl.height = dev->height;
|
||||||
dev->params.is_50hz = (dev->core->tvnorm & V4L2_STD_625_50) != 0;
|
cx2341x_handler_set_50hz(&dev->cxhdl, dev->core->tvnorm & V4L2_STD_625_50);
|
||||||
|
cx2341x_handler_setup(&dev->cxhdl);
|
||||||
cx2341x_update(dev, blackbird_mbox_func, NULL, &dev->params);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int blackbird_initialize_codec(struct cx8802_dev *dev)
|
static int blackbird_initialize_codec(struct cx8802_dev *dev)
|
||||||
|
@ -618,6 +618,8 @@ static int blackbird_start_codec(struct file *file, void *priv)
|
||||||
/* initialize the video input */
|
/* initialize the video input */
|
||||||
blackbird_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0);
|
blackbird_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0);
|
||||||
|
|
||||||
|
cx2341x_handler_set_busy(&dev->cxhdl, 1);
|
||||||
|
|
||||||
/* start capturing to the host interface */
|
/* start capturing to the host interface */
|
||||||
blackbird_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0,
|
blackbird_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0,
|
||||||
BLACKBIRD_MPEG_CAPTURE,
|
BLACKBIRD_MPEG_CAPTURE,
|
||||||
|
@ -636,6 +638,8 @@ static int blackbird_stop_codec(struct cx8802_dev *dev)
|
||||||
BLACKBIRD_RAW_BITS_NONE
|
BLACKBIRD_RAW_BITS_NONE
|
||||||
);
|
);
|
||||||
|
|
||||||
|
cx2341x_handler_set_busy(&dev->cxhdl, 0);
|
||||||
|
|
||||||
dev->mpeg_active = 0;
|
dev->mpeg_active = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -685,58 +689,15 @@ static struct videobuf_queue_ops blackbird_qops = {
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
static const u32 *ctrl_classes[] = {
|
static int vidioc_querycap(struct file *file, void *priv,
|
||||||
cx88_user_ctrls,
|
|
||||||
cx2341x_mpeg_ctrls,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
static int blackbird_queryctrl(struct cx8802_dev *dev, struct v4l2_queryctrl *qctrl)
|
|
||||||
{
|
|
||||||
qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
|
|
||||||
if (qctrl->id == 0)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
/* Standard V4L2 controls */
|
|
||||||
if (cx8800_ctrl_query(dev->core, qctrl) == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* MPEG V4L2 controls */
|
|
||||||
if (cx2341x_ctrl_query(&dev->params, qctrl))
|
|
||||||
qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
|
||||||
/* IOCTL Handlers */
|
|
||||||
|
|
||||||
static int vidioc_querymenu (struct file *file, void *priv,
|
|
||||||
struct v4l2_querymenu *qmenu)
|
|
||||||
{
|
|
||||||
struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
|
|
||||||
struct v4l2_queryctrl qctrl;
|
|
||||||
|
|
||||||
qctrl.id = qmenu->id;
|
|
||||||
blackbird_queryctrl(dev, &qctrl);
|
|
||||||
return v4l2_ctrl_query_menu(qmenu, &qctrl,
|
|
||||||
cx2341x_ctrl_get_menu(&dev->params, qmenu->id));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int vidioc_querycap (struct file *file, void *priv,
|
|
||||||
struct v4l2_capability *cap)
|
struct v4l2_capability *cap)
|
||||||
{
|
{
|
||||||
struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
|
struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
|
||||||
struct cx88_core *core = dev->core;
|
struct cx88_core *core = dev->core;
|
||||||
|
|
||||||
strcpy(cap->driver, "cx88_blackbird");
|
strcpy(cap->driver, "cx88_blackbird");
|
||||||
strlcpy(cap->card, core->board.name, sizeof(cap->card));
|
sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
|
||||||
sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));
|
cx88_querycap(file, core, cap);
|
||||||
cap->capabilities =
|
|
||||||
V4L2_CAP_VIDEO_CAPTURE |
|
|
||||||
V4L2_CAP_READWRITE |
|
|
||||||
V4L2_CAP_STREAMING;
|
|
||||||
if (UNSET != core->board.tuner_type)
|
|
||||||
cap->capabilities |= V4L2_CAP_TUNER;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -748,6 +709,7 @@ static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv,
|
||||||
|
|
||||||
strlcpy(f->description, "MPEG", sizeof(f->description));
|
strlcpy(f->description, "MPEG", sizeof(f->description));
|
||||||
f->pixelformat = V4L2_PIX_FMT_MPEG;
|
f->pixelformat = V4L2_PIX_FMT_MPEG;
|
||||||
|
f->flags = V4L2_FMT_FLAG_COMPRESSED;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -759,12 +721,12 @@ static int vidioc_g_fmt_vid_cap (struct file *file, void *priv,
|
||||||
|
|
||||||
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
|
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
|
||||||
f->fmt.pix.bytesperline = 0;
|
f->fmt.pix.bytesperline = 0;
|
||||||
f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */
|
f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */;
|
||||||
f->fmt.pix.colorspace = 0;
|
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
|
||||||
f->fmt.pix.width = dev->width;
|
f->fmt.pix.width = dev->width;
|
||||||
f->fmt.pix.height = dev->height;
|
f->fmt.pix.height = dev->height;
|
||||||
f->fmt.pix.field = fh->mpegq.field;
|
f->fmt.pix.field = fh->mpegq.field;
|
||||||
dprintk(0,"VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
|
dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
|
||||||
dev->width, dev->height, fh->mpegq.field );
|
dev->width, dev->height, fh->mpegq.field );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -777,9 +739,9 @@ static int vidioc_try_fmt_vid_cap (struct file *file, void *priv,
|
||||||
|
|
||||||
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
|
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
|
||||||
f->fmt.pix.bytesperline = 0;
|
f->fmt.pix.bytesperline = 0;
|
||||||
f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */;
|
f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */;
|
||||||
f->fmt.pix.colorspace = 0;
|
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
|
||||||
dprintk(0,"VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
|
dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
|
||||||
dev->width, dev->height, fh->mpegq.field );
|
dev->width, dev->height, fh->mpegq.field );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -793,15 +755,15 @@ static int vidioc_s_fmt_vid_cap (struct file *file, void *priv,
|
||||||
|
|
||||||
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
|
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
|
||||||
f->fmt.pix.bytesperline = 0;
|
f->fmt.pix.bytesperline = 0;
|
||||||
f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */;
|
f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */;
|
||||||
f->fmt.pix.colorspace = 0;
|
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
|
||||||
dev->width = f->fmt.pix.width;
|
dev->width = f->fmt.pix.width;
|
||||||
dev->height = f->fmt.pix.height;
|
dev->height = f->fmt.pix.height;
|
||||||
fh->mpegq.field = f->fmt.pix.field;
|
fh->mpegq.field = f->fmt.pix.field;
|
||||||
cx88_set_scale(core, f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
|
cx88_set_scale(core, f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
|
||||||
blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
|
blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
|
||||||
f->fmt.pix.height, f->fmt.pix.width);
|
f->fmt.pix.height, f->fmt.pix.width);
|
||||||
dprintk(0,"VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
|
dprintk(1, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
|
||||||
f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field );
|
f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -834,60 +796,21 @@ static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p)
|
||||||
static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
|
static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
|
||||||
{
|
{
|
||||||
struct cx8802_fh *fh = priv;
|
struct cx8802_fh *fh = priv;
|
||||||
|
struct cx8802_dev *dev = fh->dev;
|
||||||
|
|
||||||
|
if (!dev->mpeg_active)
|
||||||
|
blackbird_start_codec(file, fh);
|
||||||
return videobuf_streamon(&fh->mpegq);
|
return videobuf_streamon(&fh->mpegq);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
|
static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
|
||||||
{
|
{
|
||||||
struct cx8802_fh *fh = priv;
|
struct cx8802_fh *fh = priv;
|
||||||
return videobuf_streamoff(&fh->mpegq);
|
struct cx8802_dev *dev = fh->dev;
|
||||||
}
|
|
||||||
|
|
||||||
static int vidioc_g_ext_ctrls (struct file *file, void *priv,
|
|
||||||
struct v4l2_ext_controls *f)
|
|
||||||
{
|
|
||||||
struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
|
|
||||||
|
|
||||||
if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
|
|
||||||
return -EINVAL;
|
|
||||||
return cx2341x_ext_ctrls(&dev->params, 0, f, VIDIOC_G_EXT_CTRLS);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int vidioc_s_ext_ctrls (struct file *file, void *priv,
|
|
||||||
struct v4l2_ext_controls *f)
|
|
||||||
{
|
|
||||||
struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
|
|
||||||
struct cx2341x_mpeg_params p;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (dev->mpeg_active)
|
if (dev->mpeg_active)
|
||||||
blackbird_stop_codec(dev);
|
blackbird_stop_codec(dev);
|
||||||
|
return videobuf_streamoff(&fh->mpegq);
|
||||||
p = dev->params;
|
|
||||||
err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_S_EXT_CTRLS);
|
|
||||||
if (!err) {
|
|
||||||
err = cx2341x_update(dev, blackbird_mbox_func, &dev->params, &p);
|
|
||||||
dev->params = p;
|
|
||||||
}
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int vidioc_try_ext_ctrls (struct file *file, void *priv,
|
|
||||||
struct v4l2_ext_controls *f)
|
|
||||||
{
|
|
||||||
struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
|
|
||||||
struct cx2341x_mpeg_params p;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
|
|
||||||
return -EINVAL;
|
|
||||||
p = dev->params;
|
|
||||||
err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_TRY_EXT_CTRLS);
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vidioc_s_frequency (struct file *file, void *priv,
|
static int vidioc_s_frequency (struct file *file, void *priv,
|
||||||
|
@ -897,6 +820,10 @@ static int vidioc_s_frequency (struct file *file, void *priv,
|
||||||
struct cx8802_dev *dev = fh->dev;
|
struct cx8802_dev *dev = fh->dev;
|
||||||
struct cx88_core *core = dev->core;
|
struct cx88_core *core = dev->core;
|
||||||
|
|
||||||
|
if (unlikely(UNSET == core->board.tuner_type))
|
||||||
|
return -EINVAL;
|
||||||
|
if (unlikely(f->tuner != 0))
|
||||||
|
return -EINVAL;
|
||||||
if (dev->mpeg_active)
|
if (dev->mpeg_active)
|
||||||
blackbird_stop_codec(dev);
|
blackbird_stop_codec(dev);
|
||||||
|
|
||||||
|
@ -914,29 +841,11 @@ static int vidioc_log_status (struct file *file, void *priv)
|
||||||
char name[32 + 2];
|
char name[32 + 2];
|
||||||
|
|
||||||
snprintf(name, sizeof(name), "%s/2", core->name);
|
snprintf(name, sizeof(name), "%s/2", core->name);
|
||||||
printk("%s/2: ============ START LOG STATUS ============\n",
|
|
||||||
core->name);
|
|
||||||
call_all(core, core, log_status);
|
call_all(core, core, log_status);
|
||||||
cx2341x_log_status(&dev->params, name);
|
v4l2_ctrl_handler_log_status(&dev->cxhdl.hdl, name);
|
||||||
printk("%s/2: ============= END LOG STATUS =============\n",
|
|
||||||
core->name);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vidioc_queryctrl (struct file *file, void *priv,
|
|
||||||
struct v4l2_queryctrl *qctrl)
|
|
||||||
{
|
|
||||||
struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
|
|
||||||
|
|
||||||
if (blackbird_queryctrl(dev, qctrl) == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
|
|
||||||
if (unlikely(qctrl->id == 0))
|
|
||||||
return -EINVAL;
|
|
||||||
return cx8800_ctrl_query(dev->core, qctrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int vidioc_enum_input (struct file *file, void *priv,
|
static int vidioc_enum_input (struct file *file, void *priv,
|
||||||
struct v4l2_input *i)
|
struct v4l2_input *i)
|
||||||
{
|
{
|
||||||
|
@ -944,22 +853,6 @@ static int vidioc_enum_input (struct file *file, void *priv,
|
||||||
return cx88_enum_input (core,i);
|
return cx88_enum_input (core,i);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vidioc_g_ctrl (struct file *file, void *priv,
|
|
||||||
struct v4l2_control *ctl)
|
|
||||||
{
|
|
||||||
struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
|
|
||||||
return
|
|
||||||
cx88_get_control(core,ctl);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int vidioc_s_ctrl (struct file *file, void *priv,
|
|
||||||
struct v4l2_control *ctl)
|
|
||||||
{
|
|
||||||
struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
|
|
||||||
return
|
|
||||||
cx88_set_control(core,ctl);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int vidioc_g_frequency (struct file *file, void *priv,
|
static int vidioc_g_frequency (struct file *file, void *priv,
|
||||||
struct v4l2_frequency *f)
|
struct v4l2_frequency *f)
|
||||||
{
|
{
|
||||||
|
@ -968,8 +861,9 @@ static int vidioc_g_frequency (struct file *file, void *priv,
|
||||||
|
|
||||||
if (unlikely(UNSET == core->board.tuner_type))
|
if (unlikely(UNSET == core->board.tuner_type))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
if (unlikely(f->tuner != 0))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
f->type = V4L2_TUNER_ANALOG_TV;
|
|
||||||
f->frequency = core->freq;
|
f->frequency = core->freq;
|
||||||
call_all(core, tuner, g_frequency, f);
|
call_all(core, tuner, g_frequency, f);
|
||||||
|
|
||||||
|
@ -990,6 +884,8 @@ static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
|
||||||
|
|
||||||
if (i >= 4)
|
if (i >= 4)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
if (0 == INPUT(i).type)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
mutex_lock(&core->lock);
|
mutex_lock(&core->lock);
|
||||||
cx88_newstation(core);
|
cx88_newstation(core);
|
||||||
|
@ -1010,9 +906,9 @@ static int vidioc_g_tuner (struct file *file, void *priv,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
strcpy(t->name, "Television");
|
strcpy(t->name, "Television");
|
||||||
t->type = V4L2_TUNER_ANALOG_TV;
|
|
||||||
t->capability = V4L2_TUNER_CAP_NORM;
|
t->capability = V4L2_TUNER_CAP_NORM;
|
||||||
t->rangehigh = 0xffffffffUL;
|
t->rangehigh = 0xffffffffUL;
|
||||||
|
call_all(core, tuner, g_tuner, t);
|
||||||
|
|
||||||
cx88_get_stereo(core ,t);
|
cx88_get_stereo(core ,t);
|
||||||
reg = cx_read(MO_DEVICE_STATUS);
|
reg = cx_read(MO_DEVICE_STATUS);
|
||||||
|
@ -1034,6 +930,14 @@ static int vidioc_s_tuner (struct file *file, void *priv,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm)
|
||||||
|
{
|
||||||
|
struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
|
||||||
|
|
||||||
|
*tvnorm = core->tvnorm;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id)
|
static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id)
|
||||||
{
|
{
|
||||||
struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
|
struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
|
||||||
|
@ -1087,6 +991,7 @@ static int mpeg_open(struct file *file)
|
||||||
mutex_unlock(&dev->core->lock);
|
mutex_unlock(&dev->core->lock);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
v4l2_fh_init(&fh->fh, vdev);
|
||||||
file->private_data = fh;
|
file->private_data = fh;
|
||||||
fh->dev = dev;
|
fh->dev = dev;
|
||||||
|
|
||||||
|
@ -1103,6 +1008,7 @@ static int mpeg_open(struct file *file)
|
||||||
|
|
||||||
dev->core->mpeg_users++;
|
dev->core->mpeg_users++;
|
||||||
mutex_unlock(&dev->core->lock);
|
mutex_unlock(&dev->core->lock);
|
||||||
|
v4l2_fh_add(&fh->fh);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1123,6 +1029,8 @@ static int mpeg_release(struct file *file)
|
||||||
|
|
||||||
videobuf_mmap_free(&fh->mpegq);
|
videobuf_mmap_free(&fh->mpegq);
|
||||||
|
|
||||||
|
v4l2_fh_del(&fh->fh);
|
||||||
|
v4l2_fh_exit(&fh->fh);
|
||||||
file->private_data = NULL;
|
file->private_data = NULL;
|
||||||
kfree(fh);
|
kfree(fh);
|
||||||
|
|
||||||
|
@ -1155,13 +1063,14 @@ mpeg_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
|
||||||
static unsigned int
|
static unsigned int
|
||||||
mpeg_poll(struct file *file, struct poll_table_struct *wait)
|
mpeg_poll(struct file *file, struct poll_table_struct *wait)
|
||||||
{
|
{
|
||||||
|
unsigned long req_events = poll_requested_events(wait);
|
||||||
struct cx8802_fh *fh = file->private_data;
|
struct cx8802_fh *fh = file->private_data;
|
||||||
struct cx8802_dev *dev = fh->dev;
|
struct cx8802_dev *dev = fh->dev;
|
||||||
|
|
||||||
if (!dev->mpeg_active)
|
if (!dev->mpeg_active && (req_events & (POLLIN | POLLRDNORM)))
|
||||||
blackbird_start_codec(file, fh);
|
blackbird_start_codec(file, fh);
|
||||||
|
|
||||||
return videobuf_poll_stream(file, &fh->mpegq, wait);
|
return v4l2_ctrl_poll(file, wait) | videobuf_poll_stream(file, &fh->mpegq, wait);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -1180,11 +1089,10 @@ static const struct v4l2_file_operations mpeg_fops =
|
||||||
.read = mpeg_read,
|
.read = mpeg_read,
|
||||||
.poll = mpeg_poll,
|
.poll = mpeg_poll,
|
||||||
.mmap = mpeg_mmap,
|
.mmap = mpeg_mmap,
|
||||||
.ioctl = video_ioctl2,
|
.unlocked_ioctl = video_ioctl2,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
|
static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
|
||||||
.vidioc_querymenu = vidioc_querymenu,
|
|
||||||
.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,
|
||||||
.vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
|
.vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
|
||||||
|
@ -1196,21 +1104,18 @@ static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
|
||||||
.vidioc_dqbuf = vidioc_dqbuf,
|
.vidioc_dqbuf = vidioc_dqbuf,
|
||||||
.vidioc_streamon = vidioc_streamon,
|
.vidioc_streamon = vidioc_streamon,
|
||||||
.vidioc_streamoff = vidioc_streamoff,
|
.vidioc_streamoff = vidioc_streamoff,
|
||||||
.vidioc_g_ext_ctrls = vidioc_g_ext_ctrls,
|
|
||||||
.vidioc_s_ext_ctrls = vidioc_s_ext_ctrls,
|
|
||||||
.vidioc_try_ext_ctrls = vidioc_try_ext_ctrls,
|
|
||||||
.vidioc_s_frequency = vidioc_s_frequency,
|
.vidioc_s_frequency = vidioc_s_frequency,
|
||||||
.vidioc_log_status = vidioc_log_status,
|
.vidioc_log_status = vidioc_log_status,
|
||||||
.vidioc_queryctrl = vidioc_queryctrl,
|
|
||||||
.vidioc_enum_input = vidioc_enum_input,
|
.vidioc_enum_input = vidioc_enum_input,
|
||||||
.vidioc_g_ctrl = vidioc_g_ctrl,
|
|
||||||
.vidioc_s_ctrl = vidioc_s_ctrl,
|
|
||||||
.vidioc_g_frequency = vidioc_g_frequency,
|
.vidioc_g_frequency = vidioc_g_frequency,
|
||||||
.vidioc_g_input = vidioc_g_input,
|
.vidioc_g_input = vidioc_g_input,
|
||||||
.vidioc_s_input = vidioc_s_input,
|
.vidioc_s_input = vidioc_s_input,
|
||||||
.vidioc_g_tuner = vidioc_g_tuner,
|
.vidioc_g_tuner = vidioc_g_tuner,
|
||||||
.vidioc_s_tuner = vidioc_s_tuner,
|
.vidioc_s_tuner = vidioc_s_tuner,
|
||||||
|
.vidioc_g_std = vidioc_g_std,
|
||||||
.vidioc_s_std = vidioc_s_std,
|
.vidioc_s_std = vidioc_s_std,
|
||||||
|
.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
|
||||||
|
.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct video_device cx8802_mpeg_template = {
|
static struct video_device cx8802_mpeg_template = {
|
||||||
|
@ -1218,7 +1123,6 @@ static struct video_device cx8802_mpeg_template = {
|
||||||
.fops = &mpeg_fops,
|
.fops = &mpeg_fops,
|
||||||
.ioctl_ops = &mpeg_ioctl_ops,
|
.ioctl_ops = &mpeg_ioctl_ops,
|
||||||
.tvnorms = CX88_NORMS,
|
.tvnorms = CX88_NORMS,
|
||||||
.current_norm = V4L2_STD_NTSC_M,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
|
@ -1286,6 +1190,7 @@ static int blackbird_register_video(struct cx8802_dev *dev)
|
||||||
|
|
||||||
dev->mpeg_dev = cx88_vdev_init(dev->core,dev->pci,
|
dev->mpeg_dev = cx88_vdev_init(dev->core,dev->pci,
|
||||||
&cx8802_mpeg_template,"mpeg");
|
&cx8802_mpeg_template,"mpeg");
|
||||||
|
dev->mpeg_dev->ctrl_handler = &dev->cxhdl.hdl;
|
||||||
video_set_drvdata(dev->mpeg_dev, dev);
|
video_set_drvdata(dev->mpeg_dev, dev);
|
||||||
err = video_register_device(dev->mpeg_dev,VFL_TYPE_GRABBER, -1);
|
err = video_register_device(dev->mpeg_dev,VFL_TYPE_GRABBER, -1);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
|
@ -1318,17 +1223,20 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv)
|
||||||
goto fail_core;
|
goto fail_core;
|
||||||
|
|
||||||
dev->width = 720;
|
dev->width = 720;
|
||||||
dev->height = 576;
|
|
||||||
cx2341x_fill_defaults(&dev->params);
|
|
||||||
dev->params.port = CX2341X_PORT_STREAMING;
|
|
||||||
|
|
||||||
cx8802_mpeg_template.current_norm = core->tvnorm;
|
|
||||||
|
|
||||||
if (core->tvnorm & V4L2_STD_525_60) {
|
if (core->tvnorm & V4L2_STD_525_60) {
|
||||||
dev->height = 480;
|
dev->height = 480;
|
||||||
} else {
|
} else {
|
||||||
dev->height = 576;
|
dev->height = 576;
|
||||||
}
|
}
|
||||||
|
dev->cxhdl.port = CX2341X_PORT_STREAMING;
|
||||||
|
dev->cxhdl.width = dev->width;
|
||||||
|
dev->cxhdl.height = dev->height;
|
||||||
|
dev->cxhdl.func = blackbird_mbox_func;
|
||||||
|
dev->cxhdl.priv = dev;
|
||||||
|
err = cx2341x_handler_init(&dev->cxhdl, 36);
|
||||||
|
if (err)
|
||||||
|
goto fail_core;
|
||||||
|
v4l2_ctrl_add_handler(&dev->cxhdl.hdl, &core->video_hdl);
|
||||||
|
|
||||||
/* blackbird stuff */
|
/* blackbird stuff */
|
||||||
printk("%s/2: cx23416 based mpeg encoder (blackbird reference design)\n",
|
printk("%s/2: cx23416 based mpeg encoder (blackbird reference design)\n",
|
||||||
|
@ -1336,12 +1244,14 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv)
|
||||||
host_setup(dev->core);
|
host_setup(dev->core);
|
||||||
|
|
||||||
blackbird_initialize_codec(dev);
|
blackbird_initialize_codec(dev);
|
||||||
blackbird_register_video(dev);
|
|
||||||
|
|
||||||
/* initial device configuration: needed ? */
|
/* initial device configuration: needed ? */
|
||||||
// init_controls(core);
|
// init_controls(core);
|
||||||
cx88_set_tvnorm(core,core->tvnorm);
|
cx88_set_tvnorm(core,core->tvnorm);
|
||||||
cx88_video_mux(core,0);
|
cx88_video_mux(core,0);
|
||||||
|
cx2341x_handler_set_50hz(&dev->cxhdl, dev->height == 576);
|
||||||
|
cx2341x_handler_setup(&dev->cxhdl);
|
||||||
|
blackbird_register_video(dev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -1351,8 +1261,12 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv)
|
||||||
|
|
||||||
static int cx8802_blackbird_remove(struct cx8802_driver *drv)
|
static int cx8802_blackbird_remove(struct cx8802_driver *drv)
|
||||||
{
|
{
|
||||||
|
struct cx88_core *core = drv->core;
|
||||||
|
struct cx8802_dev *dev = core->dvbdev;
|
||||||
|
|
||||||
/* blackbird */
|
/* blackbird */
|
||||||
blackbird_unregister_video(drv->core->dvbdev);
|
blackbird_unregister_video(drv->core->dvbdev);
|
||||||
|
v4l2_ctrl_handler_free(&dev->cxhdl.hdl);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3693,7 +3693,22 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (v4l2_ctrl_handler_init(&core->video_hdl, 13)) {
|
||||||
|
v4l2_device_unregister(&core->v4l2_dev);
|
||||||
|
kfree(core);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v4l2_ctrl_handler_init(&core->audio_hdl, 13)) {
|
||||||
|
v4l2_ctrl_handler_free(&core->video_hdl);
|
||||||
|
v4l2_device_unregister(&core->v4l2_dev);
|
||||||
|
kfree(core);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (0 != cx88_get_resources(core, pci)) {
|
if (0 != cx88_get_resources(core, pci)) {
|
||||||
|
v4l2_ctrl_handler_free(&core->video_hdl);
|
||||||
|
v4l2_ctrl_handler_free(&core->audio_hdl);
|
||||||
v4l2_device_unregister(&core->v4l2_dev);
|
v4l2_device_unregister(&core->v4l2_dev);
|
||||||
kfree(core);
|
kfree(core);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -3706,6 +3721,11 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
|
||||||
core->bmmio = (u8 __iomem *)core->lmmio;
|
core->bmmio = (u8 __iomem *)core->lmmio;
|
||||||
|
|
||||||
if (core->lmmio == NULL) {
|
if (core->lmmio == NULL) {
|
||||||
|
release_mem_region(pci_resource_start(pci, 0),
|
||||||
|
pci_resource_len(pci, 0));
|
||||||
|
v4l2_ctrl_handler_free(&core->video_hdl);
|
||||||
|
v4l2_ctrl_handler_free(&core->audio_hdl);
|
||||||
|
v4l2_device_unregister(&core->v4l2_dev);
|
||||||
kfree(core);
|
kfree(core);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1012,6 +1012,9 @@ int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm)
|
||||||
// tell i2c chips
|
// tell i2c chips
|
||||||
call_all(core, core, s_std, norm);
|
call_all(core, core, s_std, norm);
|
||||||
|
|
||||||
|
/* The chroma_agc control should be inaccessible if the video format is SECAM */
|
||||||
|
v4l2_ctrl_grab(core->chroma_agc, cxiformat == VideoFormatSECAM);
|
||||||
|
|
||||||
// done
|
// done
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1030,10 +1033,10 @@ struct video_device *cx88_vdev_init(struct cx88_core *core,
|
||||||
return NULL;
|
return NULL;
|
||||||
*vfd = *template_;
|
*vfd = *template_;
|
||||||
vfd->v4l2_dev = &core->v4l2_dev;
|
vfd->v4l2_dev = &core->v4l2_dev;
|
||||||
vfd->parent = &pci->dev;
|
|
||||||
vfd->release = video_device_release;
|
vfd->release = video_device_release;
|
||||||
snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
|
snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
|
||||||
core->name, type, core->board.name);
|
core->name, type, core->board.name);
|
||||||
|
set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
|
||||||
return vfd;
|
return vfd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1086,6 +1089,8 @@ void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
|
||||||
iounmap(core->lmmio);
|
iounmap(core->lmmio);
|
||||||
cx88_devcount--;
|
cx88_devcount--;
|
||||||
mutex_unlock(&devlist);
|
mutex_unlock(&devlist);
|
||||||
|
v4l2_ctrl_handler_free(&core->video_hdl);
|
||||||
|
v4l2_ctrl_handler_free(&core->audio_hdl);
|
||||||
v4l2_device_unregister(&core->v4l2_dev);
|
v4l2_device_unregister(&core->v4l2_dev);
|
||||||
kfree(core);
|
kfree(core);
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -26,6 +26,7 @@
|
||||||
#include <linux/kdev_t.h>
|
#include <linux/kdev_t.h>
|
||||||
|
|
||||||
#include <media/v4l2-device.h>
|
#include <media/v4l2-device.h>
|
||||||
|
#include <media/v4l2-fh.h>
|
||||||
#include <media/tuner.h>
|
#include <media/tuner.h>
|
||||||
#include <media/tveeprom.h>
|
#include <media/tveeprom.h>
|
||||||
#include <media/videobuf-dma-sg.h>
|
#include <media/videobuf-dma-sg.h>
|
||||||
|
@ -115,15 +116,6 @@ struct cx8800_fmt {
|
||||||
u32 cxformat;
|
u32 cxformat;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cx88_ctrl {
|
|
||||||
struct v4l2_queryctrl v;
|
|
||||||
u32 off;
|
|
||||||
u32 reg;
|
|
||||||
u32 sreg;
|
|
||||||
u32 mask;
|
|
||||||
u32 shift;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------- */
|
/* ----------------------------------------------------------- */
|
||||||
/* SRAM memory management data (see cx88-core.c) */
|
/* SRAM memory management data (see cx88-core.c) */
|
||||||
|
|
||||||
|
@ -359,6 +351,10 @@ struct cx88_core {
|
||||||
|
|
||||||
/* config info -- analog */
|
/* config info -- analog */
|
||||||
struct v4l2_device v4l2_dev;
|
struct v4l2_device v4l2_dev;
|
||||||
|
struct v4l2_ctrl_handler video_hdl;
|
||||||
|
struct v4l2_ctrl *chroma_agc;
|
||||||
|
struct v4l2_ctrl_handler audio_hdl;
|
||||||
|
struct v4l2_subdev *sd_wm8775;
|
||||||
struct i2c_client *i2c_rtc;
|
struct i2c_client *i2c_rtc;
|
||||||
unsigned int boardnr;
|
unsigned int boardnr;
|
||||||
struct cx88_board board;
|
struct cx88_board board;
|
||||||
|
@ -409,8 +405,6 @@ static inline struct cx88_core *to_core(struct v4l2_device *v4l2_dev)
|
||||||
return container_of(v4l2_dev, struct cx88_core, v4l2_dev);
|
return container_of(v4l2_dev, struct cx88_core, v4l2_dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define WM8775_GID (1 << 0)
|
|
||||||
|
|
||||||
#define call_hw(core, grpid, o, f, args...) \
|
#define call_hw(core, grpid, o, f, args...) \
|
||||||
do { \
|
do { \
|
||||||
if (!core->i2c_rc) { \
|
if (!core->i2c_rc) { \
|
||||||
|
@ -424,6 +418,36 @@ static inline struct cx88_core *to_core(struct v4l2_device *v4l2_dev)
|
||||||
|
|
||||||
#define call_all(core, o, f, args...) call_hw(core, 0, o, f, ##args)
|
#define call_all(core, o, f, args...) call_hw(core, 0, o, f, ##args)
|
||||||
|
|
||||||
|
#define WM8775_GID (1 << 0)
|
||||||
|
|
||||||
|
#define wm8775_s_ctrl(core, id, val) \
|
||||||
|
do { \
|
||||||
|
struct v4l2_ctrl *ctrl_ = \
|
||||||
|
v4l2_ctrl_find(core->sd_wm8775->ctrl_handler, id); \
|
||||||
|
if (ctrl_ && !core->i2c_rc) { \
|
||||||
|
if (core->gate_ctrl) \
|
||||||
|
core->gate_ctrl(core, 1); \
|
||||||
|
v4l2_ctrl_s_ctrl(ctrl_, val); \
|
||||||
|
if (core->gate_ctrl) \
|
||||||
|
core->gate_ctrl(core, 0); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define wm8775_g_ctrl(core, id) \
|
||||||
|
({ \
|
||||||
|
struct v4l2_ctrl *ctrl_ = \
|
||||||
|
v4l2_ctrl_find(core->sd_wm8775->ctrl_handler, id); \
|
||||||
|
s32 val = 0; \
|
||||||
|
if (ctrl_ && !core->i2c_rc) { \
|
||||||
|
if (core->gate_ctrl) \
|
||||||
|
core->gate_ctrl(core, 1); \
|
||||||
|
val = v4l2_ctrl_g_ctrl(ctrl_); \
|
||||||
|
if (core->gate_ctrl) \
|
||||||
|
core->gate_ctrl(core, 0); \
|
||||||
|
} \
|
||||||
|
val; \
|
||||||
|
})
|
||||||
|
|
||||||
struct cx8800_dev;
|
struct cx8800_dev;
|
||||||
struct cx8802_dev;
|
struct cx8802_dev;
|
||||||
|
|
||||||
|
@ -431,19 +455,11 @@ struct cx8802_dev;
|
||||||
/* function 0: video stuff */
|
/* function 0: video stuff */
|
||||||
|
|
||||||
struct cx8800_fh {
|
struct cx8800_fh {
|
||||||
|
struct v4l2_fh fh;
|
||||||
struct cx8800_dev *dev;
|
struct cx8800_dev *dev;
|
||||||
enum v4l2_buf_type type;
|
|
||||||
int radio;
|
|
||||||
unsigned int resources;
|
unsigned int resources;
|
||||||
|
|
||||||
/* video overlay */
|
|
||||||
struct v4l2_window win;
|
|
||||||
struct v4l2_clip *clips;
|
|
||||||
unsigned int nclips;
|
|
||||||
|
|
||||||
/* video capture */
|
/* video capture */
|
||||||
const struct cx8800_fmt *fmt;
|
|
||||||
unsigned int width,height;
|
|
||||||
struct videobuf_queue vidq;
|
struct videobuf_queue vidq;
|
||||||
|
|
||||||
/* vbi capture */
|
/* vbi capture */
|
||||||
|
@ -468,6 +484,8 @@ struct cx8800_dev {
|
||||||
struct pci_dev *pci;
|
struct pci_dev *pci;
|
||||||
unsigned char pci_rev,pci_lat;
|
unsigned char pci_rev,pci_lat;
|
||||||
|
|
||||||
|
const struct cx8800_fmt *fmt;
|
||||||
|
unsigned int width, height;
|
||||||
|
|
||||||
/* capture queues */
|
/* capture queues */
|
||||||
struct cx88_dmaqueue vidq;
|
struct cx88_dmaqueue vidq;
|
||||||
|
@ -488,6 +506,7 @@ struct cx8800_dev {
|
||||||
/* function 2: mpeg stuff */
|
/* function 2: mpeg stuff */
|
||||||
|
|
||||||
struct cx8802_fh {
|
struct cx8802_fh {
|
||||||
|
struct v4l2_fh fh;
|
||||||
struct cx8802_dev *dev;
|
struct cx8802_dev *dev;
|
||||||
struct videobuf_queue mpegq;
|
struct videobuf_queue mpegq;
|
||||||
};
|
};
|
||||||
|
@ -552,7 +571,7 @@ struct cx8802_dev {
|
||||||
unsigned char mpeg_active; /* nonzero if mpeg encoder is active */
|
unsigned char mpeg_active; /* nonzero if mpeg encoder is active */
|
||||||
|
|
||||||
/* mpeg params */
|
/* mpeg params */
|
||||||
struct cx2341x_mpeg_params params;
|
struct cx2341x_handler cxhdl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)
|
#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)
|
||||||
|
@ -722,11 +741,8 @@ void cx8802_cancel_buffers(struct cx8802_dev *dev);
|
||||||
|
|
||||||
/* ----------------------------------------------------------- */
|
/* ----------------------------------------------------------- */
|
||||||
/* cx88-video.c*/
|
/* cx88-video.c*/
|
||||||
extern const u32 cx88_user_ctrls[];
|
|
||||||
extern int cx8800_ctrl_query(struct cx88_core *core,
|
|
||||||
struct v4l2_queryctrl *qctrl);
|
|
||||||
int cx88_enum_input (struct cx88_core *core,struct v4l2_input *i);
|
int cx88_enum_input (struct cx88_core *core,struct v4l2_input *i);
|
||||||
int cx88_set_freq (struct cx88_core *core,struct v4l2_frequency *f);
|
int cx88_set_freq (struct cx88_core *core,struct v4l2_frequency *f);
|
||||||
int cx88_get_control(struct cx88_core *core, struct v4l2_control *ctl);
|
|
||||||
int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl);
|
|
||||||
int cx88_video_mux(struct cx88_core *core, unsigned int input);
|
int cx88_video_mux(struct cx88_core *core, unsigned int input);
|
||||||
|
void cx88_querycap(struct file *file, struct cx88_core *core,
|
||||||
|
struct v4l2_capability *cap);
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#include <sound/initval.h>
|
#include <sound/initval.h>
|
||||||
#include <sound/control.h>
|
#include <sound/control.h>
|
||||||
#include <sound/tlv.h>
|
#include <sound/tlv.h>
|
||||||
|
#include <sound/ac97_codec.h>
|
||||||
#include <media/v4l2-common.h>
|
#include <media/v4l2-common.h>
|
||||||
#include "em28xx.h"
|
#include "em28xx.h"
|
||||||
|
|
||||||
|
@ -679,19 +680,19 @@ static int em28xx_audio_init(struct em28xx *dev)
|
||||||
INIT_WORK(&dev->wq_trigger, audio_trigger);
|
INIT_WORK(&dev->wq_trigger, audio_trigger);
|
||||||
|
|
||||||
if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
|
if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
|
||||||
em28xx_cvol_new(card, dev, "Video", AC97_VIDEO_VOL);
|
em28xx_cvol_new(card, dev, "Video", AC97_VIDEO);
|
||||||
em28xx_cvol_new(card, dev, "Line In", AC97_LINEIN_VOL);
|
em28xx_cvol_new(card, dev, "Line In", AC97_LINE);
|
||||||
em28xx_cvol_new(card, dev, "Phone", AC97_PHONE_VOL);
|
em28xx_cvol_new(card, dev, "Phone", AC97_PHONE);
|
||||||
em28xx_cvol_new(card, dev, "Microphone", AC97_PHONE_VOL);
|
em28xx_cvol_new(card, dev, "Microphone", AC97_MIC);
|
||||||
em28xx_cvol_new(card, dev, "CD", AC97_CD_VOL);
|
em28xx_cvol_new(card, dev, "CD", AC97_CD);
|
||||||
em28xx_cvol_new(card, dev, "AUX", AC97_AUX_VOL);
|
em28xx_cvol_new(card, dev, "AUX", AC97_AUX);
|
||||||
em28xx_cvol_new(card, dev, "PCM", AC97_PCM_OUT_VOL);
|
em28xx_cvol_new(card, dev, "PCM", AC97_PCM);
|
||||||
|
|
||||||
em28xx_cvol_new(card, dev, "Master", AC97_MASTER_VOL);
|
em28xx_cvol_new(card, dev, "Master", AC97_MASTER);
|
||||||
em28xx_cvol_new(card, dev, "Line", AC97_LINE_LEVEL_VOL);
|
em28xx_cvol_new(card, dev, "Line", AC97_HEADPHONE);
|
||||||
em28xx_cvol_new(card, dev, "Mono", AC97_MASTER_MONO_VOL);
|
em28xx_cvol_new(card, dev, "Mono", AC97_MASTER_MONO);
|
||||||
em28xx_cvol_new(card, dev, "LFE", AC97_LFE_MASTER_VOL);
|
em28xx_cvol_new(card, dev, "LFE", AC97_CENTER_LFE_MASTER);
|
||||||
em28xx_cvol_new(card, dev, "Surround", AC97_SURR_MASTER_VOL);
|
em28xx_cvol_new(card, dev, "Surround", AC97_SURROUND_MASTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
err = snd_card_register(card);
|
err = snd_card_register(card);
|
||||||
|
|
|
@ -975,12 +975,7 @@ struct em28xx_board em28xx_boards[] = {
|
||||||
.name = "Terratec Cinergy HTC Stick",
|
.name = "Terratec Cinergy HTC Stick",
|
||||||
.has_dvb = 1,
|
.has_dvb = 1,
|
||||||
.ir_codes = RC_MAP_NEC_TERRATEC_CINERGY_XS,
|
.ir_codes = RC_MAP_NEC_TERRATEC_CINERGY_XS,
|
||||||
#if 0
|
.tuner_type = TUNER_ABSENT,
|
||||||
.tuner_type = TUNER_PHILIPS_TDA8290,
|
|
||||||
.tuner_addr = 0x41,
|
|
||||||
.dvb_gpio = terratec_h5_digital, /* FIXME: probably wrong */
|
|
||||||
.tuner_gpio = terratec_h5_gpio,
|
|
||||||
#endif
|
|
||||||
.i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT |
|
.i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT |
|
||||||
EM28XX_I2C_CLK_WAIT_ENABLE |
|
EM28XX_I2C_CLK_WAIT_ENABLE |
|
||||||
EM28XX_I2C_FREQ_400_KHZ,
|
EM28XX_I2C_FREQ_400_KHZ,
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/usb.h>
|
#include <linux/usb.h>
|
||||||
#include <linux/vmalloc.h>
|
#include <linux/vmalloc.h>
|
||||||
|
#include <sound/ac97_codec.h>
|
||||||
#include <media/v4l2-common.h>
|
#include <media/v4l2-common.h>
|
||||||
|
|
||||||
#include "em28xx.h"
|
#include "em28xx.h"
|
||||||
|
@ -326,13 +327,13 @@ struct em28xx_vol_itable {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct em28xx_vol_itable inputs[] = {
|
static struct em28xx_vol_itable inputs[] = {
|
||||||
{ EM28XX_AMUX_VIDEO, AC97_VIDEO_VOL },
|
{ EM28XX_AMUX_VIDEO, AC97_VIDEO },
|
||||||
{ EM28XX_AMUX_LINE_IN, AC97_LINEIN_VOL },
|
{ EM28XX_AMUX_LINE_IN, AC97_LINE },
|
||||||
{ EM28XX_AMUX_PHONE, AC97_PHONE_VOL },
|
{ EM28XX_AMUX_PHONE, AC97_PHONE },
|
||||||
{ EM28XX_AMUX_MIC, AC97_MIC_VOL },
|
{ EM28XX_AMUX_MIC, AC97_MIC },
|
||||||
{ EM28XX_AMUX_CD, AC97_CD_VOL },
|
{ EM28XX_AMUX_CD, AC97_CD },
|
||||||
{ EM28XX_AMUX_AUX, AC97_AUX_VOL },
|
{ EM28XX_AMUX_AUX, AC97_AUX },
|
||||||
{ EM28XX_AMUX_PCM_OUT, AC97_PCM_OUT_VOL },
|
{ EM28XX_AMUX_PCM_OUT, AC97_PCM },
|
||||||
};
|
};
|
||||||
|
|
||||||
static int set_ac97_input(struct em28xx *dev)
|
static int set_ac97_input(struct em28xx *dev)
|
||||||
|
@ -415,11 +416,11 @@ struct em28xx_vol_otable {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct em28xx_vol_otable outputs[] = {
|
static const struct em28xx_vol_otable outputs[] = {
|
||||||
{ EM28XX_AOUT_MASTER, AC97_MASTER_VOL },
|
{ EM28XX_AOUT_MASTER, AC97_MASTER },
|
||||||
{ EM28XX_AOUT_LINE, AC97_LINE_LEVEL_VOL },
|
{ EM28XX_AOUT_LINE, AC97_HEADPHONE },
|
||||||
{ EM28XX_AOUT_MONO, AC97_MASTER_MONO_VOL },
|
{ EM28XX_AOUT_MONO, AC97_MASTER_MONO },
|
||||||
{ EM28XX_AOUT_LFE, AC97_LFE_MASTER_VOL },
|
{ EM28XX_AOUT_LFE, AC97_CENTER_LFE_MASTER },
|
||||||
{ EM28XX_AOUT_SURR, AC97_SURR_MASTER_VOL },
|
{ EM28XX_AOUT_SURR, AC97_SURROUND_MASTER },
|
||||||
};
|
};
|
||||||
|
|
||||||
int em28xx_audio_analog_set(struct em28xx *dev)
|
int em28xx_audio_analog_set(struct em28xx *dev)
|
||||||
|
@ -459,9 +460,9 @@ int em28xx_audio_analog_set(struct em28xx *dev)
|
||||||
if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
|
if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
|
||||||
int vol;
|
int vol;
|
||||||
|
|
||||||
em28xx_write_ac97(dev, AC97_POWER_DOWN_CTRL, 0x4200);
|
em28xx_write_ac97(dev, AC97_POWERDOWN, 0x4200);
|
||||||
em28xx_write_ac97(dev, AC97_EXT_AUD_CTRL, 0x0031);
|
em28xx_write_ac97(dev, AC97_EXTENDED_STATUS, 0x0031);
|
||||||
em28xx_write_ac97(dev, AC97_PCM_IN_SRATE, 0xbb80);
|
em28xx_write_ac97(dev, AC97_PCM_LR_ADC_RATE, 0xbb80);
|
||||||
|
|
||||||
/* LSB: left channel - both channels with the same level */
|
/* LSB: left channel - both channels with the same level */
|
||||||
vol = (0x1f - dev->volume) | ((0x1f - dev->volume) << 8);
|
vol = (0x1f - dev->volume) | ((0x1f - dev->volume) << 8);
|
||||||
|
@ -487,7 +488,7 @@ int em28xx_audio_analog_set(struct em28xx *dev)
|
||||||
channels */
|
channels */
|
||||||
sel |= (sel << 8);
|
sel |= (sel << 8);
|
||||||
|
|
||||||
em28xx_write_ac97(dev, AC97_RECORD_SELECT, sel);
|
em28xx_write_ac97(dev, AC97_REC_SEL, sel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -310,31 +310,47 @@ static struct drxd_config em28xx_drxd = {
|
||||||
.disable_i2c_gate_ctrl = 1,
|
.disable_i2c_gate_ctrl = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct drxk_config terratec_h5_drxk = {
|
static struct drxk_config terratec_h5_drxk = {
|
||||||
.adr = 0x29,
|
.adr = 0x29,
|
||||||
.single_master = 1,
|
.single_master = 1,
|
||||||
.no_i2c_bridge = 1,
|
.no_i2c_bridge = 1,
|
||||||
.microcode_name = "dvb-usb-terratec-h5-drxk.fw",
|
.microcode_name = "dvb-usb-terratec-h5-drxk.fw",
|
||||||
|
.qam_demod_parameter_count = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct drxk_config hauppauge_930c_drxk = {
|
static struct drxk_config hauppauge_930c_drxk = {
|
||||||
.adr = 0x29,
|
.adr = 0x29,
|
||||||
.single_master = 1,
|
.single_master = 1,
|
||||||
.no_i2c_bridge = 1,
|
.no_i2c_bridge = 1,
|
||||||
.microcode_name = "dvb-usb-hauppauge-hvr930c-drxk.fw",
|
.microcode_name = "dvb-usb-hauppauge-hvr930c-drxk.fw",
|
||||||
.chunk_size = 56,
|
.chunk_size = 56,
|
||||||
|
.qam_demod_parameter_count = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct drxk_config maxmedia_ub425_tc_drxk = {
|
struct drxk_config terratec_htc_stick_drxk = {
|
||||||
|
.adr = 0x29,
|
||||||
|
.single_master = 1,
|
||||||
|
.no_i2c_bridge = 1,
|
||||||
|
.microcode_name = "dvb-usb-terratec-htc-stick-drxk.fw",
|
||||||
|
.chunk_size = 54,
|
||||||
|
.qam_demod_parameter_count = 2,
|
||||||
|
/* Required for the antenna_gpio to disable LNA. */
|
||||||
|
.antenna_dvbt = true,
|
||||||
|
/* The windows driver uses the same. This will disable LNA. */
|
||||||
|
.antenna_gpio = 0x6,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct drxk_config maxmedia_ub425_tc_drxk = {
|
||||||
.adr = 0x29,
|
.adr = 0x29,
|
||||||
.single_master = 1,
|
.single_master = 1,
|
||||||
.no_i2c_bridge = 1,
|
.no_i2c_bridge = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct drxk_config pctv_520e_drxk = {
|
static struct drxk_config pctv_520e_drxk = {
|
||||||
.adr = 0x29,
|
.adr = 0x29,
|
||||||
.single_master = 1,
|
.single_master = 1,
|
||||||
.microcode_name = "dvb-demod-drxk-pctv.fw",
|
.microcode_name = "dvb-demod-drxk-pctv.fw",
|
||||||
|
.qam_demod_parameter_count = 2,
|
||||||
.chunk_size = 58,
|
.chunk_size = 58,
|
||||||
.antenna_dvbt = true, /* disable LNA */
|
.antenna_dvbt = true, /* disable LNA */
|
||||||
.antenna_gpio = (1 << 2), /* disable LNA */
|
.antenna_gpio = (1 << 2), /* disable LNA */
|
||||||
|
@ -473,6 +489,57 @@ static void terratec_h5_init(struct em28xx *dev)
|
||||||
em28xx_gpio_set(dev, terratec_h5_end);
|
em28xx_gpio_set(dev, terratec_h5_end);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void terratec_htc_stick_init(struct em28xx *dev)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GPIO configuration:
|
||||||
|
* 0xff: unknown (does not affect DVB-T).
|
||||||
|
* 0xf6: DRX-K (demodulator).
|
||||||
|
* 0xe6: unknown (does not affect DVB-T).
|
||||||
|
* 0xb6: unknown (does not affect DVB-T).
|
||||||
|
*/
|
||||||
|
struct em28xx_reg_seq terratec_htc_stick_init[] = {
|
||||||
|
{EM28XX_R08_GPIO, 0xff, 0xff, 10},
|
||||||
|
{EM2874_R80_GPIO, 0xf6, 0xff, 100},
|
||||||
|
{EM2874_R80_GPIO, 0xe6, 0xff, 50},
|
||||||
|
{EM2874_R80_GPIO, 0xf6, 0xff, 100},
|
||||||
|
{ -1, -1, -1, -1},
|
||||||
|
};
|
||||||
|
struct em28xx_reg_seq terratec_htc_stick_end[] = {
|
||||||
|
{EM2874_R80_GPIO, 0xb6, 0xff, 100},
|
||||||
|
{EM2874_R80_GPIO, 0xf6, 0xff, 50},
|
||||||
|
{ -1, -1, -1, -1},
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Init the analog decoder? */
|
||||||
|
struct {
|
||||||
|
unsigned char r[4];
|
||||||
|
int len;
|
||||||
|
} regs[] = {
|
||||||
|
{{ 0x06, 0x02, 0x00, 0x31 }, 4},
|
||||||
|
{{ 0x01, 0x02 }, 2},
|
||||||
|
{{ 0x01, 0x02, 0x00, 0xc6 }, 4},
|
||||||
|
{{ 0x01, 0x00 }, 2},
|
||||||
|
{{ 0x01, 0x00, 0xff, 0xaf }, 4},
|
||||||
|
};
|
||||||
|
|
||||||
|
em28xx_gpio_set(dev, terratec_htc_stick_init);
|
||||||
|
|
||||||
|
em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40);
|
||||||
|
msleep(10);
|
||||||
|
em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44);
|
||||||
|
msleep(10);
|
||||||
|
|
||||||
|
dev->i2c_client.addr = 0x82 >> 1;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(regs); i++)
|
||||||
|
i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len);
|
||||||
|
|
||||||
|
em28xx_gpio_set(dev, terratec_htc_stick_end);
|
||||||
|
};
|
||||||
|
|
||||||
static void pctv_520e_init(struct em28xx *dev)
|
static void pctv_520e_init(struct em28xx *dev)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -944,7 +1011,6 @@ static int em28xx_dvb_init(struct em28xx *dev)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case EM2884_BOARD_TERRATEC_H5:
|
case EM2884_BOARD_TERRATEC_H5:
|
||||||
case EM2884_BOARD_CINERGY_HTC_STICK:
|
|
||||||
terratec_h5_init(dev);
|
terratec_h5_init(dev);
|
||||||
|
|
||||||
dvb->fe[0] = dvb_attach(drxk_attach, &terratec_h5_drxk, &dev->i2c_adap);
|
dvb->fe[0] = dvb_attach(drxk_attach, &terratec_h5_drxk, &dev->i2c_adap);
|
||||||
|
@ -1021,6 +1087,25 @@ static int em28xx_dvb_init(struct em28xx *dev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case EM2884_BOARD_CINERGY_HTC_STICK:
|
||||||
|
terratec_htc_stick_init(dev);
|
||||||
|
|
||||||
|
/* attach demodulator */
|
||||||
|
dvb->fe[0] = dvb_attach(drxk_attach, &terratec_htc_stick_drxk,
|
||||||
|
&dev->i2c_adap);
|
||||||
|
if (!dvb->fe[0]) {
|
||||||
|
result = -EINVAL;
|
||||||
|
goto out_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Attach the demodulator. */
|
||||||
|
if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
|
||||||
|
&dev->i2c_adap,
|
||||||
|
&em28xx_cxd2820r_tda18271_config)) {
|
||||||
|
result = -EINVAL;
|
||||||
|
goto out_free;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
em28xx_errdev("/2: The frontend of your DVB/ATSC card"
|
em28xx_errdev("/2: The frontend of your DVB/ATSC card"
|
||||||
" isn't supported yet\n");
|
" isn't supported yet\n");
|
||||||
|
|
|
@ -475,6 +475,7 @@ static struct i2c_client em28xx_client_template = {
|
||||||
*/
|
*/
|
||||||
static char *i2c_devs[128] = {
|
static char *i2c_devs[128] = {
|
||||||
[0x4a >> 1] = "saa7113h",
|
[0x4a >> 1] = "saa7113h",
|
||||||
|
[0x52 >> 1] = "drxk",
|
||||||
[0x60 >> 1] = "remote IR sensor",
|
[0x60 >> 1] = "remote IR sensor",
|
||||||
[0x8e >> 1] = "remote IR sensor",
|
[0x8e >> 1] = "remote IR sensor",
|
||||||
[0x86 >> 1] = "tda9887",
|
[0x86 >> 1] = "tda9887",
|
||||||
|
|
|
@ -345,7 +345,7 @@ static void em28xx_ir_stop(struct rc_dev *rc)
|
||||||
cancel_delayed_work_sync(&ir->work);
|
cancel_delayed_work_sync(&ir->work);
|
||||||
}
|
}
|
||||||
|
|
||||||
int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 rc_type)
|
static int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 rc_type)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
struct em28xx_IR *ir = rc_dev->priv;
|
struct em28xx_IR *ir = rc_dev->priv;
|
||||||
|
|
|
@ -211,58 +211,9 @@ enum em28xx_chip_id {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Registers used by em202 and other AC97 chips
|
* Registers used by em202
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Standard AC97 registers */
|
|
||||||
#define AC97_RESET 0x00
|
|
||||||
|
|
||||||
/* Output volumes */
|
|
||||||
#define AC97_MASTER_VOL 0x02
|
|
||||||
#define AC97_LINE_LEVEL_VOL 0x04 /* Some devices use for headphones */
|
|
||||||
#define AC97_MASTER_MONO_VOL 0x06
|
|
||||||
|
|
||||||
/* Input volumes */
|
|
||||||
#define AC97_PC_BEEP_VOL 0x0a
|
|
||||||
#define AC97_PHONE_VOL 0x0c
|
|
||||||
#define AC97_MIC_VOL 0x0e
|
|
||||||
#define AC97_LINEIN_VOL 0x10
|
|
||||||
#define AC97_CD_VOL 0x12
|
|
||||||
#define AC97_VIDEO_VOL 0x14
|
|
||||||
#define AC97_AUX_VOL 0x16
|
|
||||||
#define AC97_PCM_OUT_VOL 0x18
|
|
||||||
|
|
||||||
/* capture registers */
|
|
||||||
#define AC97_RECORD_SELECT 0x1a
|
|
||||||
#define AC97_RECORD_GAIN 0x1c
|
|
||||||
|
|
||||||
/* control registers */
|
|
||||||
#define AC97_GENERAL_PURPOSE 0x20
|
|
||||||
#define AC97_3D_CTRL 0x22
|
|
||||||
#define AC97_AUD_INT_AND_PAG 0x24
|
|
||||||
#define AC97_POWER_DOWN_CTRL 0x26
|
|
||||||
#define AC97_EXT_AUD_ID 0x28
|
|
||||||
#define AC97_EXT_AUD_CTRL 0x2a
|
|
||||||
|
|
||||||
/* Supported rate varies for each AC97 device
|
|
||||||
if write an unsupported value, it will return the closest one
|
|
||||||
*/
|
|
||||||
#define AC97_PCM_OUT_FRONT_SRATE 0x2c
|
|
||||||
#define AC97_PCM_OUT_SURR_SRATE 0x2e
|
|
||||||
#define AC97_PCM_OUT_LFE_SRATE 0x30
|
|
||||||
#define AC97_PCM_IN_SRATE 0x32
|
|
||||||
|
|
||||||
/* For devices with more than 2 channels, extra output volumes */
|
|
||||||
#define AC97_LFE_MASTER_VOL 0x36
|
|
||||||
#define AC97_SURR_MASTER_VOL 0x38
|
|
||||||
|
|
||||||
/* Digital SPDIF output control */
|
|
||||||
#define AC97_SPDIF_OUT_CTRL 0x3a
|
|
||||||
|
|
||||||
/* Vendor ID identifier */
|
|
||||||
#define AC97_VENDOR_ID1 0x7c
|
|
||||||
#define AC97_VENDOR_ID2 0x7e
|
|
||||||
|
|
||||||
/* EMP202 vendor registers */
|
/* EMP202 vendor registers */
|
||||||
#define EM202_EXT_MODEM_CTRL 0x3e
|
#define EM202_EXT_MODEM_CTRL 0x3e
|
||||||
#define EM202_GPIO_CONF 0x4c
|
#define EM202_GPIO_CONF 0x4c
|
||||||
|
|
|
@ -1,94 +0,0 @@
|
||||||
/* ibmmpeg2.h - IBM MPEGCD21 definitions */
|
|
||||||
|
|
||||||
#ifndef __IBM_MPEG2__
|
|
||||||
#define __IBM_MPEG2__
|
|
||||||
|
|
||||||
/* Define all MPEG Decoder registers */
|
|
||||||
/* Chip Control and Status */
|
|
||||||
#define IBM_MP2_CHIP_CONTROL 0x200*2
|
|
||||||
#define IBM_MP2_CHIP_MODE 0x201*2
|
|
||||||
/* Timer Control and Status */
|
|
||||||
#define IBM_MP2_SYNC_STC2 0x202*2
|
|
||||||
#define IBM_MP2_SYNC_STC1 0x203*2
|
|
||||||
#define IBM_MP2_SYNC_STC0 0x204*2
|
|
||||||
#define IBM_MP2_SYNC_PTS2 0x205*2
|
|
||||||
#define IBM_MP2_SYNC_PTS1 0x206*2
|
|
||||||
#define IBM_MP2_SYNC_PTS0 0x207*2
|
|
||||||
/* Video FIFO Control */
|
|
||||||
#define IBM_MP2_FIFO 0x208*2
|
|
||||||
#define IBM_MP2_FIFOW 0x100*2
|
|
||||||
#define IBM_MP2_FIFO_STAT 0x209*2
|
|
||||||
#define IBM_MP2_RB_THRESHOLD 0x22b*2
|
|
||||||
/* Command buffer */
|
|
||||||
#define IBM_MP2_COMMAND 0x20a*2
|
|
||||||
#define IBM_MP2_CMD_DATA 0x20b*2
|
|
||||||
#define IBM_MP2_CMD_STAT 0x20c*2
|
|
||||||
#define IBM_MP2_CMD_ADDR 0x20d*2
|
|
||||||
/* Internal Processor Control and Status */
|
|
||||||
#define IBM_MP2_PROC_IADDR 0x20e*2
|
|
||||||
#define IBM_MP2_PROC_IDATA 0x20f*2
|
|
||||||
#define IBM_MP2_WR_PROT 0x235*2
|
|
||||||
/* DRAM Access */
|
|
||||||
#define IBM_MP2_DRAM_ADDR 0x210*2
|
|
||||||
#define IBM_MP2_DRAM_DATA 0x212*2
|
|
||||||
#define IBM_MP2_DRAM_CMD_STAT 0x213*2
|
|
||||||
#define IBM_MP2_BLOCK_SIZE 0x23b*2
|
|
||||||
#define IBM_MP2_SRC_ADDR 0x23c*2
|
|
||||||
/* Onscreen Display */
|
|
||||||
#define IBM_MP2_OSD_ADDR 0x214*2
|
|
||||||
#define IBM_MP2_OSD_DATA 0x215*2
|
|
||||||
#define IBM_MP2_OSD_MODE 0x217*2
|
|
||||||
#define IBM_MP2_OSD_LINK_ADDR 0x229*2
|
|
||||||
#define IBM_MP2_OSD_SIZE 0x22a*2
|
|
||||||
/* Interrupt Control */
|
|
||||||
#define IBM_MP2_HOST_INT 0x218*2
|
|
||||||
#define IBM_MP2_MASK0 0x219*2
|
|
||||||
#define IBM_MP2_HOST_INT1 0x23e*2
|
|
||||||
#define IBM_MP2_MASK1 0x23f*2
|
|
||||||
/* Audio Control */
|
|
||||||
#define IBM_MP2_AUD_IADDR 0x21a*2
|
|
||||||
#define IBM_MP2_AUD_IDATA 0x21b*2
|
|
||||||
#define IBM_MP2_AUD_FIFO 0x21c*2
|
|
||||||
#define IBM_MP2_AUD_FIFOW 0x101*2
|
|
||||||
#define IBM_MP2_AUD_CTL 0x21d*2
|
|
||||||
#define IBM_MP2_BEEP_CTL 0x21e*2
|
|
||||||
#define IBM_MP2_FRNT_ATTEN 0x22d*2
|
|
||||||
/* Display Control */
|
|
||||||
#define IBM_MP2_DISP_MODE 0x220*2
|
|
||||||
#define IBM_MP2_DISP_DLY 0x221*2
|
|
||||||
#define IBM_MP2_VBI_CTL 0x222*2
|
|
||||||
#define IBM_MP2_DISP_LBOR 0x223*2
|
|
||||||
#define IBM_MP2_DISP_TBOR 0x224*2
|
|
||||||
/* Polarity Control */
|
|
||||||
#define IBM_MP2_INFC_CTL 0x22c*2
|
|
||||||
|
|
||||||
/* control commands */
|
|
||||||
#define IBM_MP2_PLAY 0
|
|
||||||
#define IBM_MP2_PAUSE 1
|
|
||||||
#define IBM_MP2_SINGLE_FRAME 2
|
|
||||||
#define IBM_MP2_FAST_FORWARD 3
|
|
||||||
#define IBM_MP2_SLOW_MOTION 4
|
|
||||||
#define IBM_MP2_IMED_NORM_PLAY 5
|
|
||||||
#define IBM_MP2_RESET_WINDOW 6
|
|
||||||
#define IBM_MP2_FREEZE_FRAME 7
|
|
||||||
#define IBM_MP2_RESET_VID_RATE 8
|
|
||||||
#define IBM_MP2_CONFIG_DECODER 9
|
|
||||||
#define IBM_MP2_CHANNEL_SWITCH 10
|
|
||||||
#define IBM_MP2_RESET_AUD_RATE 11
|
|
||||||
#define IBM_MP2_PRE_OP_CHN_SW 12
|
|
||||||
#define IBM_MP2_SET_STILL_MODE 14
|
|
||||||
|
|
||||||
/* Define Xilinx FPGA Internal Registers */
|
|
||||||
|
|
||||||
/* general control register 0 */
|
|
||||||
#define XILINX_CTL0 0x600
|
|
||||||
/* genlock delay resister 1 */
|
|
||||||
#define XILINX_GLDELAY 0x602
|
|
||||||
/* send 16 bits to CS3310 port */
|
|
||||||
#define XILINX_CS3310 0x604
|
|
||||||
/* send 16 bits to CS3310 and complete */
|
|
||||||
#define XILINX_CS3310_CMPLT 0x60c
|
|
||||||
/* pulse width modulator control */
|
|
||||||
#define XILINX_PWM 0x606
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1830,18 +1830,6 @@ static long ivtv_default(struct file *file, void *fh, bool valid_prio,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
|
||||||
{
|
|
||||||
struct video_device *vfd = video_devdata(filp);
|
|
||||||
long ret;
|
|
||||||
|
|
||||||
if (ivtv_debug & IVTV_DBGFLG_IOCTL)
|
|
||||||
vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
|
|
||||||
ret = video_ioctl2(filp, cmd, arg);
|
|
||||||
vfd->debug = 0;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct v4l2_ioctl_ops ivtv_ioctl_ops = {
|
static const struct v4l2_ioctl_ops ivtv_ioctl_ops = {
|
||||||
.vidioc_querycap = ivtv_querycap,
|
.vidioc_querycap = ivtv_querycap,
|
||||||
.vidioc_s_audio = ivtv_s_audio,
|
.vidioc_s_audio = ivtv_s_audio,
|
||||||
|
|
|
@ -31,6 +31,5 @@ void ivtv_s_std_enc(struct ivtv *itv, v4l2_std_id *std);
|
||||||
void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std);
|
void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std);
|
||||||
int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf);
|
int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf);
|
||||||
int ivtv_s_input(struct file *file, void *fh, unsigned int inp);
|
int ivtv_s_input(struct file *file, void *fh, unsigned int inp);
|
||||||
long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -50,7 +50,7 @@ static const struct v4l2_file_operations ivtv_v4l2_enc_fops = {
|
||||||
.read = ivtv_v4l2_read,
|
.read = ivtv_v4l2_read,
|
||||||
.write = ivtv_v4l2_write,
|
.write = ivtv_v4l2_write,
|
||||||
.open = ivtv_v4l2_open,
|
.open = ivtv_v4l2_open,
|
||||||
.unlocked_ioctl = ivtv_v4l2_ioctl,
|
.unlocked_ioctl = video_ioctl2,
|
||||||
.release = ivtv_v4l2_close,
|
.release = ivtv_v4l2_close,
|
||||||
.poll = ivtv_v4l2_enc_poll,
|
.poll = ivtv_v4l2_enc_poll,
|
||||||
};
|
};
|
||||||
|
@ -60,7 +60,7 @@ static const struct v4l2_file_operations ivtv_v4l2_dec_fops = {
|
||||||
.read = ivtv_v4l2_read,
|
.read = ivtv_v4l2_read,
|
||||||
.write = ivtv_v4l2_write,
|
.write = ivtv_v4l2_write,
|
||||||
.open = ivtv_v4l2_open,
|
.open = ivtv_v4l2_open,
|
||||||
.unlocked_ioctl = ivtv_v4l2_ioctl,
|
.unlocked_ioctl = video_ioctl2,
|
||||||
.release = ivtv_v4l2_close,
|
.release = ivtv_v4l2_close,
|
||||||
.poll = ivtv_v4l2_dec_poll,
|
.poll = ivtv_v4l2_dec_poll,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
config VIDEO_M5MOLS
|
config VIDEO_M5MOLS
|
||||||
tristate "Fujitsu M-5MOLS 8MP sensor support"
|
tristate "Fujitsu M-5MOLS 8MP sensor support"
|
||||||
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
|
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
|
||||||
|
depends on MEDIA_CAMERA_SUPPORT
|
||||||
---help---
|
---help---
|
||||||
This driver supports Fujitsu M-5MOLS camera sensor with ISP
|
This driver supports Fujitsu M-5MOLS camera sensor with ISP
|
||||||
|
|
|
@ -60,6 +60,10 @@ MODULE_VERSION("0.1.1");
|
||||||
#define MEM2MEM_COLOR_STEP (0xff >> 4)
|
#define MEM2MEM_COLOR_STEP (0xff >> 4)
|
||||||
#define MEM2MEM_NUM_TILES 8
|
#define MEM2MEM_NUM_TILES 8
|
||||||
|
|
||||||
|
/* Flags that indicate processing mode */
|
||||||
|
#define MEM2MEM_HFLIP (1 << 0)
|
||||||
|
#define MEM2MEM_VFLIP (1 << 1)
|
||||||
|
|
||||||
#define dprintk(dev, fmt, arg...) \
|
#define dprintk(dev, fmt, arg...) \
|
||||||
v4l2_dbg(1, 1, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
|
v4l2_dbg(1, 1, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
|
||||||
|
|
||||||
|
@ -115,6 +119,24 @@ enum {
|
||||||
|
|
||||||
static struct v4l2_queryctrl m2mtest_ctrls[] = {
|
static struct v4l2_queryctrl m2mtest_ctrls[] = {
|
||||||
{
|
{
|
||||||
|
.id = V4L2_CID_HFLIP,
|
||||||
|
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
||||||
|
.name = "Mirror",
|
||||||
|
.minimum = 0,
|
||||||
|
.maximum = 1,
|
||||||
|
.step = 1,
|
||||||
|
.default_value = 0,
|
||||||
|
.flags = 0,
|
||||||
|
}, {
|
||||||
|
.id = V4L2_CID_VFLIP,
|
||||||
|
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
||||||
|
.name = "Vertical Mirror",
|
||||||
|
.minimum = 0,
|
||||||
|
.maximum = 1,
|
||||||
|
.step = 1,
|
||||||
|
.default_value = 0,
|
||||||
|
.flags = 0,
|
||||||
|
}, {
|
||||||
.id = V4L2_CID_TRANS_TIME_MSEC,
|
.id = V4L2_CID_TRANS_TIME_MSEC,
|
||||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||||
.name = "Transaction time (msec)",
|
.name = "Transaction time (msec)",
|
||||||
|
@ -181,6 +203,9 @@ struct m2mtest_ctx {
|
||||||
/* Abort requested by m2m */
|
/* Abort requested by m2m */
|
||||||
int aborting;
|
int aborting;
|
||||||
|
|
||||||
|
/* Processing mode */
|
||||||
|
int mode;
|
||||||
|
|
||||||
struct v4l2_m2m_ctx *m2m_ctx;
|
struct v4l2_m2m_ctx *m2m_ctx;
|
||||||
|
|
||||||
/* Source and destination queue data */
|
/* Source and destination queue data */
|
||||||
|
@ -249,19 +274,84 @@ static int device_process(struct m2mtest_ctx *ctx,
|
||||||
bytes_left = bytesperline - tile_w * MEM2MEM_NUM_TILES;
|
bytes_left = bytesperline - tile_w * MEM2MEM_NUM_TILES;
|
||||||
w = 0;
|
w = 0;
|
||||||
|
|
||||||
for (y = 0; y < height; ++y) {
|
switch (ctx->mode) {
|
||||||
for (t = 0; t < MEM2MEM_NUM_TILES; ++t) {
|
case MEM2MEM_HFLIP | MEM2MEM_VFLIP:
|
||||||
if (w & 0x1) {
|
p_out += bytesperline * height - bytes_left;
|
||||||
for (x = 0; x < tile_w; ++x)
|
for (y = 0; y < height; ++y) {
|
||||||
*p_out++ = *p_in++ + MEM2MEM_COLOR_STEP;
|
for (t = 0; t < MEM2MEM_NUM_TILES; ++t) {
|
||||||
} else {
|
if (w & 0x1) {
|
||||||
for (x = 0; x < tile_w; ++x)
|
for (x = 0; x < tile_w; ++x)
|
||||||
*p_out++ = *p_in++ - MEM2MEM_COLOR_STEP;
|
*--p_out = *p_in++ +
|
||||||
|
MEM2MEM_COLOR_STEP;
|
||||||
|
} else {
|
||||||
|
for (x = 0; x < tile_w; ++x)
|
||||||
|
*--p_out = *p_in++ -
|
||||||
|
MEM2MEM_COLOR_STEP;
|
||||||
|
}
|
||||||
|
++w;
|
||||||
}
|
}
|
||||||
++w;
|
p_in += bytes_left;
|
||||||
|
p_out -= bytes_left;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MEM2MEM_HFLIP:
|
||||||
|
for (y = 0; y < height; ++y) {
|
||||||
|
p_out += MEM2MEM_NUM_TILES * tile_w;
|
||||||
|
for (t = 0; t < MEM2MEM_NUM_TILES; ++t) {
|
||||||
|
if (w & 0x01) {
|
||||||
|
for (x = 0; x < tile_w; ++x)
|
||||||
|
*--p_out = *p_in++ +
|
||||||
|
MEM2MEM_COLOR_STEP;
|
||||||
|
} else {
|
||||||
|
for (x = 0; x < tile_w; ++x)
|
||||||
|
*--p_out = *p_in++ -
|
||||||
|
MEM2MEM_COLOR_STEP;
|
||||||
|
}
|
||||||
|
++w;
|
||||||
|
}
|
||||||
|
p_in += bytes_left;
|
||||||
|
p_out += bytesperline;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MEM2MEM_VFLIP:
|
||||||
|
p_out += bytesperline * (height - 1);
|
||||||
|
for (y = 0; y < height; ++y) {
|
||||||
|
for (t = 0; t < MEM2MEM_NUM_TILES; ++t) {
|
||||||
|
if (w & 0x1) {
|
||||||
|
for (x = 0; x < tile_w; ++x)
|
||||||
|
*p_out++ = *p_in++ +
|
||||||
|
MEM2MEM_COLOR_STEP;
|
||||||
|
} else {
|
||||||
|
for (x = 0; x < tile_w; ++x)
|
||||||
|
*p_out++ = *p_in++ -
|
||||||
|
MEM2MEM_COLOR_STEP;
|
||||||
|
}
|
||||||
|
++w;
|
||||||
|
}
|
||||||
|
p_in += bytes_left;
|
||||||
|
p_out += bytes_left - 2 * bytesperline;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
for (y = 0; y < height; ++y) {
|
||||||
|
for (t = 0; t < MEM2MEM_NUM_TILES; ++t) {
|
||||||
|
if (w & 0x1) {
|
||||||
|
for (x = 0; x < tile_w; ++x)
|
||||||
|
*p_out++ = *p_in++ +
|
||||||
|
MEM2MEM_COLOR_STEP;
|
||||||
|
} else {
|
||||||
|
for (x = 0; x < tile_w; ++x)
|
||||||
|
*p_out++ = *p_in++ -
|
||||||
|
MEM2MEM_COLOR_STEP;
|
||||||
|
}
|
||||||
|
++w;
|
||||||
|
}
|
||||||
|
p_in += bytes_left;
|
||||||
|
p_out += bytes_left;
|
||||||
}
|
}
|
||||||
p_in += bytes_left;
|
|
||||||
p_out += bytes_left;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -648,6 +738,14 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
|
||||||
struct m2mtest_ctx *ctx = priv;
|
struct m2mtest_ctx *ctx = priv;
|
||||||
|
|
||||||
switch (ctrl->id) {
|
switch (ctrl->id) {
|
||||||
|
case V4L2_CID_HFLIP:
|
||||||
|
ctrl->value = (ctx->mode & MEM2MEM_HFLIP) ? 1 : 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case V4L2_CID_VFLIP:
|
||||||
|
ctrl->value = (ctx->mode & MEM2MEM_VFLIP) ? 1 : 0;
|
||||||
|
break;
|
||||||
|
|
||||||
case V4L2_CID_TRANS_TIME_MSEC:
|
case V4L2_CID_TRANS_TIME_MSEC:
|
||||||
ctrl->value = ctx->transtime;
|
ctrl->value = ctx->transtime;
|
||||||
break;
|
break;
|
||||||
|
@ -691,6 +789,20 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
switch (ctrl->id) {
|
switch (ctrl->id) {
|
||||||
|
case V4L2_CID_HFLIP:
|
||||||
|
if (ctrl->value)
|
||||||
|
ctx->mode |= MEM2MEM_HFLIP;
|
||||||
|
else
|
||||||
|
ctx->mode &= ~MEM2MEM_HFLIP;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case V4L2_CID_VFLIP:
|
||||||
|
if (ctrl->value)
|
||||||
|
ctx->mode |= MEM2MEM_VFLIP;
|
||||||
|
else
|
||||||
|
ctx->mode &= ~MEM2MEM_VFLIP;
|
||||||
|
break;
|
||||||
|
|
||||||
case V4L2_CID_TRANS_TIME_MSEC:
|
case V4L2_CID_TRANS_TIME_MSEC:
|
||||||
ctx->transtime = ctrl->value;
|
ctx->transtime = ctrl->value;
|
||||||
break;
|
break;
|
||||||
|
@ -861,6 +973,7 @@ static int m2mtest_open(struct file *file)
|
||||||
ctx->translen = MEM2MEM_DEF_TRANSLEN;
|
ctx->translen = MEM2MEM_DEF_TRANSLEN;
|
||||||
ctx->transtime = MEM2MEM_DEF_TRANSTIME;
|
ctx->transtime = MEM2MEM_DEF_TRANSTIME;
|
||||||
ctx->num_processed = 0;
|
ctx->num_processed = 0;
|
||||||
|
ctx->mode = 0;
|
||||||
|
|
||||||
ctx->q_data[V4L2_M2M_SRC].fmt = &formats[0];
|
ctx->q_data[V4L2_M2M_SRC].fmt = &formats[0];
|
||||||
ctx->q_data[V4L2_M2M_DST].fmt = &formats[0];
|
ctx->q_data[V4L2_M2M_DST].fmt = &formats[0];
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* mt9m001 i2c address 0x5d
|
* mt9m001 i2c address 0x5d
|
||||||
* The platform has to define ctruct i2c_board_info objects and link to them
|
* The platform has to define struct i2c_board_info objects and link to them
|
||||||
* from struct soc_camera_link
|
* from struct soc_camera_link
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -688,11 +688,17 @@ static const struct v4l2_subdev_ops mt9m032_ops = {
|
||||||
static int mt9m032_probe(struct i2c_client *client,
|
static int mt9m032_probe(struct i2c_client *client,
|
||||||
const struct i2c_device_id *devid)
|
const struct i2c_device_id *devid)
|
||||||
{
|
{
|
||||||
|
struct mt9m032_platform_data *pdata = client->dev.platform_data;
|
||||||
struct i2c_adapter *adapter = client->adapter;
|
struct i2c_adapter *adapter = client->adapter;
|
||||||
struct mt9m032 *sensor;
|
struct mt9m032 *sensor;
|
||||||
int chip_version;
|
int chip_version;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (pdata == NULL) {
|
||||||
|
dev_err(&client->dev, "No platform data\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
|
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
|
||||||
dev_warn(&client->dev,
|
dev_warn(&client->dev,
|
||||||
"I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
|
"I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
|
||||||
|
@ -708,7 +714,7 @@ static int mt9m032_probe(struct i2c_client *client,
|
||||||
|
|
||||||
mutex_init(&sensor->lock);
|
mutex_init(&sensor->lock);
|
||||||
|
|
||||||
sensor->pdata = client->dev.platform_data;
|
sensor->pdata = pdata;
|
||||||
|
|
||||||
v4l2_i2c_subdev_init(&sensor->subdev, client, &mt9m032_ops);
|
v4l2_i2c_subdev_init(&sensor->subdev, client, &mt9m032_ops);
|
||||||
sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
|
sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
|
||||||
|
@ -738,7 +744,7 @@ static int mt9m032_probe(struct i2c_client *client,
|
||||||
sensor->format.field = V4L2_FIELD_NONE;
|
sensor->format.field = V4L2_FIELD_NONE;
|
||||||
sensor->format.colorspace = V4L2_COLORSPACE_SRGB;
|
sensor->format.colorspace = V4L2_COLORSPACE_SRGB;
|
||||||
|
|
||||||
v4l2_ctrl_handler_init(&sensor->ctrls, 4);
|
v4l2_ctrl_handler_init(&sensor->ctrls, 5);
|
||||||
|
|
||||||
v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops,
|
v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops,
|
||||||
V4L2_CID_GAIN, 0, 127, 1, 64);
|
V4L2_CID_GAIN, 0, 127, 1, 64);
|
||||||
|
@ -754,6 +760,9 @@ static int mt9m032_probe(struct i2c_client *client,
|
||||||
V4L2_CID_EXPOSURE, MT9M032_SHUTTER_WIDTH_MIN,
|
V4L2_CID_EXPOSURE, MT9M032_SHUTTER_WIDTH_MIN,
|
||||||
MT9M032_SHUTTER_WIDTH_MAX, 1,
|
MT9M032_SHUTTER_WIDTH_MAX, 1,
|
||||||
MT9M032_SHUTTER_WIDTH_DEF);
|
MT9M032_SHUTTER_WIDTH_DEF);
|
||||||
|
v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops,
|
||||||
|
V4L2_CID_PIXEL_RATE, pdata->pix_clock,
|
||||||
|
pdata->pix_clock, 1, pdata->pix_clock);
|
||||||
|
|
||||||
if (sensor->ctrls.error) {
|
if (sensor->ctrls.error) {
|
||||||
ret = sensor->ctrls.error;
|
ret = sensor->ctrls.error;
|
||||||
|
|
|
@ -214,7 +214,6 @@ struct mt9m111 {
|
||||||
int power_count;
|
int power_count;
|
||||||
const struct mt9m111_datafmt *fmt;
|
const struct mt9m111_datafmt *fmt;
|
||||||
int lastpage; /* PageMap cache value */
|
int lastpage; /* PageMap cache value */
|
||||||
unsigned char datawidth;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Find a data format by a pixel code */
|
/* Find a data format by a pixel code */
|
||||||
|
|
|
@ -950,7 +950,7 @@ static int mt9p031_probe(struct i2c_client *client,
|
||||||
mt9p031->model = did->driver_data;
|
mt9p031->model = did->driver_data;
|
||||||
mt9p031->reset = -1;
|
mt9p031->reset = -1;
|
||||||
|
|
||||||
v4l2_ctrl_handler_init(&mt9p031->ctrls, ARRAY_SIZE(mt9p031_ctrls) + 4);
|
v4l2_ctrl_handler_init(&mt9p031->ctrls, ARRAY_SIZE(mt9p031_ctrls) + 5);
|
||||||
|
|
||||||
v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
|
v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
|
||||||
V4L2_CID_EXPOSURE, MT9P031_SHUTTER_WIDTH_MIN,
|
V4L2_CID_EXPOSURE, MT9P031_SHUTTER_WIDTH_MIN,
|
||||||
|
@ -963,6 +963,9 @@ static int mt9p031_probe(struct i2c_client *client,
|
||||||
V4L2_CID_HFLIP, 0, 1, 1, 0);
|
V4L2_CID_HFLIP, 0, 1, 1, 0);
|
||||||
v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
|
v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
|
||||||
V4L2_CID_VFLIP, 0, 1, 1, 0);
|
V4L2_CID_VFLIP, 0, 1, 1, 0);
|
||||||
|
v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
|
||||||
|
V4L2_CID_PIXEL_RATE, pdata->target_freq,
|
||||||
|
pdata->target_freq, 1, pdata->target_freq);
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(mt9p031_ctrls); ++i)
|
for (i = 0; i < ARRAY_SIZE(mt9p031_ctrls); ++i)
|
||||||
v4l2_ctrl_new_custom(&mt9p031->ctrls, &mt9p031_ctrls[i], NULL);
|
v4l2_ctrl_new_custom(&mt9p031->ctrls, &mt9p031_ctrls[i], NULL);
|
||||||
|
|
|
@ -691,7 +691,7 @@ static int mt9t001_video_probe(struct i2c_client *client)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Configure the pixel clock polarity */
|
/* Configure the pixel clock polarity */
|
||||||
if (pdata && pdata->clk_pol) {
|
if (pdata->clk_pol) {
|
||||||
ret = mt9t001_write(client, MT9T001_PIXEL_CLOCK,
|
ret = mt9t001_write(client, MT9T001_PIXEL_CLOCK,
|
||||||
MT9T001_PIXEL_CLOCK_INVERT);
|
MT9T001_PIXEL_CLOCK_INVERT);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
@ -715,10 +715,16 @@ static int mt9t001_video_probe(struct i2c_client *client)
|
||||||
static int mt9t001_probe(struct i2c_client *client,
|
static int mt9t001_probe(struct i2c_client *client,
|
||||||
const struct i2c_device_id *did)
|
const struct i2c_device_id *did)
|
||||||
{
|
{
|
||||||
|
struct mt9t001_platform_data *pdata = client->dev.platform_data;
|
||||||
struct mt9t001 *mt9t001;
|
struct mt9t001 *mt9t001;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (pdata == NULL) {
|
||||||
|
dev_err(&client->dev, "No platform data\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!i2c_check_functionality(client->adapter,
|
if (!i2c_check_functionality(client->adapter,
|
||||||
I2C_FUNC_SMBUS_WORD_DATA)) {
|
I2C_FUNC_SMBUS_WORD_DATA)) {
|
||||||
dev_warn(&client->adapter->dev,
|
dev_warn(&client->adapter->dev,
|
||||||
|
@ -735,7 +741,7 @@ static int mt9t001_probe(struct i2c_client *client,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
v4l2_ctrl_handler_init(&mt9t001->ctrls, ARRAY_SIZE(mt9t001_ctrls) +
|
v4l2_ctrl_handler_init(&mt9t001->ctrls, ARRAY_SIZE(mt9t001_ctrls) +
|
||||||
ARRAY_SIZE(mt9t001_gains) + 2);
|
ARRAY_SIZE(mt9t001_gains) + 3);
|
||||||
|
|
||||||
v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops,
|
v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops,
|
||||||
V4L2_CID_EXPOSURE, MT9T001_SHUTTER_WIDTH_MIN,
|
V4L2_CID_EXPOSURE, MT9T001_SHUTTER_WIDTH_MIN,
|
||||||
|
@ -743,6 +749,9 @@ static int mt9t001_probe(struct i2c_client *client,
|
||||||
MT9T001_SHUTTER_WIDTH_DEF);
|
MT9T001_SHUTTER_WIDTH_DEF);
|
||||||
v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops,
|
v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops,
|
||||||
V4L2_CID_BLACK_LEVEL, 1, 1, 1, 1);
|
V4L2_CID_BLACK_LEVEL, 1, 1, 1, 1);
|
||||||
|
v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops,
|
||||||
|
V4L2_CID_PIXEL_RATE, pdata->ext_clk, pdata->ext_clk,
|
||||||
|
1, pdata->ext_clk);
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(mt9t001_ctrls); ++i)
|
for (i = 0; i < ARRAY_SIZE(mt9t001_ctrls); ++i)
|
||||||
v4l2_ctrl_new_custom(&mt9t001->ctrls, &mt9t001_ctrls[i], NULL);
|
v4l2_ctrl_new_custom(&mt9t001->ctrls, &mt9t001_ctrls[i], NULL);
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* mt9v022 i2c address 0x48, 0x4c, 0x58, 0x5c
|
* mt9v022 i2c address 0x48, 0x4c, 0x58, 0x5c
|
||||||
* The platform has to define ctruct i2c_board_info objects and link to them
|
* The platform has to define struct i2c_board_info objects and link to them
|
||||||
* from struct soc_camera_link
|
* from struct soc_camera_link
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -2014,7 +2014,7 @@ static int ccdc_get_selection(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
switch (sel->target) {
|
switch (sel->target) {
|
||||||
case V4L2_SUBDEV_SEL_TGT_CROP_BOUNDS:
|
case V4L2_SEL_TGT_CROP_BOUNDS:
|
||||||
sel->r.left = 0;
|
sel->r.left = 0;
|
||||||
sel->r.top = 0;
|
sel->r.top = 0;
|
||||||
sel->r.width = INT_MAX;
|
sel->r.width = INT_MAX;
|
||||||
|
@ -2024,7 +2024,7 @@ static int ccdc_get_selection(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
|
||||||
ccdc_try_crop(ccdc, format, &sel->r);
|
ccdc_try_crop(ccdc, format, &sel->r);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL:
|
case V4L2_SEL_TGT_CROP:
|
||||||
sel->r = *__ccdc_get_crop(ccdc, fh, sel->which);
|
sel->r = *__ccdc_get_crop(ccdc, fh, sel->which);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -2052,7 +2052,7 @@ static int ccdc_set_selection(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
|
||||||
struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
|
struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
|
||||||
struct v4l2_mbus_framefmt *format;
|
struct v4l2_mbus_framefmt *format;
|
||||||
|
|
||||||
if (sel->target != V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL ||
|
if (sel->target != V4L2_SEL_TGT_CROP ||
|
||||||
sel->pad != CCDC_PAD_SOURCE_OF)
|
sel->pad != CCDC_PAD_SOURCE_OF)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
@ -2064,7 +2064,7 @@ static int ccdc_set_selection(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
|
||||||
* pad. If the KEEP_CONFIG flag is set, just return the current crop
|
* pad. If the KEEP_CONFIG flag is set, just return the current crop
|
||||||
* rectangle.
|
* rectangle.
|
||||||
*/
|
*/
|
||||||
if (sel->flags & V4L2_SUBDEV_SEL_FLAG_KEEP_CONFIG) {
|
if (sel->flags & V4L2_SEL_FLAG_KEEP_CONFIG) {
|
||||||
sel->r = *__ccdc_get_crop(ccdc, fh, sel->which);
|
sel->r = *__ccdc_get_crop(ccdc, fh, sel->which);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1949,7 +1949,7 @@ static int preview_get_selection(struct v4l2_subdev *sd,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
switch (sel->target) {
|
switch (sel->target) {
|
||||||
case V4L2_SUBDEV_SEL_TGT_CROP_BOUNDS:
|
case V4L2_SEL_TGT_CROP_BOUNDS:
|
||||||
sel->r.left = 0;
|
sel->r.left = 0;
|
||||||
sel->r.top = 0;
|
sel->r.top = 0;
|
||||||
sel->r.width = INT_MAX;
|
sel->r.width = INT_MAX;
|
||||||
|
@ -1960,7 +1960,7 @@ static int preview_get_selection(struct v4l2_subdev *sd,
|
||||||
preview_try_crop(prev, format, &sel->r);
|
preview_try_crop(prev, format, &sel->r);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL:
|
case V4L2_SEL_TGT_CROP:
|
||||||
sel->r = *__preview_get_crop(prev, fh, sel->which);
|
sel->r = *__preview_get_crop(prev, fh, sel->which);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1988,7 +1988,7 @@ static int preview_set_selection(struct v4l2_subdev *sd,
|
||||||
struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
|
struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
|
||||||
struct v4l2_mbus_framefmt *format;
|
struct v4l2_mbus_framefmt *format;
|
||||||
|
|
||||||
if (sel->target != V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL ||
|
if (sel->target != V4L2_SEL_TGT_CROP ||
|
||||||
sel->pad != PREV_PAD_SINK)
|
sel->pad != PREV_PAD_SINK)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
@ -2000,7 +2000,7 @@ static int preview_set_selection(struct v4l2_subdev *sd,
|
||||||
* pad. If the KEEP_CONFIG flag is set, just return the current crop
|
* pad. If the KEEP_CONFIG flag is set, just return the current crop
|
||||||
* rectangle.
|
* rectangle.
|
||||||
*/
|
*/
|
||||||
if (sel->flags & V4L2_SUBDEV_SEL_FLAG_KEEP_CONFIG) {
|
if (sel->flags & V4L2_SEL_FLAG_KEEP_CONFIG) {
|
||||||
sel->r = *__preview_get_crop(prev, fh, sel->which);
|
sel->r = *__preview_get_crop(prev, fh, sel->which);
|
||||||
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