Merge branch 'patches_for_v3.6' into v4l_for_linus
* patches_for_v3.6: (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
c893e7c64e
|
@ -194,7 +194,7 @@ in the frequency range from 87,5 to 108,0 MHz</title>
|
|||
<corpauthor>National Radio Systems Committee
|
||||
(<ulink url="http://www.nrscstandards.org">http://www.nrscstandards.org</ulink>)</corpauthor>
|
||||
</authorgroup>
|
||||
<title>NTSC-4: United States RBDS Standard</title>
|
||||
<title>NRSC-4: United States RBDS Standard</title>
|
||||
</biblioentry>
|
||||
|
||||
<biblioentry id="iso12232">
|
||||
|
|
|
@ -464,14 +464,14 @@ The <structfield>type</structfield> field of the respective
|
|||
<structfield>tuner</structfield> field contains the index number of
|
||||
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>
|
||||
|
||||
<para>To query and change tuner properties applications use the
|
||||
&VIDIOC-G-TUNER; and &VIDIOC-S-TUNER; ioctl, respectively. The
|
||||
&v4l2-tuner; returned by <constant>VIDIOC_G_TUNER</constant> also
|
||||
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,
|
||||
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
|
||||
|
@ -491,8 +491,17 @@ the modulator. The <structfield>type</structfield> field of the
|
|||
respective &v4l2-output; returned by the &VIDIOC-ENUMOUTPUT; ioctl is
|
||||
set to <constant>V4L2_OUTPUT_TYPE_MODULATOR</constant> and its
|
||||
<structfield>modulator</structfield> field contains the index number
|
||||
of the modulator. This specification does not define radio output
|
||||
devices.</para>
|
||||
of the modulator.</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
|
||||
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>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Add selection API for extended control over cropping and
|
||||
composing. Does not affect the compatibility of current drivers and
|
||||
applications. See <link linkend="selection-api"> selection API </link> for
|
||||
details.</para>
|
||||
<para>Add selection API for extended control over cropping
|
||||
and composing. Does not affect the compatibility of current
|
||||
drivers and applications. See <link
|
||||
linkend="selection-api"> selection API </link> for
|
||||
details.</para>
|
||||
</listitem>
|
||||
</orderedlist>
|
||||
</section>
|
||||
|
@ -2458,6 +2459,18 @@ details.</para>
|
|||
</orderedlist>
|
||||
</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">
|
||||
<title>Relation of V4L2 to other Linux multimedia APIs</title>
|
||||
|
||||
|
|
|
@ -276,7 +276,7 @@
|
|||
</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<section id="v4l2-subdev-selections">
|
||||
<title>Selections: cropping, scaling and composition</title>
|
||||
|
||||
<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>
|
||||
|
||||
<para>As for pad formats, drivers store try and active
|
||||
rectangles for the selection targets of ACTUAL type <xref
|
||||
linkend="v4l2-subdev-selection-targets">.</xref></para>
|
||||
rectangles for the selection targets <xref
|
||||
linkend="v4l2-selections-common" />.</para>
|
||||
|
||||
<para>On sink pads, cropping is applied relative to the
|
||||
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,
|
||||
the crop rectangle on the subdev's sink pad is scaled to the
|
||||
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
|
||||
but not composing, the top and left values are not used and must
|
||||
always be set to zero.</para>
|
||||
|
@ -323,32 +323,32 @@
|
|||
<para>The drivers should always use the closest possible
|
||||
rectangle the user requests on all selection targets, unless
|
||||
specifically told otherwise.
|
||||
<constant>V4L2_SUBDEV_SEL_FLAG_SIZE_GE</constant> and
|
||||
<constant>V4L2_SUBDEV_SEL_FLAG_SIZE_LE</constant> flags may be
|
||||
<constant>V4L2_SEL_FLAG_GE</constant> and
|
||||
<constant>V4L2_SEL_FLAG_LE</constant> flags may be
|
||||
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>
|
||||
<title>Types of selection targets</title>
|
||||
|
||||
<section>
|
||||
<title>ACTUAL targets</title>
|
||||
<title>Actual targets</title>
|
||||
|
||||
<para>ACTUAL targets reflect the actual hardware configuration
|
||||
at any point of time. There is a BOUNDS target
|
||||
corresponding to every ACTUAL.</para>
|
||||
<para>Actual targets (without a postfix) reflect the actual
|
||||
hardware configuration at any point of time. There is a BOUNDS
|
||||
target corresponding to every actual target.</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>BOUNDS targets</title>
|
||||
|
||||
<para>BOUNDS targets is the smallest rectangle that contains
|
||||
all valid ACTUAL rectangles. It may not be possible to set the
|
||||
ACTUAL rectangle as large as the BOUNDS rectangle, however.
|
||||
This may be because e.g. a sensor's pixel array is not
|
||||
rectangular but cross-shaped or round. The maximum size may
|
||||
also be smaller than the BOUNDS rectangle.</para>
|
||||
<para>BOUNDS targets is the smallest rectangle that contains all
|
||||
valid actual rectangles. It may not be possible to set the actual
|
||||
rectangle as large as the BOUNDS rectangle, however. This may be
|
||||
because e.g. a sensor's pixel array is not rectangular but
|
||||
cross-shaped or round. The maximum size may also be smaller than the
|
||||
BOUNDS rectangle.</para>
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
@ -362,7 +362,7 @@
|
|||
performed by the user: the changes made will be propagated to
|
||||
any subsequent stages. If this behaviour is not desired, the
|
||||
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
|
||||
circumstances. This may also cause the accessed rectangle to be
|
||||
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>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>input</structfield></entry>
|
||||
<entry><structfield>reserved2</structfield></entry>
|
||||
<entry></entry>
|
||||
<entry>Some video capture drivers support rapid and
|
||||
synchronous video input changes, a function useful for example in
|
||||
video surveillance applications. For this purpose applications set the
|
||||
<constant>V4L2_BUF_FLAG_INPUT</constant> flag, and this field to the
|
||||
number of a video input as in &v4l2-input; field
|
||||
<structfield>index</structfield>.</entry>
|
||||
<entry>A place holder for future extensions and custom
|
||||
(driver defined) buffer types
|
||||
<constant>V4L2_BUF_TYPE_PRIVATE</constant> and higher. Applications
|
||||
should set this to 0.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
|
@ -921,13 +919,6 @@ previous key frame.</entry>
|
|||
<entry>The <structfield>timecode</structfield> field is valid.
|
||||
Drivers set or clear this flag when the <constant>VIDIOC_DQBUF</constant>
|
||||
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>
|
||||
<entry><constant>V4L2_BUF_FLAG_PREPARED</constant></entry>
|
||||
|
|
|
@ -53,11 +53,11 @@ cropping and composing rectangles have the same size.</para>
|
|||
</mediaobject>
|
||||
</figure>
|
||||
|
||||
For complete list of the available selection targets see table <xref
|
||||
linkend="v4l2-sel-target"/>
|
||||
|
||||
</section>
|
||||
|
||||
See <xref linkend="v4l2-selection-targets" /> for more
|
||||
information.
|
||||
|
||||
<section>
|
||||
|
||||
<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,
|
||||
drivers are expected to adjust the requested parameters and return the actual
|
||||
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>
|
||||
|
||||
|
@ -91,7 +91,7 @@ top/left corner at position <constant> (0,0) </constant>. The rectangle's
|
|||
coordinates are expressed in pixels.</para>
|
||||
|
||||
<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>
|
||||
V4L2_SEL_TGT_CROP_BOUNDS </constant>. The active cropping area must lie
|
||||
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>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 bounds rectangle. The composing rectangle must lie completely inside bounds
|
||||
rectangle. The driver must adjust the composing rectangle to fit to the
|
||||
bounding limits. Moreover, the driver can perform other adjustments according
|
||||
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
|
||||
<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
|
||||
<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
|
||||
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
|
||||
|
@ -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
|
||||
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
|
||||
area must lie completely inside the crop boundaries and the driver may further
|
||||
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
|
||||
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
|
||||
bounds rectangle. The driver must adjust the area to fit to the bounding
|
||||
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.
|
||||
The padded target is accessed by the <constant> V4L2_SEL_TGT_COMPOSE_PADDED
|
||||
</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>
|
||||
|
||||
|
@ -193,8 +193,8 @@ V4L2_SEL_TGT_COMPOSE_ACTIVE </constant> target.</para>
|
|||
<title>Scaling control</title>
|
||||
|
||||
<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
|
||||
</constant> and <constant> V4L2_SEL_TGT_COMPOSE_ACTIVE </constant> targets. If
|
||||
and the height of rectangles obtained using <constant> V4L2_SEL_TGT_CROP
|
||||
</constant> and <constant> V4L2_SEL_TGT_COMPOSE </constant> targets. If
|
||||
these are not equal then the scaling is applied. The application can compute
|
||||
the scaling ratios using these values.</para>
|
||||
|
||||
|
@ -252,7 +252,7 @@ area)</para>
|
|||
ret = ioctl(fd, &VIDIOC-G-SELECTION;, &sel);
|
||||
if (ret)
|
||||
exit(-1);
|
||||
sel.target = V4L2_SEL_TGT_CROP_ACTIVE;
|
||||
sel.target = V4L2_SEL_TGT_CROP;
|
||||
ret = ioctl(fd, &VIDIOC-S-SELECTION;, &sel);
|
||||
if (ret)
|
||||
exit(-1);
|
||||
|
@ -281,7 +281,7 @@ area)</para>
|
|||
r.left = sel.r.width / 4;
|
||||
r.top = sel.r.height / 4;
|
||||
sel.r = r;
|
||||
sel.target = V4L2_SEL_TGT_COMPOSE_ACTIVE;
|
||||
sel.target = V4L2_SEL_TGT_COMPOSE;
|
||||
sel.flags = V4L2_SEL_FLAG_LE;
|
||||
ret = ioctl(fd, &VIDIOC-S-SELECTION;, &sel);
|
||||
if (ret)
|
||||
|
@ -298,11 +298,11 @@ V4L2_BUF_TYPE_VIDEO_OUTPUT </constant> for other devices</para>
|
|||
|
||||
&v4l2-selection; compose = {
|
||||
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT,
|
||||
.target = V4L2_SEL_TGT_COMPOSE_ACTIVE,
|
||||
.target = V4L2_SEL_TGT_COMPOSE,
|
||||
};
|
||||
&v4l2-selection; crop = {
|
||||
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT,
|
||||
.target = V4L2_SEL_TGT_CROP_ACTIVE,
|
||||
.target = V4L2_SEL_TGT_CROP,
|
||||
};
|
||||
double hscale, vscale;
|
||||
|
||||
|
|
164
Documentation/DocBook/media/v4l/selections-common.xml
Normal file
164
Documentation/DocBook/media/v4l/selections-common.xml
Normal file
|
@ -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;
|
||||
</appendix>
|
||||
|
||||
<appendix>
|
||||
<title>Common definitions for V4L2 and V4L2 subdev interfaces</title>
|
||||
&sub-selections-common;
|
||||
</appendix>
|
||||
|
||||
<appendix id="videodev">
|
||||
<title>Video For Linux Two Header File</title>
|
||||
&sub-videodev2-h;
|
||||
|
|
|
@ -97,7 +97,13 @@ information.</para>
|
|||
<row>
|
||||
<entry>__u32</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>
|
||||
<entry>__u32</entry>
|
||||
|
|
|
@ -135,6 +135,12 @@ bounds or the value in the <structfield>type</structfield> field is
|
|||
wrong.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><errorcode>EBUSY</errorcode></term>
|
||||
<listitem>
|
||||
<para>A hardware seek is in progress.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
</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> V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE </constant>. The next step is
|
||||
setting the value of &v4l2-selection; <structfield>target</structfield> field
|
||||
to <constant> V4L2_SEL_TGT_CROP_ACTIVE </constant> (<constant>
|
||||
V4L2_SEL_TGT_COMPOSE_ACTIVE </constant>). Please refer to table <xref
|
||||
linkend="v4l2-sel-target" /> or <xref linkend="selection-api" /> for additional
|
||||
to <constant> V4L2_SEL_TGT_CROP </constant> (<constant>
|
||||
V4L2_SEL_TGT_COMPOSE </constant>). Please refer to table <xref
|
||||
linkend="v4l2-selections-common" /> or <xref linkend="selection-api" /> for additional
|
||||
targets. The <structfield>flags</structfield> and <structfield>reserved
|
||||
</structfield> fields of &v4l2-selection; are ignored and they must be filled
|
||||
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> V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE </constant>. The next step is
|
||||
setting the value of &v4l2-selection; <structfield>target</structfield> to
|
||||
<constant>V4L2_SEL_TGT_CROP_ACTIVE</constant> (<constant>
|
||||
V4L2_SEL_TGT_COMPOSE_ACTIVE </constant>). Please refer to table <xref
|
||||
linkend="v4l2-sel-target" /> or <xref linkend="selection-api" /> for additional
|
||||
<constant>V4L2_SEL_TGT_CROP</constant> (<constant>
|
||||
V4L2_SEL_TGT_COMPOSE </constant>). Please refer to table <xref
|
||||
linkend="v4l2-selections-common" /> or <xref linkend="selection-api" /> for additional
|
||||
targets. The &v4l2-rect; <structfield>r</structfield> rectangle need to be
|
||||
set to the desired active area. Field &v4l2-selection; <structfield> reserved
|
||||
</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>
|
||||
<table frame="none" pgwide="1" id="v4l2-sel-target">
|
||||
<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>
|
||||
<para>Selection targets and flags are documented in <xref
|
||||
linkend="v4l2-selections-common"/>.</para>
|
||||
|
||||
<section>
|
||||
<figure id="sel-const-adjust">
|
||||
|
@ -252,14 +186,14 @@ exist no rectangle </emphasis> that satisfies the constraints.</para>
|
|||
<row>
|
||||
<entry>__u32</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>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>flags</structfield></entry>
|
||||
<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>
|
||||
<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
|
||||
<constant>V4L2_TUNER_ANALOG_TV</constant> tuners can have this capability.</entry>
|
||||
</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>
|
||||
<entry><constant>V4L2_TUNER_CAP_STEREO</constant></entry>
|
||||
<entry>0x0010</entry>
|
||||
|
|
|
@ -71,12 +71,9 @@ initialize the <structfield>bytesused</structfield>,
|
|||
<structfield>field</structfield> and
|
||||
<structfield>timestamp</structfield> fields, see <xref
|
||||
linkend="buffer" /> for details.
|
||||
Applications must also set <structfield>flags</structfield> to 0. If a driver
|
||||
supports capturing from specific video inputs and you want to specify a video
|
||||
input, then <structfield>flags</structfield> should be set to
|
||||
<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
|
||||
Applications must also set <structfield>flags</structfield> to 0.
|
||||
The <structfield>reserved2</structfield> and
|
||||
<structfield>reserved</structfield> fields must be set to 0. When using
|
||||
the <link linkend="planar-apis">multi-planar API</link>, the
|
||||
<structfield>m.planes</structfield> field must contain a userspace pointer
|
||||
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
|
||||
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>
|
||||
|
||||
<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>
|
||||
<entry>__u32</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>
|
||||
<entry>__u32</entry>
|
||||
|
@ -118,9 +124,15 @@ wrong.</para>
|
|||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><errorcode>EAGAIN</errorcode></term>
|
||||
<term><errorcode>ENODATA</errorcode></term>
|
||||
<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>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
|
|
@ -72,10 +72,10 @@
|
|||
<section>
|
||||
<title>Types of selection targets</title>
|
||||
|
||||
<para>There are two types of selection targets: actual and bounds.
|
||||
The ACTUAL targets are the targets which configure the hardware.
|
||||
The BOUNDS target will return a rectangle that contain all
|
||||
possible ACTUAL rectangles.</para>
|
||||
<para>There are two types of selection targets: actual and bounds. The
|
||||
actual targets are the targets which configure the hardware. The BOUNDS
|
||||
target will return a rectangle that contain all possible actual
|
||||
rectangles.</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
|
@ -87,71 +87,8 @@
|
|||
<constant>EINVAL</constant>.</para>
|
||||
</section>
|
||||
|
||||
<table pgwide="1" frame="none" id="v4l2-subdev-selection-targets">
|
||||
<title>V4L2 subdev selection targets</title>
|
||||
<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>
|
||||
<para>Selection targets and flags are documented in <xref
|
||||
linkend="v4l2-selections-common"/>.</para>
|
||||
|
||||
<table pgwide="1" frame="none" id="v4l2-subdev-selection">
|
||||
<title>struct <structname>v4l2_subdev_selection</structname></title>
|
||||
|
@ -173,13 +110,13 @@
|
|||
<entry>__u32</entry>
|
||||
<entry><structfield>target</structfield></entry>
|
||||
<entry>Target selection rectangle. See
|
||||
<xref linkend="v4l2-subdev-selection-targets">.</xref>.</entry>
|
||||
<xref linkend="v4l2-selections-common" />.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>flags</structfield></entry>
|
||||
<entry>Flags. See
|
||||
<xref linkend="v4l2-subdev-selection-flags">.</xref></entry>
|
||||
<xref linkend="v4l2-selection-flags" />.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>&v4l2-rect;</entry>
|
||||
|
|
|
@ -29,7 +29,7 @@ use IO::Handle;
|
|||
"af9015", "ngene", "az6027", "lme2510_lg", "lme2510c_s7395",
|
||||
"lme2510c_s7395_old", "drxk", "drxk_terratec_h5",
|
||||
"drxk_hauppauge_hvr930c", "tda10071", "it9135", "it9137",
|
||||
"drxk_pctv");
|
||||
"drxk_pctv", "drxk_terratec_htc_stick", "sms1xxx_hcw");
|
||||
|
||||
# Check args
|
||||
syntax() if (scalar(@ARGV) != 1);
|
||||
|
@ -676,6 +676,24 @@ sub drxk_terratec_h5 {
|
|||
"$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 {
|
||||
my $sourcefile = "dvb-usb-it9135.zip";
|
||||
my $url = "http://www.ite.com.tw/uploads/firmware/v3.6.0.0/$sourcefile";
|
||||
|
@ -748,6 +766,28 @@ sub drxk_pctv {
|
|||
"$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
|
||||
|
||||
|
|
|
@ -558,3 +558,21 @@ Why: The V4L2_CID_VCENTER, V4L2_CID_HCENTER controls have been deprecated
|
|||
There are newer controls (V4L2_CID_PAN*, V4L2_CID_TILT*) that provide
|
||||
similar functionality.
|
||||
Who: Sylwester Nawrocki <sylvester.nawrocki@gmail.com>
|
||||
|
||||
----------------------------
|
||||
|
||||
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
|
||||
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.
|
||||
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),
|
||||
|
@ -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
|
||||
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
|
||||
will be either a top-level mutex or a mutex per device node. By default this
|
||||
lock will be used for unlocked_ioctl, but you can disable locking for
|
||||
selected ioctls by calling:
|
||||
The V4L core provides optional locking services. The main service is the
|
||||
lock field in struct video_device, which is a pointer to a mutex. If you set
|
||||
this pointer, then that will be used by unlocked_ioctl to serialize all ioctls.
|
||||
|
||||
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
|
||||
can take a long time you may want to do your own locking for the buffer queuing
|
||||
ioctls.
|
||||
|
||||
If you want still finer-grained locking then you have to set mutex_lock to NULL
|
||||
and do you own locking completely.
|
||||
|
||||
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.
|
||||
If you use the old videobuf then you must pass the video_device 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
|
||||
wait_finish callbacks to unlock/lock if applicable. In particular, if you use
|
||||
the lock in struct video_device then you must unlock/lock this mutex in
|
||||
wait_prepare and wait_finish.
|
||||
wait_finish callbacks to unlock/lock if applicable. If you use the queue->lock
|
||||
pointer, then you can use the helper functions vb2_ops_wait_prepare/finish.
|
||||
|
||||
The implementation of a hotplug disconnect should also take the lock before
|
||||
calling v4l2_device_disconnect.
|
||||
The implementation of a hotplug disconnect should also take the lock from
|
||||
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
|
||||
-------------------------
|
||||
|
|
|
@ -3061,8 +3061,7 @@ S: Maintained
|
|||
F: drivers/media/video/gspca/t613.c
|
||||
|
||||
GSPCA USB WEBCAM DRIVER
|
||||
M: Jean-Francois Moine <moinejf@free.fr>
|
||||
W: http://moinejf.free.fr
|
||||
M: Hans de Goede <hdegoede@redhat.com>
|
||||
L: linux-media@vger.kernel.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
|
||||
S: Maintained
|
||||
|
|
|
@ -1294,6 +1294,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
|
||||
* @adap: Handle to I2C bus
|
||||
|
@ -1308,8 +1339,7 @@ module_exit(i2c_exit);
|
|||
*/
|
||||
int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
|
||||
{
|
||||
unsigned long orig_jiffies;
|
||||
int ret, try;
|
||||
int ret;
|
||||
|
||||
/* REVISIT the fault reporting model here is weak:
|
||||
*
|
||||
|
@ -1347,15 +1377,7 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
|
|||
i2c_lock_adapter(adap);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
ret = __i2c_transfer(adap, msgs, num);
|
||||
i2c_unlock_adapter(adap);
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -6,20 +6,82 @@ menuconfig MEDIA_SUPPORT
|
|||
tristate "Multimedia support"
|
||||
depends on HAS_IOMEM
|
||||
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.
|
||||
Additional info and docs are available on the web at
|
||||
<http://linuxtv.org>
|
||||
|
||||
if MEDIA_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
|
||||
# Selectable only for webcam/grabbers, as other drivers don't use it
|
||||
#
|
||||
|
||||
config MEDIA_CONTROLLER
|
||||
bool "Media Controller API (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL
|
||||
depends on MEDIA_CAMERA_SUPPORT
|
||||
---help---
|
||||
Enable the media controller API used to query media devices internal
|
||||
topology and configure it dynamically.
|
||||
|
@ -27,26 +89,15 @@ config MEDIA_CONTROLLER
|
|||
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
|
||||
tristate "Video For Linux"
|
||||
---help---
|
||||
V4L core support for video capture and overlay devices, webcams and
|
||||
AM/FM radio cards.
|
||||
|
||||
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.
|
||||
tristate
|
||||
depends on MEDIA_SUPPORT
|
||||
depends on MEDIA_CAMERA_SUPPORT || MEDIA_ANALOG_TV_SUPPORT || MEDIA_RADIO_SUPPORT
|
||||
default y
|
||||
|
||||
config VIDEO_V4L2_COMMON
|
||||
tristate
|
||||
|
@ -64,25 +115,15 @@ config VIDEO_V4L2_SUBDEV_API
|
|||
|
||||
#
|
||||
# DVB Core
|
||||
# Only enables if one of DTV is selected
|
||||
#
|
||||
|
||||
config DVB_CORE
|
||||
tristate "DVB for Linux"
|
||||
tristate
|
||||
depends on MEDIA_SUPPORT
|
||||
depends on MEDIA_DIGITAL_TV_SUPPORT
|
||||
default y
|
||||
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
|
||||
bool "DVB Network Support"
|
||||
|
@ -97,12 +138,7 @@ config DVB_NET
|
|||
You may want to disable the network support on embedded devices. If
|
||||
unsure say Y.
|
||||
|
||||
config VIDEO_MEDIA
|
||||
tristate
|
||||
default (DVB_CORE && (VIDEO_DEV = n)) || (VIDEO_DEV && (DVB_CORE = n)) || (DVB_CORE && VIDEO_DEV)
|
||||
|
||||
comment "Multimedia drivers"
|
||||
|
||||
comment "Media drivers"
|
||||
source "drivers/media/common/Kconfig"
|
||||
source "drivers/media/rc/Kconfig"
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
config MEDIA_ATTACH
|
||||
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
|
||||
default y if !EXPERT
|
||||
help
|
||||
Remove the static dependency of DVB card drivers on all
|
||||
frontend modules for all possible card variants. Instead,
|
||||
|
@ -19,15 +20,15 @@ config MEDIA_ATTACH
|
|||
|
||||
config MEDIA_TUNER
|
||||
tristate
|
||||
default VIDEO_MEDIA && I2C
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
depends on (MEDIA_ANALOG_TV_SUPPORT || MEDIA_RADIO_SUPPORT) && I2C
|
||||
default y
|
||||
select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
|
||||
select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE
|
||||
select MEDIA_TUNER_XC4000 if !MEDIA_TUNER_CUSTOMISE
|
||||
select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMISE
|
||||
select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
|
||||
select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMISE && EXPERIMENTAL
|
||||
select MEDIA_TUNER_TEA5767 if !MEDIA_TUNER_CUSTOMISE
|
||||
select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMISE && MEDIA_RADIO_SUPPORT && EXPERIMENTAL
|
||||
select MEDIA_TUNER_TEA5767 if !MEDIA_TUNER_CUSTOMISE && MEDIA_RADIO_SUPPORT
|
||||
select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
|
||||
select MEDIA_TUNER_TDA9887 if !MEDIA_TUNER_CUSTOMISE
|
||||
select MEDIA_TUNER_MC44S803 if !MEDIA_TUNER_CUSTOMISE
|
||||
|
@ -47,10 +48,11 @@ config MEDIA_TUNER_CUSTOMISE
|
|||
|
||||
menu "Customize TV tuners"
|
||||
visible if MEDIA_TUNER_CUSTOMISE
|
||||
depends on MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT || MEDIA_RADIO_SUPPORT
|
||||
|
||||
config MEDIA_TUNER_SIMPLE
|
||||
tristate "Simple tuner support"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
depends on MEDIA_SUPPORT && I2C
|
||||
select MEDIA_TUNER_TDA9887
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
|
@ -58,7 +60,7 @@ config MEDIA_TUNER_SIMPLE
|
|||
|
||||
config MEDIA_TUNER_TDA8290
|
||||
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_TDA18271
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
|
@ -67,21 +69,21 @@ config MEDIA_TUNER_TDA8290
|
|||
|
||||
config MEDIA_TUNER_TDA827X
|
||||
tristate "Philips TDA827X silicon tuner"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
depends on MEDIA_SUPPORT && I2C
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
A DVB-T silicon tuner module. Say Y when you want to support this tuner.
|
||||
|
||||
config MEDIA_TUNER_TDA18271
|
||||
tristate "NXP TDA18271 silicon tuner"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
depends on MEDIA_SUPPORT && I2C
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
A silicon tuner module. Say Y when you want to support this tuner.
|
||||
|
||||
config MEDIA_TUNER_TDA9887
|
||||
tristate "TDA 9885/6/7 analog IF demodulator"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
depends on MEDIA_SUPPORT && I2C
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
Say Y here to include support for Philips TDA9885/6/7
|
||||
|
@ -89,7 +91,7 @@ config MEDIA_TUNER_TDA9887
|
|||
|
||||
config MEDIA_TUNER_TEA5761
|
||||
tristate "TEA 5761 radio tuner (EXPERIMENTAL)"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
depends on MEDIA_SUPPORT && I2C
|
||||
depends on EXPERIMENTAL
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
|
@ -97,63 +99,63 @@ config MEDIA_TUNER_TEA5761
|
|||
|
||||
config MEDIA_TUNER_TEA5767
|
||||
tristate "TEA 5767 radio tuner"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
depends on MEDIA_SUPPORT && I2C
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
Say Y here to include support for the Philips TEA5767 radio tuner.
|
||||
|
||||
config MEDIA_TUNER_MT20XX
|
||||
tristate "Microtune 2032 / 2050 tuners"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
depends on MEDIA_SUPPORT && I2C
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
Say Y here to include support for the MT2032 / MT2050 tuner.
|
||||
|
||||
config MEDIA_TUNER_MT2060
|
||||
tristate "Microtune MT2060 silicon IF tuner"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
depends on MEDIA_SUPPORT && I2C
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
A driver for the silicon IF tuner MT2060 from Microtune.
|
||||
|
||||
config MEDIA_TUNER_MT2063
|
||||
tristate "Microtune MT2063 silicon IF tuner"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
depends on MEDIA_SUPPORT && I2C
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
A driver for the silicon IF tuner MT2063 from Microtune.
|
||||
|
||||
config MEDIA_TUNER_MT2266
|
||||
tristate "Microtune MT2266 silicon tuner"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
depends on MEDIA_SUPPORT && I2C
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
A driver for the silicon baseband tuner MT2266 from Microtune.
|
||||
|
||||
config MEDIA_TUNER_MT2131
|
||||
tristate "Microtune MT2131 silicon tuner"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
depends on MEDIA_SUPPORT && I2C
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
A driver for the silicon baseband tuner MT2131 from Microtune.
|
||||
|
||||
config MEDIA_TUNER_QT1010
|
||||
tristate "Quantek QT1010 silicon tuner"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
depends on MEDIA_SUPPORT && I2C
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
A driver for the silicon tuner QT1010 from Quantek.
|
||||
|
||||
config MEDIA_TUNER_XC2028
|
||||
tristate "XCeive xc2028/xc3028 tuners"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
depends on MEDIA_SUPPORT && I2C
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
Say Y here to include support for the xc2028/xc3028 tuners.
|
||||
|
||||
config MEDIA_TUNER_XC5000
|
||||
tristate "Xceive XC5000 silicon tuner"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
depends on MEDIA_SUPPORT && I2C
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
A driver for the silicon tuner XC5000 from Xceive.
|
||||
|
@ -162,7 +164,7 @@ config MEDIA_TUNER_XC5000
|
|||
|
||||
config MEDIA_TUNER_XC4000
|
||||
tristate "Xceive XC4000 silicon tuner"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
depends on MEDIA_SUPPORT && I2C
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
A driver for the silicon tuner XC4000 from Xceive.
|
||||
|
@ -171,70 +173,70 @@ config MEDIA_TUNER_XC4000
|
|||
|
||||
config MEDIA_TUNER_MXL5005S
|
||||
tristate "MaxLinear MSL5005S silicon tuner"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
depends on MEDIA_SUPPORT && I2C
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
A driver for the silicon tuner MXL5005S from MaxLinear.
|
||||
|
||||
config MEDIA_TUNER_MXL5007T
|
||||
tristate "MaxLinear MxL5007T silicon tuner"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
depends on MEDIA_SUPPORT && I2C
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
A driver for the silicon tuner MxL5007T from MaxLinear.
|
||||
|
||||
config MEDIA_TUNER_MC44S803
|
||||
tristate "Freescale MC44S803 Low Power CMOS Broadband tuners"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
depends on MEDIA_SUPPORT && I2C
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
Say Y here to support the Freescale MC44S803 based tuners
|
||||
|
||||
config MEDIA_TUNER_MAX2165
|
||||
tristate "Maxim MAX2165 silicon tuner"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
depends on MEDIA_SUPPORT && I2C
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
A driver for the silicon tuner MAX2165 from Maxim.
|
||||
|
||||
config MEDIA_TUNER_TDA18218
|
||||
tristate "NXP TDA18218 silicon tuner"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
depends on MEDIA_SUPPORT && I2C
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
NXP TDA18218 silicon tuner driver.
|
||||
|
||||
config MEDIA_TUNER_FC0011
|
||||
tristate "Fitipower FC0011 silicon tuner"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
depends on MEDIA_SUPPORT && I2C
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
Fitipower FC0011 silicon tuner driver.
|
||||
|
||||
config MEDIA_TUNER_FC0012
|
||||
tristate "Fitipower FC0012 silicon tuner"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
depends on MEDIA_SUPPORT && I2C
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
Fitipower FC0012 silicon tuner driver.
|
||||
|
||||
config MEDIA_TUNER_FC0013
|
||||
tristate "Fitipower FC0013 silicon tuner"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
depends on MEDIA_SUPPORT && I2C
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
Fitipower FC0013 silicon tuner driver.
|
||||
|
||||
config MEDIA_TUNER_TDA18212
|
||||
tristate "NXP TDA18212 silicon tuner"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
depends on MEDIA_SUPPORT && I2C
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
NXP TDA18212 silicon tuner driver.
|
||||
|
||||
config MEDIA_TUNER_TUA9001
|
||||
tristate "Infineon TUA 9001 silicon tuner"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
depends on MEDIA_SUPPORT && I2C
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
Infineon TUA 9001 silicon tuner driver.
|
||||
|
|
|
@ -90,11 +90,22 @@ struct firmware_properties {
|
|||
int scode_nr;
|
||||
};
|
||||
|
||||
enum xc2028_state {
|
||||
XC2028_NO_FIRMWARE = 0,
|
||||
XC2028_WAITING_FIRMWARE,
|
||||
XC2028_ACTIVE,
|
||||
XC2028_SLEEP,
|
||||
XC2028_NODEV,
|
||||
};
|
||||
|
||||
struct xc2028_data {
|
||||
struct list_head hybrid_tuner_instance_list;
|
||||
struct tuner_i2c_props i2c_props;
|
||||
__u32 frequency;
|
||||
|
||||
enum xc2028_state state;
|
||||
const char *fname;
|
||||
|
||||
struct firmware_description *firm;
|
||||
int firm_size;
|
||||
__u16 firm_version;
|
||||
|
@ -255,6 +266,21 @@ static v4l2_std_id parse_audio_std_option(void)
|
|||
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)
|
||||
{
|
||||
int i;
|
||||
|
@ -270,45 +296,28 @@ static void free_firmware(struct xc2028_data *priv)
|
|||
|
||||
priv->firm = NULL;
|
||||
priv->firm_size = 0;
|
||||
priv->state = XC2028_NO_FIRMWARE;
|
||||
|
||||
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;
|
||||
const struct firmware *fw = NULL;
|
||||
const unsigned char *p, *endp;
|
||||
int rc = 0;
|
||||
int n, n_array;
|
||||
char name[33];
|
||||
char *fname;
|
||||
|
||||
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;
|
||||
endp = p + fw->size;
|
||||
|
||||
if (fw->size < sizeof(name) - 1 + 2 + 2) {
|
||||
tuner_err("Error: firmware file %s has invalid size!\n",
|
||||
fname);
|
||||
priv->fname);
|
||||
goto corrupt;
|
||||
}
|
||||
|
||||
|
@ -323,7 +332,7 @@ static int load_all_firmwares(struct dvb_frontend *fe)
|
|||
p += 2;
|
||||
|
||||
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 = kcalloc(n_array, sizeof(*priv->firm), GFP_KERNEL);
|
||||
|
@ -417,9 +426,10 @@ err:
|
|||
free_firmware(priv);
|
||||
|
||||
done:
|
||||
release_firmware(fw);
|
||||
if (rc == 0)
|
||||
tuner_dbg("Firmware files loaded.\n");
|
||||
else
|
||||
priv->state = XC2028_NODEV;
|
||||
|
||||
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 firmware_properties new_fw;
|
||||
int rc = 0, retry_count = 0;
|
||||
int rc, retry_count = 0;
|
||||
u16 version, hwmodel;
|
||||
v4l2_std_id std0;
|
||||
|
||||
tuner_dbg("%s called\n", __func__);
|
||||
|
||||
if (!priv->firm) {
|
||||
if (!priv->ctrl.fname) {
|
||||
tuner_info("xc2028/3028 firmware name not set!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = load_all_firmwares(fe);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
}
|
||||
rc = check_device_status(priv);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
if (priv->ctrl.mts && !(type & FM))
|
||||
type |= MTS;
|
||||
|
@ -749,9 +752,13 @@ retry:
|
|||
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) ==
|
||||
(priv->cur_fw.type & BASE_TYPES)) {
|
||||
/*
|
||||
* No need to reload base firmware if it matches and if the tuner
|
||||
* 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");
|
||||
goto skip_base;
|
||||
}
|
||||
|
@ -872,10 +879,13 @@ read_not_reliable:
|
|||
* 2. Tell whether BASE firmware was just changed the next time through.
|
||||
*/
|
||||
priv->cur_fw.type |= BASE;
|
||||
priv->state = XC2028_ACTIVE;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
priv->state = XC2028_SLEEP;
|
||||
|
||||
memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
|
||||
if (retry_count < 8) {
|
||||
msleep(50);
|
||||
|
@ -893,28 +903,39 @@ static int xc2028_signal(struct dvb_frontend *fe, u16 *strength)
|
|||
{
|
||||
struct xc2028_data *priv = fe->tuner_priv;
|
||||
u16 frq_lock, signal = 0;
|
||||
int rc;
|
||||
int rc, i;
|
||||
|
||||
tuner_dbg("%s called\n", __func__);
|
||||
|
||||
rc = check_device_status(priv);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
mutex_lock(&priv->lock);
|
||||
|
||||
/* Sync Lock Indicator */
|
||||
rc = xc2028_get_reg(priv, XREG_LOCK, &frq_lock);
|
||||
if (rc < 0)
|
||||
goto ret;
|
||||
for (i = 0; i < 3; i++) {
|
||||
rc = xc2028_get_reg(priv, XREG_LOCK, &frq_lock);
|
||||
if (rc < 0)
|
||||
goto ret;
|
||||
|
||||
/* Frequency is locked */
|
||||
if (frq_lock == 1)
|
||||
signal = 1 << 11;
|
||||
if (frq_lock)
|
||||
break;
|
||||
msleep(6);
|
||||
}
|
||||
|
||||
/* Frequency didn't lock */
|
||||
if (frq_lock == 2)
|
||||
goto ret;
|
||||
|
||||
/* Get SNR of the video signal */
|
||||
rc = xc2028_get_reg(priv, XREG_SNR, &signal);
|
||||
if (rc < 0)
|
||||
goto ret;
|
||||
|
||||
/* Use both frq_lock and signal to generate the result */
|
||||
signal = signal || ((signal & 0x07) << 12);
|
||||
/* Signal level is 3 bits only */
|
||||
|
||||
signal = ((1 << 12) - 1) | ((signal & 0x07) << 12);
|
||||
|
||||
ret:
|
||||
mutex_unlock(&priv->lock);
|
||||
|
@ -926,6 +947,49 @@ ret:
|
|||
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
|
||||
|
||||
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 bw = c->bandwidth_hz;
|
||||
struct xc2028_data *priv = fe->tuner_priv;
|
||||
unsigned int type=0;
|
||||
int rc;
|
||||
unsigned int type = 0;
|
||||
u16 demod = 0;
|
||||
|
||||
tuner_dbg("%s called\n", __func__);
|
||||
|
||||
rc = check_device_status(priv);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
switch (delsys) {
|
||||
case SYS_DVBT:
|
||||
case SYS_DVBT2:
|
||||
|
@ -1201,7 +1270,11 @@ static int xc2028_set_params(struct dvb_frontend *fe)
|
|||
static int xc2028_sleep(struct dvb_frontend *fe)
|
||||
{
|
||||
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 */
|
||||
if (no_poweroff || priv->ctrl.disable_power_mgmt)
|
||||
|
@ -1220,7 +1293,7 @@ static int xc2028_sleep(struct dvb_frontend *fe)
|
|||
else
|
||||
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);
|
||||
|
||||
|
@ -1237,8 +1310,9 @@ static int xc2028_dvb_release(struct dvb_frontend *fe)
|
|||
|
||||
/* only perform final cleanup if this is the last instance */
|
||||
if (hybrid_tuner_report_instance_count(priv) == 1) {
|
||||
kfree(priv->ctrl.fname);
|
||||
free_firmware(priv);
|
||||
kfree(priv->ctrl.fname);
|
||||
priv->ctrl.fname = NULL;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct xc2028_data *priv = fe->tuner_priv;
|
||||
int rc;
|
||||
|
||||
tuner_dbg("%s called\n", __func__);
|
||||
|
||||
rc = check_device_status(priv);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
*frequency = priv->frequency;
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
/*
|
||||
* 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));
|
||||
if (priv->ctrl.max_len < 9)
|
||||
priv->ctrl.max_len = 13;
|
||||
|
||||
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);
|
||||
if (priv->ctrl.fname == NULL)
|
||||
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);
|
||||
|
||||
return rc;
|
||||
|
@ -1305,6 +1435,7 @@ static const struct dvb_tuner_ops xc2028_dvb_tuner_ops = {
|
|||
.release = xc2028_dvb_release,
|
||||
.get_frequency = xc2028_get_frequency,
|
||||
.get_rf_strength = xc2028_signal,
|
||||
.get_afc = xc2028_get_afc,
|
||||
.set_params = xc2028_set_params,
|
||||
.sleep = xc2028_sleep,
|
||||
};
|
||||
|
@ -1375,3 +1506,5 @@ MODULE_DESCRIPTION("Xceive xc2028/xc3028 tuner driver");
|
|||
MODULE_AUTHOR("Michel Ludwig <michel.ludwig@gmail.com>");
|
||||
MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
|
||||
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->video_standard = DTV6;
|
||||
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_DVBT2:
|
||||
dprintk(1, "%s() OFDM\n", __func__);
|
||||
|
|
|
@ -578,6 +578,7 @@ static int demod_attach_drxk(struct ddb_input *input)
|
|||
|
||||
memset(&config, 0, sizeof(config));
|
||||
config.microcode_name = "drxk_a3.mc";
|
||||
config.qam_demod_parameter_count = 4;
|
||||
config.adr = 0x29 + (input->nr & 1);
|
||||
|
||||
fe = input->fe = dvb_attach(drxk_attach, &config, i2c);
|
||||
|
|
|
@ -220,6 +220,7 @@ struct dvb_tuner_ops {
|
|||
#define TUNER_STATUS_STEREO 2
|
||||
int (*get_status)(struct dvb_frontend *fe, u32 *status);
|
||||
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
|
||||
* tuners which require sophisticated tuning loops, controlling each parameter separately. */
|
||||
|
|
|
@ -418,9 +418,12 @@ config DVB_USB_RTL28XXU
|
|||
tristate "Realtek RTL28xxU DVB USB support"
|
||||
depends on DVB_USB && EXPERIMENTAL
|
||||
select DVB_RTL2830
|
||||
select DVB_RTL2832
|
||||
select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE
|
||||
select MEDIA_TUNER_MT2060 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
|
||||
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));
|
||||
|
||||
if (ret > 0)
|
||||
deb_info("%s: mac is %02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
__func__, mac[0], mac[1], mac[2],
|
||||
mac[3], mac[4], mac[5]);
|
||||
deb_info("%s: mac is %pM\n", __func__, mac);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -100,6 +100,7 @@
|
|||
#define USB_PID_CONCEPTRONIC_CTVDIGRCU 0xe397
|
||||
#define USB_PID_CONEXANT_D680_DMB 0x86d6
|
||||
#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_REENUM 0x0065
|
||||
#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_RC 0x0097
|
||||
#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_WARM 0x3202
|
||||
#define USB_PID_TWINHAN_VP7020_COLD 0x3203
|
||||
|
@ -245,6 +247,7 @@
|
|||
#define USB_PID_TERRATEC_H7_2 0x10a3
|
||||
#define USB_PID_TERRATEC_T3 0x10a0
|
||||
#define USB_PID_TERRATEC_T5 0x10a1
|
||||
#define USB_PID_NOXON_DAB_STICK 0x00b3
|
||||
#define USB_PID_PINNACLE_EXPRESSCARD_320CX 0x022e
|
||||
#define USB_PID_PINNACLE_PCTV2000E 0x022c
|
||||
#define USB_PID_PINNACLE_PCTV_DVB_T_FLASH 0x0228
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 2009 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
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -22,10 +23,13 @@
|
|||
#include "rtl28xxu.h"
|
||||
|
||||
#include "rtl2830.h"
|
||||
#include "rtl2832.h"
|
||||
|
||||
#include "qt1010.h"
|
||||
#include "mt2060.h"
|
||||
#include "mxl5005s.h"
|
||||
#include "fc0012.h"
|
||||
#include "fc0013.h"
|
||||
|
||||
/* debug */
|
||||
static int dvb_usb_rtl28xxu_debug;
|
||||
|
@ -80,7 +84,7 @@ err:
|
|||
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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -308,12 +312,12 @@ static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap)
|
|||
*/
|
||||
|
||||
/* GPIO direction */
|
||||
ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_DIR, 0x0a);
|
||||
ret = rtl28xx_wr_reg(adap->dev, SYS_GPIO_DIR, 0x0a);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
/* 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)
|
||||
goto err;
|
||||
|
||||
|
@ -381,34 +385,159 @@ err:
|
|||
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)
|
||||
{
|
||||
int ret;
|
||||
struct rtl28xxu_priv *priv = adap->dev->priv;
|
||||
u8 buf[1];
|
||||
struct rtl2832_config *rtl2832_config;
|
||||
|
||||
u8 buf[2], val;
|
||||
/* open RTL2832U/RTL2832 I2C gate */
|
||||
struct rtl28xxu_req req_gate_open = {0x0120, 0x0011, 0x0001, "\x18"};
|
||||
/* close RTL2832U/RTL2832 I2C gate */
|
||||
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 */
|
||||
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__);
|
||||
|
||||
/* GPIO direction */
|
||||
ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_DIR, 0x0a);
|
||||
|
||||
ret = rtl28xx_rd_reg(adap->dev, SYS_GPIO_DIR, &val);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
/* enable as output GPIO0, GPIO2, GPIO4 */
|
||||
ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_OUT_EN, 0x15);
|
||||
val &= 0xbf;
|
||||
|
||||
ret = rtl28xx_wr_reg(adap->dev, SYS_GPIO_DIR, val);
|
||||
if (ret)
|
||||
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)
|
||||
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
|
||||
* 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)
|
||||
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 */
|
||||
ret = rtl28xxu_ctrl_msg(adap->dev, &req_fc2580);
|
||||
if (ret == 0 && buf[0] == 0x56) {
|
||||
priv->tuner = TUNER_RTL2832_FC2580;
|
||||
deb_info("%s: FC2580\n", __func__);
|
||||
goto found;
|
||||
} else {
|
||||
deb_info("%s: FC2580 probe failed=%d - %02x\n",
|
||||
__func__, ret, buf[0]);
|
||||
/* TODO implement tuner */
|
||||
info("%s: FC2580 tuner found", __func__);
|
||||
goto unsupported;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate_close);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
/* tuner not found */
|
||||
deb_info("No compatible tuner found");
|
||||
ret = -ENODEV;
|
||||
goto err;
|
||||
return ret;
|
||||
|
||||
found:
|
||||
/* close demod I2C gate */
|
||||
|
@ -446,9 +658,18 @@ found:
|
|||
goto err;
|
||||
|
||||
/* 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;
|
||||
|
||||
err:
|
||||
deb_info("%s: failed=%d\n", __func__, ret);
|
||||
return ret;
|
||||
|
@ -531,10 +752,24 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
|
|||
deb_info("%s:\n", __func__);
|
||||
|
||||
switch (priv->tuner) {
|
||||
case TUNER_RTL2832_FC2580:
|
||||
/* TODO: */
|
||||
fe = NULL;
|
||||
case TUNER_RTL2832_FC0012:
|
||||
fe = dvb_attach(fc0012_attach, adap->fe_adap[0].fe,
|
||||
&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;
|
||||
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:
|
||||
fe = NULL;
|
||||
err("unknown tuner=%d", priv->tuner);
|
||||
|
@ -551,14 +786,14 @@ err:
|
|||
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;
|
||||
u8 buf[2], gpio;
|
||||
|
||||
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)
|
||||
goto err;
|
||||
|
||||
|
@ -572,11 +807,11 @@ static int rtl28xxu_streaming_ctrl(struct dvb_usb_adapter *adap , int onoff)
|
|||
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)
|
||||
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)
|
||||
goto err;
|
||||
|
||||
|
@ -586,7 +821,33 @@ err:
|
|||
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;
|
||||
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);
|
||||
|
||||
/* demod adc */
|
||||
ret = rtl2831_rd_reg(d, SYS_SYS0, &sys0);
|
||||
ret = rtl28xx_rd_reg(d, SYS_SYS0, &sys0);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
/* 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)
|
||||
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);
|
||||
|
||||
/* demod adc */
|
||||
ret = rtl2831_wr_reg(d, SYS_SYS0, sys0);
|
||||
ret = rtl28xx_wr_reg(d, SYS_SYS0, sys0);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
/* 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)
|
||||
goto err;
|
||||
|
||||
|
@ -634,6 +895,128 @@ err:
|
|||
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)
|
||||
{
|
||||
int ret, i;
|
||||
|
@ -660,7 +1043,7 @@ static int rtl2831u_rc_query(struct dvb_usb_device *d)
|
|||
/* init remote controller */
|
||||
if (!priv->rc_active) {
|
||||
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);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
@ -690,12 +1073,12 @@ static int rtl2831u_rc_query(struct dvb_usb_device *d)
|
|||
|
||||
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)
|
||||
goto err;
|
||||
|
||||
/* 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)
|
||||
goto err;
|
||||
}
|
||||
|
@ -732,7 +1115,7 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d)
|
|||
/* init remote controller */
|
||||
if (!priv->rc_active) {
|
||||
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);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
@ -740,14 +1123,14 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d)
|
|||
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)
|
||||
goto err;
|
||||
|
||||
if (buf[0] != 0x83)
|
||||
goto exit;
|
||||
|
||||
ret = rtl2831_rd_reg(d, IR_RX_BC, &buf[0]);
|
||||
ret = rtl28xx_rd_reg(d, IR_RX_BC, &buf[0]);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
|
@ -756,9 +1139,9 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d)
|
|||
|
||||
/* TODO: pass raw IR to Kernel IR decoder */
|
||||
|
||||
ret = rtl2831_wr_reg(d, IR_RX_IF, 0x03);
|
||||
ret = rtl2831_wr_reg(d, IR_RX_BUF_CTRL, 0x80);
|
||||
ret = rtl2831_wr_reg(d, IR_RX_CTRL, 0x80);
|
||||
ret = rtl28xx_wr_reg(d, IR_RX_IF, 0x03);
|
||||
ret = rtl28xx_wr_reg(d, IR_RX_BUF_CTRL, 0x80);
|
||||
ret = rtl28xx_wr_reg(d, IR_RX_CTRL, 0x80);
|
||||
|
||||
exit:
|
||||
return ret;
|
||||
|
@ -771,6 +1154,9 @@ enum rtl28xxu_usb_table_entry {
|
|||
RTL2831U_0BDA_2831,
|
||||
RTL2831U_14AA_0160,
|
||||
RTL2831U_14AA_0161,
|
||||
RTL2832U_0CCD_00A9,
|
||||
RTL2832U_1F4D_B803,
|
||||
RTL2832U_0CCD_00B3,
|
||||
};
|
||||
|
||||
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)},
|
||||
|
||||
/* 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 */
|
||||
};
|
||||
|
||||
|
@ -805,7 +1197,7 @@ static struct dvb_usb_device_properties rtl28xxu_properties[] = {
|
|||
{
|
||||
.frontend_attach = rtl2831u_frontend_attach,
|
||||
.tuner_attach = rtl2831u_tuner_attach,
|
||||
.streaming_ctrl = rtl28xxu_streaming_ctrl,
|
||||
.streaming_ctrl = rtl2831u_streaming_ctrl,
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.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 = {
|
||||
.protocol = RC_TYPE_NEC,
|
||||
|
@ -867,7 +1259,7 @@ static struct dvb_usb_device_properties rtl28xxu_properties[] = {
|
|||
{
|
||||
.frontend_attach = rtl2832u_frontend_attach,
|
||||
.tuner_attach = rtl2832u_tuner_attach,
|
||||
.streaming_ctrl = rtl28xxu_streaming_ctrl,
|
||||
.streaming_ctrl = rtl2832u_streaming_ctrl,
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.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 = {
|
||||
.protocol = RC_TYPE_NEC,
|
||||
|
@ -896,10 +1288,25 @@ static struct dvb_usb_device_properties rtl28xxu_properties[] = {
|
|||
|
||||
.i2c_algo = &rtl28xxu_i2c_algo,
|
||||
|
||||
.num_device_descs = 0, /* disabled as no support for RTL2832 */
|
||||
.num_device_descs = 3,
|
||||
.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)
|
||||
{
|
||||
int ret, i;
|
||||
u8 val;
|
||||
int properties_count = ARRAY_SIZE(rtl28xxu_properties);
|
||||
struct dvb_usb_device *d;
|
||||
struct usb_device *udev;
|
||||
|
@ -954,16 +1362,25 @@ static int rtl28xxu_probe(struct usb_interface *intf,
|
|||
if (ret)
|
||||
goto err;
|
||||
|
||||
|
||||
/* 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)
|
||||
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)
|
||||
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)
|
||||
goto err;
|
||||
|
||||
|
@ -1007,4 +1424,5 @@ module_exit(rtl28xxu_module_exit);
|
|||
|
||||
MODULE_DESCRIPTION("Realtek RTL28xxU DVB USB driver");
|
||||
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
|
||||
MODULE_AUTHOR("Thomas Mair <thomas.mair86@googlemail.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
config DVB_FE_CUSTOMISE
|
||||
bool "Customise the frontend modules to build"
|
||||
depends on DVB_CORE
|
||||
depends on EXPERT
|
||||
default y if EXPERT
|
||||
help
|
||||
This allows the user to select/deselect frontend drivers for their
|
||||
|
@ -432,6 +433,13 @@ config DVB_RTL2830
|
|||
help
|
||||
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"
|
||||
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_TDA10071) += tda10071.o
|
||||
obj-$(CONFIG_DVB_RTL2830) += rtl2830.o
|
||||
obj-$(CONFIG_DVB_RTL2832) += rtl2832.o
|
||||
obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o
|
||||
obj-$(CONFIG_DVB_AF9033) += af9033.o
|
||||
|
||||
|
|
|
@ -21,24 +21,6 @@
|
|||
#include "dvb_frontend.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 i2c_adapter *i2c;
|
||||
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) {
|
||||
ret = 0;
|
||||
} 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;
|
||||
}
|
||||
|
||||
|
@ -88,7 +71,8 @@ static int a8293_set_voltage(struct dvb_frontend *fe,
|
|||
struct a8293_priv *priv = fe->sec_priv;
|
||||
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) {
|
||||
case SEC_VOLTAGE_OFF:
|
||||
|
@ -114,14 +98,12 @@ static int a8293_set_voltage(struct dvb_frontend *fe,
|
|||
|
||||
return ret;
|
||||
err:
|
||||
dbg("%s: failed=%d", __func__, ret);
|
||||
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void a8293_release_sec(struct dvb_frontend *fe)
|
||||
{
|
||||
dbg("%s:", __func__);
|
||||
|
||||
a8293_set_voltage(fe, SEC_VOLTAGE_OFF);
|
||||
|
||||
kfree(fe->sec_priv);
|
||||
|
@ -154,7 +136,7 @@ struct dvb_frontend *a8293_attach(struct dvb_frontend *fe,
|
|||
|
||||
/* ENB=0 */
|
||||
priv->reg[0] = 0x10;
|
||||
ret = a8293_wr(priv, &priv->reg[1], 1);
|
||||
ret = a8293_wr(priv, &priv->reg[0], 1);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
|
@ -164,16 +146,17 @@ struct dvb_frontend *a8293_attach(struct dvb_frontend *fe,
|
|||
if (ret)
|
||||
goto err;
|
||||
|
||||
info("Allegro A8293 SEC attached.");
|
||||
|
||||
fe->ops.release_sec = a8293_release_sec;
|
||||
|
||||
/* override frontend ops */
|
||||
fe->ops.set_voltage = a8293_set_voltage;
|
||||
|
||||
dev_info(&priv->i2c->dev, "%s: Allegro A8293 SEC attached\n",
|
||||
KBUILD_MODNAME);
|
||||
|
||||
return fe;
|
||||
err:
|
||||
dbg("%s: failed=%d", __func__, ret);
|
||||
dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||
kfree(priv);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,14 @@
|
|||
* means that 1=DVBC, 0 = DVBT. Zero means the opposite.
|
||||
* @mpeg_out_clk_strength: DRXK Mpeg output clock drive strength.
|
||||
* @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
|
||||
* UIO-3.
|
||||
|
@ -38,7 +46,8 @@ struct drxk_config {
|
|||
u8 mpeg_out_clk_strength;
|
||||
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) \
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/hardirq.h>
|
||||
#include <asm/div64.h>
|
||||
|
||||
#include "dvb_frontend.h"
|
||||
|
@ -308,16 +309,42 @@ static u32 Log10Times100(u32 x)
|
|||
/* 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,
|
||||
.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;
|
||||
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 "\n");
|
||||
}
|
||||
status = i2c_transfer(adap, &msg, 1);
|
||||
status = drxk_i2c_transfer(state, &msg, 1);
|
||||
if (status >= 0 && status != 1)
|
||||
status = -EIO;
|
||||
|
||||
|
@ -340,7 +367,7 @@ static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len)
|
|||
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)
|
||||
{
|
||||
int status;
|
||||
|
@ -351,7 +378,7 @@ static int i2c_read(struct i2c_adapter *adap,
|
|||
.buf = answ, .len = alen}
|
||||
};
|
||||
|
||||
status = i2c_transfer(adap, msgs, 2);
|
||||
status = drxk_i2c_transfer(state, msgs, 2);
|
||||
if (status != 2) {
|
||||
if (debug > 2)
|
||||
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;
|
||||
}
|
||||
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)
|
||||
return status;
|
||||
if (data)
|
||||
|
@ -428,7 +455,7 @@ static int read32_flags(struct drxk_state *state, u32 reg, u32 *data, u8 flags)
|
|||
len = 2;
|
||||
}
|
||||
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)
|
||||
return status;
|
||||
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;
|
||||
|
||||
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)
|
||||
|
@ -495,7 +522,7 @@ static int write32_flags(struct drxk_state *state, u32 reg, u32 data, u8 flags)
|
|||
mm[len + 3] = (data >> 24) & 0xff;
|
||||
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)
|
||||
|
@ -542,7 +569,7 @@ static int write_block(struct drxk_state *state, u32 Address,
|
|||
printk(KERN_CONT " %02x", pBlock[i]);
|
||||
printk(KERN_CONT "\n");
|
||||
}
|
||||
status = i2c_write(state->i2c, state->demod_address,
|
||||
status = i2c_write(state, state->demod_address,
|
||||
&state->Chunk[0], Chunk + AdrLength);
|
||||
if (status < 0) {
|
||||
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");
|
||||
|
||||
status = i2c_read1(state->i2c, state->demod_address, &data);
|
||||
status = i2c_read1(state, state->demod_address, &data);
|
||||
if (status < 0) {
|
||||
do {
|
||||
data = 0;
|
||||
status = i2c_write(state->i2c, state->demod_address,
|
||||
status = i2c_write(state, state->demod_address,
|
||||
&data, 1);
|
||||
msleep(10);
|
||||
retryCount++;
|
||||
if (status < 0)
|
||||
continue;
|
||||
status = i2c_read1(state->i2c, state->demod_address,
|
||||
status = i2c_read1(state, state->demod_address,
|
||||
&data);
|
||||
} while (status < 0 &&
|
||||
(retryCount < DRXK_MAX_RETRIES_POWERUP));
|
||||
|
@ -932,7 +959,7 @@ static int GetDeviceCapabilities(struct drxk_state *state)
|
|||
if (status < 0)
|
||||
goto error;
|
||||
|
||||
printk(KERN_ERR "drxk: status = 0x%08x\n", sioTopJtagidLo);
|
||||
printk(KERN_INFO "drxk: status = 0x%08x\n", sioTopJtagidLo);
|
||||
|
||||
/* driver 0.9.0 */
|
||||
switch ((sioTopJtagidLo >> 29) & 0xF) {
|
||||
|
@ -2824,7 +2851,7 @@ static int ConfigureI2CBridge(struct drxk_state *state, bool bEnableBridge)
|
|||
dprintk(1, "\n");
|
||||
|
||||
if (state->m_DrxkState == DRXK_UNINITIALIZED)
|
||||
goto error;
|
||||
return 0;
|
||||
if (state->m_DrxkState == DRXK_POWERED_DOWN)
|
||||
goto error;
|
||||
|
||||
|
@ -2977,7 +3004,7 @@ static int ADCSynchronization(struct drxk_state *state)
|
|||
status = read16(state, IQM_AF_CLKNEG__A, &clkNeg);
|
||||
if (status < 0)
|
||||
goto error;
|
||||
if ((clkNeg | IQM_AF_CLKNEG_CLKNEGDATA__M) ==
|
||||
if ((clkNeg & IQM_AF_CLKNEG_CLKNEGDATA__M) ==
|
||||
IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_POS) {
|
||||
clkNeg &= (~(IQM_AF_CLKNEG_CLKNEGDATA__M));
|
||||
clkNeg |=
|
||||
|
@ -5361,7 +5388,7 @@ static int GetQAMLockStatus(struct drxk_state *state, u32 *pLockStatus)
|
|||
SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK, 0, NULL, 2,
|
||||
Result);
|
||||
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) {
|
||||
/* 0x0000 NOT LOCKED */
|
||||
|
@ -5388,12 +5415,67 @@ static int GetQAMLockStatus(struct drxk_state *state, u32 *pLockStatus)
|
|||
#define QAM_LOCKRANGE__M 0x10
|
||||
#define QAM_LOCKRANGE_NORMAL 0x10
|
||||
|
||||
static int QAMDemodulatorCommand(struct drxk_state *state,
|
||||
int numberOfParameters)
|
||||
{
|
||||
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,
|
||||
s32 tunerFreqOffset)
|
||||
{
|
||||
int status;
|
||||
u16 setParamParameters[4] = { 0, 0, 0, 0 };
|
||||
u16 cmdResult;
|
||||
int qamDemodParamCount = state->qam_demod_parameter_count;
|
||||
|
||||
dprintk(1, "\n");
|
||||
/*
|
||||
|
@ -5445,34 +5527,42 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz,
|
|||
}
|
||||
if (status < 0)
|
||||
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);
|
||||
if (status < 0) {
|
||||
/* Fall-back to the simpler call */
|
||||
if (state->m_OperationMode == OM_QAM_ITU_C)
|
||||
setParamParameters[0] = QAM_TOP_ANNEX_C;
|
||||
else
|
||||
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);
|
||||
/* Use the 4-parameter if it's requested or we're probing for
|
||||
* the correct command. */
|
||||
if (state->qam_demod_parameter_count == 4
|
||||
|| !state->qam_demod_parameter_count) {
|
||||
qamDemodParamCount = 4;
|
||||
status = QAMDemodulatorCommand(state, qamDemodParamCount);
|
||||
}
|
||||
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;
|
||||
} 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
|
||||
|
@ -5968,34 +6058,15 @@ error:
|
|||
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)
|
||||
{
|
||||
int status = 0;
|
||||
int status = 0, n = 0;
|
||||
enum DRXPowerMode powerMode = DRXK_POWER_DOWN_OFDM;
|
||||
u16 driverVersion;
|
||||
|
||||
dprintk(1, "\n");
|
||||
if ((state->m_DrxkState == DRXK_UNINITIALIZED)) {
|
||||
drxk_i2c_lock(state);
|
||||
status = PowerUpDevice(state);
|
||||
if (status < 0)
|
||||
goto error;
|
||||
|
@ -6073,8 +6144,12 @@ static int init_drxk(struct drxk_state *state)
|
|||
if (status < 0)
|
||||
goto error;
|
||||
|
||||
if (state->microcode_name)
|
||||
load_microcode(state, state->microcode_name);
|
||||
if (state->fw) {
|
||||
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 */
|
||||
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;
|
||||
} else
|
||||
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:
|
||||
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__);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct drxk_state *state = fe->demodulator_priv;
|
||||
|
||||
dprintk(1, "\n");
|
||||
if (state->fw)
|
||||
release_firmware(state->fw);
|
||||
|
||||
kfree(state);
|
||||
}
|
||||
|
||||
|
@ -6188,6 +6315,12 @@ static int drxk_sleep(struct dvb_frontend *fe)
|
|||
struct drxk_state *state = fe->demodulator_priv;
|
||||
|
||||
dprintk(1, "\n");
|
||||
|
||||
if (state->m_DrxkState == DRXK_NO_DEV)
|
||||
return -ENODEV;
|
||||
if (state->m_DrxkState == DRXK_UNINITIALIZED)
|
||||
return 0;
|
||||
|
||||
ShutDown(state);
|
||||
return 0;
|
||||
}
|
||||
|
@ -6196,7 +6329,11 @@ static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
|
|||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -6209,6 +6346,12 @@ static int drxk_set_parameters(struct dvb_frontend *fe)
|
|||
|
||||
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) {
|
||||
printk(KERN_ERR
|
||||
"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;
|
||||
|
||||
dprintk(1, "\n");
|
||||
|
||||
if (state->m_DrxkState == DRXK_NO_DEV)
|
||||
return -ENODEV;
|
||||
if (state->m_DrxkState == DRXK_UNINITIALIZED)
|
||||
return -EAGAIN;
|
||||
|
||||
*status = 0;
|
||||
GetLockStatus(state, &stat, 0);
|
||||
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)
|
||||
{
|
||||
struct drxk_state *state = fe->demodulator_priv;
|
||||
|
||||
dprintk(1, "\n");
|
||||
|
||||
if (state->m_DrxkState == DRXK_NO_DEV)
|
||||
return -ENODEV;
|
||||
if (state->m_DrxkState == DRXK_UNINITIALIZED)
|
||||
return -EAGAIN;
|
||||
|
||||
*ber = 0;
|
||||
return 0;
|
||||
}
|
||||
|
@ -6288,6 +6444,12 @@ static int drxk_read_signal_strength(struct dvb_frontend *fe,
|
|||
u32 val = 0;
|
||||
|
||||
dprintk(1, "\n");
|
||||
|
||||
if (state->m_DrxkState == DRXK_NO_DEV)
|
||||
return -ENODEV;
|
||||
if (state->m_DrxkState == DRXK_UNINITIALIZED)
|
||||
return -EAGAIN;
|
||||
|
||||
ReadIFAgc(state, &val);
|
||||
*strength = val & 0xffff;
|
||||
return 0;
|
||||
|
@ -6299,6 +6461,12 @@ static int drxk_read_snr(struct dvb_frontend *fe, u16 *snr)
|
|||
s32 snr2;
|
||||
|
||||
dprintk(1, "\n");
|
||||
|
||||
if (state->m_DrxkState == DRXK_NO_DEV)
|
||||
return -ENODEV;
|
||||
if (state->m_DrxkState == DRXK_UNINITIALIZED)
|
||||
return -EAGAIN;
|
||||
|
||||
GetSignalToNoise(state, &snr2);
|
||||
*snr = snr2 & 0xffff;
|
||||
return 0;
|
||||
|
@ -6310,6 +6478,12 @@ static int drxk_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
|
|||
u16 err;
|
||||
|
||||
dprintk(1, "\n");
|
||||
|
||||
if (state->m_DrxkState == DRXK_NO_DEV)
|
||||
return -ENODEV;
|
||||
if (state->m_DrxkState == DRXK_UNINITIALIZED)
|
||||
return -EAGAIN;
|
||||
|
||||
DVBTQAMGetAccPktErr(state, &err);
|
||||
*ucblocks = (u32) err;
|
||||
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
|
||||
*sets)
|
||||
{
|
||||
struct drxk_state *state = fe->demodulator_priv;
|
||||
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
|
||||
|
||||
dprintk(1, "\n");
|
||||
|
||||
if (state->m_DrxkState == DRXK_NO_DEV)
|
||||
return -ENODEV;
|
||||
if (state->m_DrxkState == DRXK_UNINITIALIZED)
|
||||
return -EAGAIN;
|
||||
|
||||
switch (p->delivery_system) {
|
||||
case SYS_DVBC_ANNEX_A:
|
||||
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 i2c_adapter *i2c)
|
||||
{
|
||||
int n;
|
||||
|
||||
struct drxk_state *state = NULL;
|
||||
u8 adr = config->adr;
|
||||
int status;
|
||||
|
||||
dprintk(1, "\n");
|
||||
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->single_master = config->single_master;
|
||||
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->antenna_gpio = config->antenna_gpio;
|
||||
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;
|
||||
|
||||
init_state(state);
|
||||
if (init_drxk(state) < 0)
|
||||
goto error;
|
||||
|
||||
/* 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));
|
||||
}
|
||||
/* Load firmware and initialize DRX-K */
|
||||
if (state->microcode_name) {
|
||||
status = request_firmware_nowait(THIS_MODULE, 1,
|
||||
state->microcode_name,
|
||||
state->i2c->dev.parent,
|
||||
GFP_KERNEL,
|
||||
state, load_firmware_cb);
|
||||
if (status < 0) {
|
||||
printk(KERN_ERR
|
||||
"drxk: failed to request a firmware\n");
|
||||
return NULL;
|
||||
}
|
||||
} else if (init_drxk(state) < 0)
|
||||
goto error;
|
||||
|
||||
printk(KERN_INFO "drxk: frontend initialized.\n");
|
||||
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 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 {
|
||||
DRXK_COEF_IDX_MN = 0,
|
||||
DRXK_COEF_IDX_FM ,
|
||||
|
@ -325,6 +333,9 @@ struct drxk_state {
|
|||
|
||||
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
|
||||
* at struct drxk_config.
|
||||
|
@ -338,7 +349,11 @@ struct drxk_state {
|
|||
bool antenna_dvbt;
|
||||
u16 antenna_gpio;
|
||||
|
||||
/* Firmware */
|
||||
const char *microcode_name;
|
||||
struct completion fw_wait_load;
|
||||
const struct firmware *fw;
|
||||
int qam_demod_parameter_count;
|
||||
};
|
||||
|
||||
#define NEVER_LOCK 0
|
||||
|
|
789
drivers/media/dvb/frontends/rtl2832.c
Normal file
789
drivers/media/dvb/frontends/rtl2832.c
Normal file
|
@ -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");
|
74
drivers/media/dvb/frontends/rtl2832.h
Normal file
74
drivers/media/dvb/frontends/rtl2832.h
Normal file
|
@ -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 */
|
260
drivers/media/dvb/frontends/rtl2832_priv.h
Normal file
260
drivers/media/dvb/frontends/rtl2832_priv.h
Normal file
|
@ -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;
|
||||
int frequency_delta;
|
||||
struct dvb_frontend_tune_settings fesettings;
|
||||
uint8_t clock_setting;
|
||||
|
||||
dprintk("enter %s\n", __func__);
|
||||
|
||||
|
@ -679,25 +678,6 @@ static int s5h1420_set_frontend(struct dvb_frontend *fe)
|
|||
else
|
||||
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));
|
||||
s5h1420_writereg(state, PLL01, state->fclk/1000000 - 8);
|
||||
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;
|
||||
|
||||
u8 lsb, msb;
|
||||
u32 i;
|
||||
|
||||
*ber = 0;
|
||||
|
||||
|
@ -1137,14 +1136,9 @@ static int stb0899_read_ber(struct dvb_frontend *fe, u32 *ber)
|
|||
case SYS_DVBS:
|
||||
case SYS_DSS:
|
||||
if (internal->lock) {
|
||||
/* average 5 BER values */
|
||||
for (i = 0; i < 5; i++) {
|
||||
msleep(100);
|
||||
lsb = stb0899_read_reg(state, STB0899_ECNT1L);
|
||||
msb = stb0899_read_reg(state, STB0899_ECNT1M);
|
||||
*ber += MAKEWORD16(msb, lsb);
|
||||
}
|
||||
*ber /= 5;
|
||||
lsb = stb0899_read_reg(state, STB0899_ECNT1L);
|
||||
msb = stb0899_read_reg(state, STB0899_ECNT1M);
|
||||
*ber = MAKEWORD16(msb, lsb);
|
||||
/* Viterbi Check */
|
||||
if (STB0899_GETFIELD(VSTATUS_PRFVIT, internal->v_status)) {
|
||||
/* Error Rate */
|
||||
|
@ -1157,13 +1151,9 @@ static int stb0899_read_ber(struct dvb_frontend *fe, u32 *ber)
|
|||
break;
|
||||
case SYS_DVBS2:
|
||||
if (internal->lock) {
|
||||
/* Average 5 PER values */
|
||||
for (i = 0; i < 5; i++) {
|
||||
msleep(100);
|
||||
lsb = stb0899_read_reg(state, STB0899_ECNT1L);
|
||||
msb = stb0899_read_reg(state, STB0899_ECNT1M);
|
||||
*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 *= 10000000;
|
||||
*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;
|
||||
int offset = 0, tempo = 0;
|
||||
u8 u_var;
|
||||
u8 /*constell,*/ counter, tps_rcvd[2];
|
||||
u8 /*constell,*/ counter;
|
||||
s8 step;
|
||||
s32 timing_offset = 0;
|
||||
u32 trl_nomrate = 0, InternalFreq = 0, temp = 0;
|
||||
|
@ -1709,9 +1709,6 @@ static int stv0367ter_algo(struct dvb_frontend *fe)
|
|||
return 0;
|
||||
|
||||
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->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;
|
||||
u32 reg;
|
||||
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);
|
||||
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;
|
||||
} else {
|
||||
signal_state = STV090x_NODATA;
|
||||
no_signal = stv090x_chk_signal(state);
|
||||
stv090x_chk_signal(state);
|
||||
}
|
||||
}
|
||||
return signal_state;
|
||||
|
|
|
@ -20,10 +20,6 @@
|
|||
|
||||
#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;
|
||||
|
||||
/* write multiple registers */
|
||||
|
@ -48,7 +44,8 @@ static int tda10071_wr_regs(struct tda10071_priv *priv, u8 reg, u8 *val,
|
|||
if (ret == 1) {
|
||||
ret = 0;
|
||||
} 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;
|
||||
}
|
||||
return ret;
|
||||
|
@ -79,7 +76,8 @@ static int tda10071_rd_regs(struct tda10071_priv *priv, u8 reg, u8 *val,
|
|||
memcpy(val, buf, len);
|
||||
ret = 0;
|
||||
} 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;
|
||||
}
|
||||
return ret;
|
||||
|
@ -170,7 +168,7 @@ static int tda10071_cmd_execute(struct tda10071_priv *priv,
|
|||
usleep_range(200, 5000);
|
||||
}
|
||||
|
||||
dbg("%s: loop=%d", __func__, i);
|
||||
dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i);
|
||||
|
||||
if (i == 0) {
|
||||
ret = -ETIMEDOUT;
|
||||
|
@ -179,7 +177,7 @@ static int tda10071_cmd_execute(struct tda10071_priv *priv,
|
|||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed=%d", __func__, ret);
|
||||
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -196,7 +194,8 @@ static int tda10071_set_tone(struct dvb_frontend *fe,
|
|||
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) {
|
||||
case SEC_TONE_ON:
|
||||
|
@ -206,24 +205,25 @@ static int tda10071_set_tone(struct dvb_frontend *fe,
|
|||
tone = 0;
|
||||
break;
|
||||
default:
|
||||
dbg("%s: invalid fe_sec_tone_mode", __func__);
|
||||
dev_dbg(&priv->i2c->dev, "%s: invalid fe_sec_tone_mode\n",
|
||||
__func__);
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
cmd.args[0x00] = CMD_LNB_PCB_CONFIG;
|
||||
cmd.args[0x01] = 0;
|
||||
cmd.args[0x02] = 0x00;
|
||||
cmd.args[0x03] = 0x00;
|
||||
cmd.args[0x04] = tone;
|
||||
cmd.len = 0x05;
|
||||
cmd.args[0] = CMD_LNB_PCB_CONFIG;
|
||||
cmd.args[1] = 0;
|
||||
cmd.args[2] = 0x00;
|
||||
cmd.args[3] = 0x00;
|
||||
cmd.args[4] = tone;
|
||||
cmd.len = 5;
|
||||
ret = tda10071_cmd_execute(priv, &cmd);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed=%d", __func__, ret);
|
||||
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -240,7 +240,7 @@ static int tda10071_set_voltage(struct dvb_frontend *fe,
|
|||
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) {
|
||||
case SEC_VOLTAGE_13:
|
||||
|
@ -253,22 +253,23 @@ static int tda10071_set_voltage(struct dvb_frontend *fe,
|
|||
voltage = 0;
|
||||
break;
|
||||
default:
|
||||
dbg("%s: invalid fe_sec_voltage", __func__);
|
||||
dev_dbg(&priv->i2c->dev, "%s: invalid fe_sec_voltage\n",
|
||||
__func__);
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
};
|
||||
|
||||
cmd.args[0x00] = CMD_LNB_SET_DC_LEVEL;
|
||||
cmd.args[0x01] = 0;
|
||||
cmd.args[0x02] = voltage;
|
||||
cmd.len = 0x03;
|
||||
cmd.args[0] = CMD_LNB_SET_DC_LEVEL;
|
||||
cmd.args[1] = 0;
|
||||
cmd.args[2] = voltage;
|
||||
cmd.len = 3;
|
||||
ret = tda10071_cmd_execute(priv, &cmd);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed=%d", __func__, ret);
|
||||
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -285,9 +286,10 @@ static int tda10071_diseqc_send_master_cmd(struct dvb_frontend *fe,
|
|||
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;
|
||||
goto error;
|
||||
}
|
||||
|
@ -301,7 +303,7 @@ static int tda10071_diseqc_send_master_cmd(struct dvb_frontend *fe,
|
|||
usleep_range(10000, 20000);
|
||||
}
|
||||
|
||||
dbg("%s: loop=%d", __func__, i);
|
||||
dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i);
|
||||
|
||||
if (i == 0) {
|
||||
ret = -ETIMEDOUT;
|
||||
|
@ -312,22 +314,22 @@ static int tda10071_diseqc_send_master_cmd(struct dvb_frontend *fe,
|
|||
if (ret)
|
||||
goto error;
|
||||
|
||||
cmd.args[0x00] = CMD_LNB_SEND_DISEQC;
|
||||
cmd.args[0x01] = 0;
|
||||
cmd.args[0x02] = 0;
|
||||
cmd.args[0x03] = 0;
|
||||
cmd.args[0x04] = 2;
|
||||
cmd.args[0x05] = 0;
|
||||
cmd.args[0x06] = diseqc_cmd->msg_len;
|
||||
memcpy(&cmd.args[0x07], diseqc_cmd->msg, diseqc_cmd->msg_len);
|
||||
cmd.len = 0x07 + diseqc_cmd->msg_len;
|
||||
cmd.args[0] = CMD_LNB_SEND_DISEQC;
|
||||
cmd.args[1] = 0;
|
||||
cmd.args[2] = 0;
|
||||
cmd.args[3] = 0;
|
||||
cmd.args[4] = 2;
|
||||
cmd.args[5] = 0;
|
||||
cmd.args[6] = diseqc_cmd->msg_len;
|
||||
memcpy(&cmd.args[7], diseqc_cmd->msg, diseqc_cmd->msg_len);
|
||||
cmd.len = 7 + diseqc_cmd->msg_len;
|
||||
ret = tda10071_cmd_execute(priv, &cmd);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed=%d", __func__, ret);
|
||||
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -344,7 +346,7 @@ static int tda10071_diseqc_recv_slave_reply(struct dvb_frontend *fe,
|
|||
goto error;
|
||||
}
|
||||
|
||||
dbg("%s:", __func__);
|
||||
dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
|
||||
|
||||
/* wait LNB RX */
|
||||
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);
|
||||
}
|
||||
|
||||
dbg("%s: loop=%d", __func__, i);
|
||||
dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i);
|
||||
|
||||
if (i == 0) {
|
||||
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 */
|
||||
|
||||
/* read reply */
|
||||
cmd.args[0x00] = CMD_LNB_UPDATE_REPLY;
|
||||
cmd.args[0x01] = 0;
|
||||
cmd.len = 0x02;
|
||||
cmd.args[0] = CMD_LNB_UPDATE_REPLY;
|
||||
cmd.args[1] = 0;
|
||||
cmd.len = 2;
|
||||
ret = tda10071_cmd_execute(priv, &cmd);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
@ -385,7 +387,7 @@ static int tda10071_diseqc_recv_slave_reply(struct dvb_frontend *fe,
|
|||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed=%d", __func__, ret);
|
||||
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -402,7 +404,8 @@ static int tda10071_diseqc_send_burst(struct dvb_frontend *fe,
|
|||
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) {
|
||||
case SEC_MINI_A:
|
||||
|
@ -412,7 +415,8 @@ static int tda10071_diseqc_send_burst(struct dvb_frontend *fe,
|
|||
burst = 1;
|
||||
break;
|
||||
default:
|
||||
dbg("%s: invalid fe_sec_mini_cmd", __func__);
|
||||
dev_dbg(&priv->i2c->dev, "%s: invalid fe_sec_mini_cmd\n",
|
||||
__func__);
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
@ -426,7 +430,7 @@ static int tda10071_diseqc_send_burst(struct dvb_frontend *fe,
|
|||
usleep_range(10000, 20000);
|
||||
}
|
||||
|
||||
dbg("%s: loop=%d", __func__, i);
|
||||
dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i);
|
||||
|
||||
if (i == 0) {
|
||||
ret = -ETIMEDOUT;
|
||||
|
@ -437,17 +441,17 @@ static int tda10071_diseqc_send_burst(struct dvb_frontend *fe,
|
|||
if (ret)
|
||||
goto error;
|
||||
|
||||
cmd.args[0x00] = CMD_LNB_SEND_TONEBURST;
|
||||
cmd.args[0x01] = 0;
|
||||
cmd.args[0x02] = burst;
|
||||
cmd.len = 0x03;
|
||||
cmd.args[0] = CMD_LNB_SEND_TONEBURST;
|
||||
cmd.args[1] = 0;
|
||||
cmd.args[2] = burst;
|
||||
cmd.len = 3;
|
||||
ret = tda10071_cmd_execute(priv, &cmd);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed=%d", __func__, ret);
|
||||
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -481,7 +485,7 @@ static int tda10071_read_status(struct dvb_frontend *fe, fe_status_t *status)
|
|||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed=%d", __func__, ret);
|
||||
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -506,7 +510,7 @@ static int tda10071_read_snr(struct dvb_frontend *fe, u16 *snr)
|
|||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed=%d", __func__, ret);
|
||||
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -523,9 +527,9 @@ static int tda10071_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
|
|||
goto error;
|
||||
}
|
||||
|
||||
cmd.args[0x00] = CMD_GET_AGCACC;
|
||||
cmd.args[0x01] = 0;
|
||||
cmd.len = 0x02;
|
||||
cmd.args[0] = CMD_GET_AGCACC;
|
||||
cmd.args[1] = 0;
|
||||
cmd.len = 2;
|
||||
ret = tda10071_cmd_execute(priv, &cmd);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
@ -545,7 +549,7 @@ static int tda10071_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
|
|||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed=%d", __func__, ret);
|
||||
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -583,17 +587,18 @@ static int tda10071_read_ber(struct dvb_frontend *fe, u32 *ber)
|
|||
goto error;
|
||||
|
||||
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;
|
||||
return 0;
|
||||
} else {
|
||||
priv->meas_count[i] = tmp;
|
||||
}
|
||||
|
||||
cmd.args[0x00] = CMD_BER_UPDATE_COUNTERS;
|
||||
cmd.args[0x01] = 0;
|
||||
cmd.args[0x02] = i;
|
||||
cmd.len = 0x03;
|
||||
cmd.args[0] = CMD_BER_UPDATE_COUNTERS;
|
||||
cmd.args[1] = 0;
|
||||
cmd.args[2] = i;
|
||||
cmd.len = 3;
|
||||
ret = tda10071_cmd_execute(priv, &cmd);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
@ -612,7 +617,7 @@ static int tda10071_read_ber(struct dvb_frontend *fe, u32 *ber)
|
|||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed=%d", __func__, ret);
|
||||
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -632,7 +637,7 @@ static int tda10071_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
|
|||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed=%d", __func__, ret);
|
||||
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -644,10 +649,11 @@ static int tda10071_set_frontend(struct dvb_frontend *fe)
|
|||
int ret, i;
|
||||
u8 mode, rolloff, pilot, inversion, div;
|
||||
|
||||
dbg("%s: delivery_system=%d modulation=%d frequency=%d " \
|
||||
"symbol_rate=%d inversion=%d pilot=%d rolloff=%d", __func__,
|
||||
c->delivery_system, c->modulation, c->frequency,
|
||||
c->symbol_rate, c->inversion, c->pilot, c->rolloff);
|
||||
dev_dbg(&priv->i2c->dev, "%s: delivery_system=%d modulation=%d " \
|
||||
"frequency=%d symbol_rate=%d inversion=%d pilot=%d " \
|
||||
"rolloff=%d\n", __func__, c->delivery_system, c->modulation,
|
||||
c->frequency, c->symbol_rate, c->inversion, c->pilot,
|
||||
c->rolloff);
|
||||
|
||||
priv->delivery_system = SYS_UNDEFINED;
|
||||
|
||||
|
@ -669,7 +675,7 @@ static int tda10071_set_frontend(struct dvb_frontend *fe)
|
|||
inversion = 3;
|
||||
break;
|
||||
default:
|
||||
dbg("%s: invalid inversion", __func__);
|
||||
dev_dbg(&priv->i2c->dev, "%s: invalid inversion\n", __func__);
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
@ -692,7 +698,8 @@ static int tda10071_set_frontend(struct dvb_frontend *fe)
|
|||
break;
|
||||
case ROLLOFF_AUTO:
|
||||
default:
|
||||
dbg("%s: invalid rolloff", __func__);
|
||||
dev_dbg(&priv->i2c->dev, "%s: invalid rolloff\n",
|
||||
__func__);
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
@ -708,13 +715,15 @@ static int tda10071_set_frontend(struct dvb_frontend *fe)
|
|||
pilot = 2;
|
||||
break;
|
||||
default:
|
||||
dbg("%s: invalid pilot", __func__);
|
||||
dev_dbg(&priv->i2c->dev, "%s: invalid pilot\n",
|
||||
__func__);
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dbg("%s: invalid delivery_system", __func__);
|
||||
dev_dbg(&priv->i2c->dev, "%s: invalid delivery_system\n",
|
||||
__func__);
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
@ -724,13 +733,15 @@ static int tda10071_set_frontend(struct dvb_frontend *fe)
|
|||
c->modulation == TDA10071_MODCOD[i].modulation &&
|
||||
c->fec_inner == TDA10071_MODCOD[i].fec) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (mode == 0xff) {
|
||||
dbg("%s: invalid parameter combination", __func__);
|
||||
dev_dbg(&priv->i2c->dev, "%s: invalid parameter combination\n",
|
||||
__func__);
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
@ -748,22 +759,22 @@ static int tda10071_set_frontend(struct dvb_frontend *fe)
|
|||
if (ret)
|
||||
goto error;
|
||||
|
||||
cmd.args[0x00] = CMD_CHANGE_CHANNEL;
|
||||
cmd.args[0x01] = 0;
|
||||
cmd.args[0x02] = mode;
|
||||
cmd.args[0x03] = (c->frequency >> 16) & 0xff;
|
||||
cmd.args[0x04] = (c->frequency >> 8) & 0xff;
|
||||
cmd.args[0x05] = (c->frequency >> 0) & 0xff;
|
||||
cmd.args[0x06] = ((c->symbol_rate / 1000) >> 8) & 0xff;
|
||||
cmd.args[0x07] = ((c->symbol_rate / 1000) >> 0) & 0xff;
|
||||
cmd.args[0x08] = (tda10071_ops.info.frequency_tolerance >> 8) & 0xff;
|
||||
cmd.args[0x09] = (tda10071_ops.info.frequency_tolerance >> 0) & 0xff;
|
||||
cmd.args[0x0a] = rolloff;
|
||||
cmd.args[0x0b] = inversion;
|
||||
cmd.args[0x0c] = pilot;
|
||||
cmd.args[0x0d] = 0x00;
|
||||
cmd.args[0x0e] = 0x00;
|
||||
cmd.len = 0x0f;
|
||||
cmd.args[0] = CMD_CHANGE_CHANNEL;
|
||||
cmd.args[1] = 0;
|
||||
cmd.args[2] = mode;
|
||||
cmd.args[3] = (c->frequency >> 16) & 0xff;
|
||||
cmd.args[4] = (c->frequency >> 8) & 0xff;
|
||||
cmd.args[5] = (c->frequency >> 0) & 0xff;
|
||||
cmd.args[6] = ((c->symbol_rate / 1000) >> 8) & 0xff;
|
||||
cmd.args[7] = ((c->symbol_rate / 1000) >> 0) & 0xff;
|
||||
cmd.args[8] = (tda10071_ops.info.frequency_tolerance >> 8) & 0xff;
|
||||
cmd.args[9] = (tda10071_ops.info.frequency_tolerance >> 0) & 0xff;
|
||||
cmd.args[10] = rolloff;
|
||||
cmd.args[11] = inversion;
|
||||
cmd.args[12] = pilot;
|
||||
cmd.args[13] = 0x00;
|
||||
cmd.args[14] = 0x00;
|
||||
cmd.len = 15;
|
||||
ret = tda10071_cmd_execute(priv, &cmd);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
@ -772,7 +783,7 @@ static int tda10071_set_frontend(struct dvb_frontend *fe)
|
|||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed=%d", __func__, ret);
|
||||
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -829,7 +840,7 @@ static int tda10071_get_frontend(struct dvb_frontend *fe)
|
|||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed=%d", __func__, ret);
|
||||
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -915,10 +926,10 @@ static int tda10071_init(struct dvb_frontend *fe)
|
|||
goto error;
|
||||
}
|
||||
|
||||
cmd.args[0x00] = CMD_SET_SLEEP_MODE;
|
||||
cmd.args[0x01] = 0;
|
||||
cmd.args[0x02] = 0;
|
||||
cmd.len = 0x03;
|
||||
cmd.args[0] = CMD_SET_SLEEP_MODE;
|
||||
cmd.args[1] = 0;
|
||||
cmd.args[2] = 0;
|
||||
cmd.len = 3;
|
||||
ret = tda10071_cmd_execute(priv, &cmd);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
@ -929,10 +940,11 @@ static int tda10071_init(struct dvb_frontend *fe)
|
|||
/* request the firmware, this will block and timeout */
|
||||
ret = request_firmware(&fw, fw_file, priv->i2c->dev.parent);
|
||||
if (ret) {
|
||||
err("did not find the firmware file. (%s) "
|
||||
"Please see linux/Documentation/dvb/ for more" \
|
||||
" details on firmware-problems. (%d)",
|
||||
fw_file, ret);
|
||||
dev_err(&priv->i2c->dev, "%s: did not find the " \
|
||||
"firmware file. (%s) Please see " \
|
||||
"linux/Documentation/dvb/ for more " \
|
||||
"details on firmware-problems. (%d)\n",
|
||||
KBUILD_MODNAME, fw_file, ret);
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -961,10 +973,11 @@ static int tda10071_init(struct dvb_frontend *fe)
|
|||
if (ret)
|
||||
goto error_release_firmware;
|
||||
|
||||
info("found a '%s' in cold state, will try to load a firmware",
|
||||
tda10071_ops.info.name);
|
||||
|
||||
info("downloading firmware from file '%s'", fw_file);
|
||||
dev_info(&priv->i2c->dev, "%s: found a '%s' in cold state, " \
|
||||
"will try to load a firmware\n", KBUILD_MODNAME,
|
||||
tda10071_ops.info.name);
|
||||
dev_info(&priv->i2c->dev, "%s: downloading firmware from " \
|
||||
"file '%s'\n", KBUILD_MODNAME, fw_file);
|
||||
|
||||
/* do not download last byte */
|
||||
fw_size = fw->size - 1;
|
||||
|
@ -978,7 +991,9 @@ static int tda10071_init(struct dvb_frontend *fe)
|
|||
ret = tda10071_wr_regs(priv, 0xfa,
|
||||
(u8 *) &fw->data[fw_size - remaining], len);
|
||||
if (ret) {
|
||||
err("firmware download failed=%d", ret);
|
||||
dev_err(&priv->i2c->dev, "%s: firmware " \
|
||||
"download failed=%d\n",
|
||||
KBUILD_MODNAME, ret);
|
||||
if (ret)
|
||||
goto error_release_firmware;
|
||||
}
|
||||
|
@ -1002,15 +1017,16 @@ static int tda10071_init(struct dvb_frontend *fe)
|
|||
goto error;
|
||||
|
||||
if (tmp) {
|
||||
info("firmware did not run");
|
||||
dev_info(&priv->i2c->dev, "%s: firmware did not run\n",
|
||||
KBUILD_MODNAME);
|
||||
ret = -EFAULT;
|
||||
goto error;
|
||||
} else {
|
||||
priv->warm = 1;
|
||||
}
|
||||
|
||||
cmd.args[0x00] = CMD_GET_FW_VERSION;
|
||||
cmd.len = 0x01;
|
||||
cmd.args[0] = CMD_GET_FW_VERSION;
|
||||
cmd.len = 1;
|
||||
ret = tda10071_cmd_execute(priv, &cmd);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
@ -1019,54 +1035,55 @@ static int tda10071_init(struct dvb_frontend *fe)
|
|||
if (ret)
|
||||
goto error;
|
||||
|
||||
info("firmware version %d.%d.%d.%d",
|
||||
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: firmware version %d.%d.%d.%d\n",
|
||||
KBUILD_MODNAME, buf[0], buf[1], buf[2], buf[3]);
|
||||
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);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
cmd.args[0x00] = CMD_DEMOD_INIT;
|
||||
cmd.args[0x01] = ((priv->cfg.xtal / 1000) >> 8) & 0xff;
|
||||
cmd.args[0x02] = ((priv->cfg.xtal / 1000) >> 0) & 0xff;
|
||||
cmd.args[0x03] = buf[0];
|
||||
cmd.args[0x04] = buf[1];
|
||||
cmd.args[0x05] = priv->cfg.pll_multiplier;
|
||||
cmd.args[0x06] = priv->cfg.spec_inv;
|
||||
cmd.args[0x07] = 0x00;
|
||||
cmd.len = 0x08;
|
||||
cmd.args[0] = CMD_DEMOD_INIT;
|
||||
cmd.args[1] = ((priv->cfg.xtal / 1000) >> 8) & 0xff;
|
||||
cmd.args[2] = ((priv->cfg.xtal / 1000) >> 0) & 0xff;
|
||||
cmd.args[3] = buf[0];
|
||||
cmd.args[4] = buf[1];
|
||||
cmd.args[5] = priv->cfg.pll_multiplier;
|
||||
cmd.args[6] = priv->cfg.spec_inv;
|
||||
cmd.args[7] = 0x00;
|
||||
cmd.len = 8;
|
||||
ret = tda10071_cmd_execute(priv, &cmd);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
cmd.args[0x00] = CMD_TUNER_INIT;
|
||||
cmd.args[0x01] = 0x00;
|
||||
cmd.args[0x02] = 0x00;
|
||||
cmd.args[0x03] = 0x00;
|
||||
cmd.args[0x04] = 0x00;
|
||||
cmd.args[0x05] = 0x14;
|
||||
cmd.args[0x06] = 0x00;
|
||||
cmd.args[0x07] = 0x03;
|
||||
cmd.args[0x08] = 0x02;
|
||||
cmd.args[0x09] = 0x02;
|
||||
cmd.args[0x0a] = 0x00;
|
||||
cmd.args[0x0b] = 0x00;
|
||||
cmd.args[0x0c] = 0x00;
|
||||
cmd.args[0x0d] = 0x00;
|
||||
cmd.args[0x0e] = 0x00;
|
||||
cmd.len = 0x0f;
|
||||
cmd.args[0] = CMD_TUNER_INIT;
|
||||
cmd.args[1] = 0x00;
|
||||
cmd.args[2] = 0x00;
|
||||
cmd.args[3] = 0x00;
|
||||
cmd.args[4] = 0x00;
|
||||
cmd.args[5] = 0x14;
|
||||
cmd.args[6] = 0x00;
|
||||
cmd.args[7] = 0x03;
|
||||
cmd.args[8] = 0x02;
|
||||
cmd.args[9] = 0x02;
|
||||
cmd.args[10] = 0x00;
|
||||
cmd.args[11] = 0x00;
|
||||
cmd.args[12] = 0x00;
|
||||
cmd.args[13] = 0x00;
|
||||
cmd.args[14] = 0x00;
|
||||
cmd.len = 15;
|
||||
ret = tda10071_cmd_execute(priv, &cmd);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
cmd.args[0x00] = CMD_MPEG_CONFIG;
|
||||
cmd.args[0x01] = 0;
|
||||
cmd.args[0x02] = priv->cfg.ts_mode;
|
||||
cmd.args[0x03] = 0x00;
|
||||
cmd.args[0x04] = 0x04;
|
||||
cmd.args[0x05] = 0x00;
|
||||
cmd.len = 0x06;
|
||||
cmd.args[0] = CMD_MPEG_CONFIG;
|
||||
cmd.args[1] = 0;
|
||||
cmd.args[2] = priv->cfg.ts_mode;
|
||||
cmd.args[3] = 0x00;
|
||||
cmd.args[4] = 0x04;
|
||||
cmd.args[5] = 0x00;
|
||||
cmd.len = 6;
|
||||
ret = tda10071_cmd_execute(priv, &cmd);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
@ -1075,27 +1092,27 @@ static int tda10071_init(struct dvb_frontend *fe)
|
|||
if (ret)
|
||||
goto error;
|
||||
|
||||
cmd.args[0x00] = CMD_LNB_CONFIG;
|
||||
cmd.args[0x01] = 0;
|
||||
cmd.args[0x02] = 150;
|
||||
cmd.args[0x03] = 3;
|
||||
cmd.args[0x04] = 22;
|
||||
cmd.args[0x05] = 1;
|
||||
cmd.args[0x06] = 1;
|
||||
cmd.args[0x07] = 30;
|
||||
cmd.args[0x08] = 30;
|
||||
cmd.args[0x09] = 30;
|
||||
cmd.args[0x0a] = 30;
|
||||
cmd.len = 0x0b;
|
||||
cmd.args[0] = CMD_LNB_CONFIG;
|
||||
cmd.args[1] = 0;
|
||||
cmd.args[2] = 150;
|
||||
cmd.args[3] = 3;
|
||||
cmd.args[4] = 22;
|
||||
cmd.args[5] = 1;
|
||||
cmd.args[6] = 1;
|
||||
cmd.args[7] = 30;
|
||||
cmd.args[8] = 30;
|
||||
cmd.args[9] = 30;
|
||||
cmd.args[10] = 30;
|
||||
cmd.len = 11;
|
||||
ret = tda10071_cmd_execute(priv, &cmd);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
cmd.args[0x00] = CMD_BER_CONTROL;
|
||||
cmd.args[0x01] = 0;
|
||||
cmd.args[0x02] = 14;
|
||||
cmd.args[0x03] = 14;
|
||||
cmd.len = 0x04;
|
||||
cmd.args[0] = CMD_BER_CONTROL;
|
||||
cmd.args[1] = 0;
|
||||
cmd.args[2] = 14;
|
||||
cmd.args[3] = 14;
|
||||
cmd.len = 4;
|
||||
ret = tda10071_cmd_execute(priv, &cmd);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
@ -1105,7 +1122,7 @@ static int tda10071_init(struct dvb_frontend *fe)
|
|||
error_release_firmware:
|
||||
release_firmware(fw);
|
||||
error:
|
||||
dbg("%s: failed=%d", __func__, ret);
|
||||
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1132,10 +1149,10 @@ static int tda10071_sleep(struct dvb_frontend *fe)
|
|||
goto error;
|
||||
}
|
||||
|
||||
cmd.args[0x00] = CMD_SET_SLEEP_MODE;
|
||||
cmd.args[0x01] = 0;
|
||||
cmd.args[0x02] = 1;
|
||||
cmd.len = 0x03;
|
||||
cmd.args[0] = CMD_SET_SLEEP_MODE;
|
||||
cmd.args[1] = 0;
|
||||
cmd.args[2] = 1;
|
||||
cmd.len = 3;
|
||||
ret = tda10071_cmd_execute(priv, &cmd);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
@ -1149,7 +1166,7 @@ static int tda10071_sleep(struct dvb_frontend *fe)
|
|||
|
||||
return ret;
|
||||
error:
|
||||
dbg("%s: failed=%d", __func__, ret);
|
||||
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1208,7 +1225,7 @@ struct dvb_frontend *tda10071_attach(const struct tda10071_config *config,
|
|||
|
||||
return &priv->fe;
|
||||
error:
|
||||
dbg("%s: failed=%d", __func__, ret);
|
||||
dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret);
|
||||
kfree(priv);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -25,19 +25,6 @@
|
|||
#include "tda10071.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 i2c_adapter *i2c;
|
||||
struct dvb_frontend fe;
|
||||
|
@ -112,7 +99,7 @@ struct tda10071_reg_val_mask {
|
|||
#define CMD_BER_UPDATE_COUNTERS 0x3f
|
||||
|
||||
/* firmare command struct */
|
||||
#define TDA10071_ARGLEN 0x1e
|
||||
#define TDA10071_ARGLEN 30
|
||||
struct tda10071_cmd {
|
||||
u8 args[TDA10071_ARGLEN];
|
||||
u8 len;
|
||||
|
|
|
@ -217,6 +217,7 @@ static int demod_attach_drxk(struct ngene_channel *chan,
|
|||
|
||||
memset(&config, 0, sizeof(config));
|
||||
config.microcode_name = "drxk_a3.mc";
|
||||
config.qam_demod_parameter_count = 4;
|
||||
config.adr = 0x29 + (chan->number ^ 2);
|
||||
|
||||
chan->fe = dvb_attach(drxk_attach, &config, i2c);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
menuconfig RADIO_ADAPTERS
|
||||
bool "Radio Adapters"
|
||||
depends on VIDEO_V4L2
|
||||
depends on MEDIA_RADIO_SUPPORT
|
||||
default y
|
||||
---help---
|
||||
Say Y here to enable selecting AM/FM radio adapters.
|
||||
|
|
43
drivers/media/radio/lm7000.h
Normal file
43
drivers/media/radio/lm7000.h
Normal file
|
@ -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-ctrls.h>
|
||||
#include "radio-isa.h"
|
||||
#include "lm7000.h"
|
||||
|
||||
MODULE_AUTHOR("M. Kirkwood");
|
||||
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;
|
||||
}
|
||||
|
||||
/* The 128+64 on these outb's is to keep the volume stable while tuning.
|
||||
* Without them, the volume _will_ creep up with each frequency change
|
||||
* and bit 4 (+16) is to keep the signal strength meter enabled.
|
||||
*/
|
||||
#define AIMS_BIT_TUN_CE (1 << 0)
|
||||
#define AIMS_BIT_TUN_CLK (1 << 1)
|
||||
#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 */
|
||||
outb_p(128+64+16+on+2+1, isa->io); /* clock */
|
||||
msleep(1);
|
||||
}
|
||||
struct radio_isa_card *isa = handle;
|
||||
struct rtrack *rt = container_of(isa, struct rtrack, isa);
|
||||
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)
|
||||
{
|
||||
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 */
|
||||
msleep(1);
|
||||
if (!v4l2_ctrl_g_ctrl(rt->isa.mute))
|
||||
bits |= AIMS_BIT_VOL_CE;
|
||||
|
||||
if (pins & LM7000_DATA)
|
||||
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)
|
||||
{
|
||||
int on = v4l2_ctrl_g_ctrl(isa->mute) ? 0 : 8;
|
||||
int i;
|
||||
lm7000_set_freq(freq, isa, rtrack_set_pins);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -295,7 +295,8 @@ static int vidioc_g_tuner(struct file *file, void *priv,
|
|||
v->type = V4L2_TUNER_RADIO;
|
||||
v->rangelow = FREQ_MIN * 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->audmode = radio->stereo ?
|
||||
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);
|
||||
for (;;) {
|
||||
if (time_after(jiffies, timeout)) {
|
||||
retval = -EAGAIN;
|
||||
retval = -ENODATA;
|
||||
break;
|
||||
}
|
||||
if (schedule_timeout_interruptible(msecs_to_jiffies(10))) {
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <linux/io.h> /* outb, outb_p */
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-ioctl.h>
|
||||
#include "lm7000.h"
|
||||
|
||||
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.");
|
||||
|
@ -54,31 +55,33 @@ static struct fmi fmi_card;
|
|||
static struct pnp_dev *dev;
|
||||
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_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--) {
|
||||
if (data & 1) {
|
||||
outb(5, io);
|
||||
udelay(6);
|
||||
outb(7, io);
|
||||
udelay(6);
|
||||
} else {
|
||||
outb(1, io);
|
||||
udelay(6);
|
||||
outb(3, io);
|
||||
udelay(6);
|
||||
}
|
||||
data >>= 1;
|
||||
}
|
||||
struct fmi *fmi = handle;
|
||||
u8 bits = FMI_BIT_TUN_STRQ;
|
||||
|
||||
if (!fmi->mute)
|
||||
bits |= FMI_BIT_VOL_SW;
|
||||
|
||||
if (pins & LM7000_DATA)
|
||||
bits |= FMI_BIT_TUN_DATA;
|
||||
if (pins & LM7000_CLK)
|
||||
bits |= FMI_BIT_TUN_CLK;
|
||||
if (pins & LM7000_CE)
|
||||
bits |= FMI_BIT_TUN_CE;
|
||||
|
||||
mutex_lock(&fmi->lock);
|
||||
outb_p(bits, fmi->io);
|
||||
mutex_unlock(&fmi->lock);
|
||||
}
|
||||
|
||||
static inline void fmi_mute(struct fmi *fmi)
|
||||
|
@ -95,20 +98,6 @@ static inline void fmi_unmute(struct fmi *fmi)
|
|||
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)
|
||||
{
|
||||
int val;
|
||||
|
@ -173,7 +162,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
|
|||
return -EINVAL;
|
||||
/* rounding in steps of 800 to match the freq
|
||||
that will be used */
|
||||
fmi_setfreq(fmi, (f->frequency / 800) * 800);
|
||||
lm7000_set_freq((f->frequency / 800) * 800, fmi, fmi_set_pins);
|
||||
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->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)
|
||||
tuner->audmode = V4L2_TUNER_MODE_STEREO;
|
||||
|
|
|
@ -363,7 +363,7 @@ stop:
|
|||
|
||||
/* try again, if timed out */
|
||||
if (retval == 0 && timed_out)
|
||||
return -EAGAIN;
|
||||
return -ENODATA;
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -596,7 +596,9 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
|
|||
strcpy(tuner->name, "FM");
|
||||
tuner->type = V4L2_TUNER_RADIO;
|
||||
tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
|
||||
V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO;
|
||||
V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO |
|
||||
V4L2_TUNER_CAP_HWSEEK_BOUNDED |
|
||||
V4L2_TUNER_CAP_HWSEEK_WRAP;
|
||||
|
||||
/* range limits */
|
||||
switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) {
|
||||
|
|
|
@ -251,7 +251,7 @@ again:
|
|||
if (!timeleft) {
|
||||
fmerr("Timeout(%d sec),didn't get tune ended int\n",
|
||||
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);
|
||||
|
|
|
@ -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 |
|
||||
((fmdev->rx.rds.flag == FM_RDS_ENABLE) ? V4L2_TUNER_SUB_RDS : 0);
|
||||
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 ?
|
||||
V4L2_TUNER_MODE_MONO : V4L2_TUNER_MODE_STEREO);
|
||||
|
||||
|
|
|
@ -1,22 +1,21 @@
|
|||
menuconfig 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
|
||||
config RC_CORE
|
||||
tristate
|
||||
depends on MEDIA_RC_SUPPORT
|
||||
depends on INPUT
|
||||
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---
|
||||
Enable this option to build the Linux Infrared Remote
|
||||
Control (LIRC) core device interface driver. The LIRC
|
||||
|
@ -24,7 +23,16 @@ config LIRC
|
|||
LIRC daemon handles protocol decoding for IR reception and
|
||||
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
|
||||
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
|
||||
Windows Media Center Edition, which you would like to use with
|
||||
a raw IR receiver in your system.
|
||||
endif #RC_DECODERS
|
||||
|
||||
config IR_LIRC_CODEC
|
||||
tristate "Enable IR to LIRC bridge"
|
||||
menuconfig RC_DEVICES
|
||||
bool "Remote Controller devices"
|
||||
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.
|
||||
if RC_DEVICES
|
||||
|
||||
config RC_ATI_REMOTE
|
||||
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
|
||||
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);
|
||||
|
||||
dev->hw_io = pnp_port_start(pnp_dev, 0);
|
||||
|
||||
pnp_set_drvdata(pnp_dev, 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 */
|
||||
error = -EBUSY;
|
||||
dev->hw_io = pnp_port_start(pnp_dev, 0);
|
||||
if (!request_region(dev->hw_io, ENE_IO_SIZE, ENE_DRIVER_NAME)) {
|
||||
dev->hw_io = -1;
|
||||
dev->irq = -1;
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
* USA
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pnp.h>
|
||||
|
@ -110,30 +112,32 @@ static u8 fintek_cir_reg_read(struct fintek_dev *fintek, u8 offset)
|
|||
return val;
|
||||
}
|
||||
|
||||
#define pr_reg(text, ...) \
|
||||
printk(KERN_INFO KBUILD_MODNAME ": " text, ## __VA_ARGS__)
|
||||
|
||||
/* dump current cir register contents */
|
||||
static void cir_dump_regs(struct fintek_dev *fintek)
|
||||
{
|
||||
fintek_config_mode_enable(fintek);
|
||||
fintek_select_logical_dev(fintek, fintek->logical_dev_cir);
|
||||
|
||||
pr_reg("%s: Dump CIR logical device registers:\n", FINTEK_DRIVER_NAME);
|
||||
pr_reg(" * CR CIR BASE ADDR: 0x%x\n",
|
||||
(fintek_cr_read(fintek, CIR_CR_BASE_ADDR_HI) << 8) |
|
||||
pr_info("%s: Dump CIR logical device registers:\n", FINTEK_DRIVER_NAME);
|
||||
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_LO));
|
||||
pr_reg(" * CR CIR IRQ NUM: 0x%x\n",
|
||||
fintek_cr_read(fintek, CIR_CR_IRQ_SEL));
|
||||
pr_info(" * CR CIR IRQ NUM: 0x%x\n",
|
||||
fintek_cr_read(fintek, CIR_CR_IRQ_SEL));
|
||||
|
||||
fintek_config_mode_disable(fintek);
|
||||
|
||||
pr_reg("%s: Dump CIR registers:\n", FINTEK_DRIVER_NAME);
|
||||
pr_reg(" * STATUS: 0x%x\n", fintek_cir_reg_read(fintek, CIR_STATUS));
|
||||
pr_reg(" * CONTROL: 0x%x\n", fintek_cir_reg_read(fintek, CIR_CONTROL));
|
||||
pr_reg(" * RX_DATA: 0x%x\n", fintek_cir_reg_read(fintek, CIR_RX_DATA));
|
||||
pr_reg(" * TX_CONTROL: 0x%x\n", fintek_cir_reg_read(fintek, CIR_TX_CONTROL));
|
||||
pr_reg(" * TX_DATA: 0x%x\n", fintek_cir_reg_read(fintek, CIR_TX_DATA));
|
||||
pr_info("%s: Dump CIR registers:\n", FINTEK_DRIVER_NAME);
|
||||
pr_info(" * STATUS: 0x%x\n",
|
||||
fintek_cir_reg_read(fintek, CIR_STATUS));
|
||||
pr_info(" * CONTROL: 0x%x\n",
|
||||
fintek_cir_reg_read(fintek, CIR_CONTROL));
|
||||
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 */
|
||||
|
|
|
@ -82,12 +82,21 @@ static int __devinit gpio_ir_recv_probe(struct platform_device *pdev)
|
|||
goto err_allocate_device;
|
||||
}
|
||||
|
||||
rcdev->priv = gpio_dev;
|
||||
rcdev->driver_type = RC_DRIVER_IR_RAW;
|
||||
rcdev->allowed_protos = RC_TYPE_ALL;
|
||||
rcdev->input_name = GPIO_IR_DEVICE_NAME;
|
||||
rcdev->input_phys = GPIO_IR_DEVICE_NAME "/input0";
|
||||
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->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->gpio_nr = pdata->gpio_nr;
|
||||
|
@ -188,18 +197,7 @@ static struct platform_driver gpio_ir_recv_driver = {
|
|||
#endif
|
||||
},
|
||||
};
|
||||
|
||||
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_platform_driver(gpio_ir_recv_driver);
|
||||
|
||||
MODULE_DESCRIPTION("GPIO IR Receiver driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
* USA
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pnp.h>
|
||||
|
@ -123,43 +125,40 @@ static u8 nvt_cir_wake_reg_read(struct nvt_dev *nvt, u8 offset)
|
|||
return val;
|
||||
}
|
||||
|
||||
#define pr_reg(text, ...) \
|
||||
printk(KERN_INFO KBUILD_MODNAME ": " text, ## __VA_ARGS__)
|
||||
|
||||
/* dump current cir register contents */
|
||||
static void cir_dump_regs(struct nvt_dev *nvt)
|
||||
{
|
||||
nvt_efm_enable(nvt);
|
||||
nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
|
||||
|
||||
pr_reg("%s: Dump CIR logical device registers:\n", NVT_DRIVER_NAME);
|
||||
pr_reg(" * CR CIR ACTIVE : 0x%x\n",
|
||||
nvt_cr_read(nvt, CR_LOGICAL_DEV_EN));
|
||||
pr_reg(" * CR CIR BASE ADDR: 0x%x\n",
|
||||
(nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8) |
|
||||
pr_info("%s: Dump CIR logical device registers:\n", NVT_DRIVER_NAME);
|
||||
pr_info(" * CR CIR ACTIVE : 0x%x\n",
|
||||
nvt_cr_read(nvt, CR_LOGICAL_DEV_EN));
|
||||
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_LO));
|
||||
pr_reg(" * CR CIR IRQ NUM: 0x%x\n",
|
||||
nvt_cr_read(nvt, CR_CIR_IRQ_RSRC));
|
||||
pr_info(" * CR CIR IRQ NUM: 0x%x\n",
|
||||
nvt_cr_read(nvt, CR_CIR_IRQ_RSRC));
|
||||
|
||||
nvt_efm_disable(nvt);
|
||||
|
||||
pr_reg("%s: Dump CIR registers:\n", NVT_DRIVER_NAME);
|
||||
pr_reg(" * 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_reg(" * 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_reg(" * 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_reg(" * 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_reg(" * 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_reg(" * 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_reg(" * 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_reg(" * 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("%s: Dump CIR registers:\n", NVT_DRIVER_NAME);
|
||||
pr_info(" * IRCON: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRCON));
|
||||
pr_info(" * IRSTS: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRSTS));
|
||||
pr_info(" * IREN: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IREN));
|
||||
pr_info(" * RXFCONT: 0x%x\n", nvt_cir_reg_read(nvt, CIR_RXFCONT));
|
||||
pr_info(" * CP: 0x%x\n", nvt_cir_reg_read(nvt, CIR_CP));
|
||||
pr_info(" * CC: 0x%x\n", nvt_cir_reg_read(nvt, CIR_CC));
|
||||
pr_info(" * SLCH: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SLCH));
|
||||
pr_info(" * SLCL: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SLCL));
|
||||
pr_info(" * FIFOCON: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FIFOCON));
|
||||
pr_info(" * IRFIFOSTS: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRFIFOSTS));
|
||||
pr_info(" * SRXFIFO: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SRXFIFO));
|
||||
pr_info(" * TXFCONT: 0x%x\n", nvt_cir_reg_read(nvt, CIR_TXFCONT));
|
||||
pr_info(" * STXFIFO: 0x%x\n", nvt_cir_reg_read(nvt, CIR_STXFIFO));
|
||||
pr_info(" * FCCH: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FCCH));
|
||||
pr_info(" * FCCL: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FCCL));
|
||||
pr_info(" * IRFSM: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRFSM));
|
||||
}
|
||||
|
||||
/* 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_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE);
|
||||
|
||||
pr_reg("%s: Dump CIR WAKE logical device registers:\n",
|
||||
NVT_DRIVER_NAME);
|
||||
pr_reg(" * CR CIR WAKE ACTIVE : 0x%x\n",
|
||||
nvt_cr_read(nvt, CR_LOGICAL_DEV_EN));
|
||||
pr_reg(" * CR CIR WAKE BASE ADDR: 0x%x\n",
|
||||
(nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8) |
|
||||
pr_info("%s: Dump CIR WAKE logical device registers:\n",
|
||||
NVT_DRIVER_NAME);
|
||||
pr_info(" * CR CIR WAKE ACTIVE : 0x%x\n",
|
||||
nvt_cr_read(nvt, CR_LOGICAL_DEV_EN));
|
||||
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_LO));
|
||||
pr_reg(" * CR CIR WAKE IRQ NUM: 0x%x\n",
|
||||
nvt_cr_read(nvt, CR_CIR_IRQ_RSRC));
|
||||
pr_info(" * CR CIR WAKE IRQ NUM: 0x%x\n",
|
||||
nvt_cr_read(nvt, CR_CIR_IRQ_RSRC));
|
||||
|
||||
nvt_efm_disable(nvt);
|
||||
|
||||
pr_reg("%s: Dump CIR WAKE registers\n", NVT_DRIVER_NAME);
|
||||
pr_reg(" * IRCON: 0x%x\n",
|
||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRCON));
|
||||
pr_reg(" * IRSTS: 0x%x\n",
|
||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS));
|
||||
pr_reg(" * IREN: 0x%x\n",
|
||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN));
|
||||
pr_reg(" * FIFO CMP DEEP: 0x%x\n",
|
||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_CMP_DEEP));
|
||||
pr_reg(" * FIFO CMP TOL: 0x%x\n",
|
||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_CMP_TOL));
|
||||
pr_reg(" * FIFO COUNT: 0x%x\n",
|
||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT));
|
||||
pr_reg(" * SLCH: 0x%x\n",
|
||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_SLCH));
|
||||
pr_reg(" * SLCL: 0x%x\n",
|
||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_SLCL));
|
||||
pr_reg(" * FIFOCON: 0x%x\n",
|
||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFOCON));
|
||||
pr_reg(" * SRXFSTS: 0x%x\n",
|
||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_SRXFSTS));
|
||||
pr_reg(" * SAMPLE RX FIFO: 0x%x\n",
|
||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_SAMPLE_RX_FIFO));
|
||||
pr_reg(" * WR FIFO DATA: 0x%x\n",
|
||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_WR_FIFO_DATA));
|
||||
pr_reg(" * RD FIFO ONLY: 0x%x\n",
|
||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY));
|
||||
pr_reg(" * RD FIFO ONLY IDX: 0x%x\n",
|
||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY_IDX));
|
||||
pr_reg(" * FIFO IGNORE: 0x%x\n",
|
||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_IGNORE));
|
||||
pr_reg(" * IRFSM: 0x%x\n",
|
||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRFSM));
|
||||
pr_info("%s: Dump CIR WAKE registers\n", NVT_DRIVER_NAME);
|
||||
pr_info(" * IRCON: 0x%x\n",
|
||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRCON));
|
||||
pr_info(" * IRSTS: 0x%x\n",
|
||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS));
|
||||
pr_info(" * IREN: 0x%x\n",
|
||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN));
|
||||
pr_info(" * FIFO CMP DEEP: 0x%x\n",
|
||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_CMP_DEEP));
|
||||
pr_info(" * FIFO CMP TOL: 0x%x\n",
|
||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_CMP_TOL));
|
||||
pr_info(" * FIFO COUNT: 0x%x\n",
|
||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT));
|
||||
pr_info(" * SLCH: 0x%x\n",
|
||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_SLCH));
|
||||
pr_info(" * SLCL: 0x%x\n",
|
||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_SLCL));
|
||||
pr_info(" * FIFOCON: 0x%x\n",
|
||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFOCON));
|
||||
pr_info(" * SRXFSTS: 0x%x\n",
|
||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_SRXFSTS));
|
||||
pr_info(" * SAMPLE RX FIFO: 0x%x\n",
|
||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_SAMPLE_RX_FIFO));
|
||||
pr_info(" * WR FIFO DATA: 0x%x\n",
|
||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_WR_FIFO_DATA));
|
||||
pr_info(" * RD FIFO ONLY: 0x%x\n",
|
||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY));
|
||||
pr_info(" * RD FIFO ONLY IDX: 0x%x\n",
|
||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY_IDX));
|
||||
pr_info(" * FIFO IGNORE: 0x%x\n",
|
||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_IGNORE));
|
||||
pr_info(" * IRFSM: 0x%x\n",
|
||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRFSM));
|
||||
|
||||
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_reg("* Contents = ");
|
||||
pr_info("%s: Dump CIR WAKE FIFO (len %d)\n", NVT_DRIVER_NAME, fifo_len);
|
||||
pr_info("* Contents =");
|
||||
for (i = 0; i < fifo_len; i++)
|
||||
printk(KERN_CONT "%02x ",
|
||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY));
|
||||
printk(KERN_CONT "\n");
|
||||
pr_cont(" %02x",
|
||||
nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY));
|
||||
pr_cont("\n");
|
||||
}
|
||||
|
||||
/* detect hardware features */
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
config VIDEO_V4L2
|
||||
tristate
|
||||
depends on VIDEO_DEV && VIDEO_V4L2_COMMON
|
||||
default VIDEO_DEV && VIDEO_V4L2_COMMON
|
||||
default y
|
||||
|
||||
config VIDEOBUF_GEN
|
||||
tristate
|
||||
|
@ -73,6 +73,7 @@ config VIDEOBUF2_DMA_SG
|
|||
menuconfig VIDEO_CAPTURE_DRIVERS
|
||||
bool "Video capture adapters"
|
||||
depends on VIDEO_V4L2
|
||||
depends on MEDIA_CAMERA_SUPPORT || MEDIA_ANALOG_TV_SUPPORT
|
||||
default y
|
||||
---help---
|
||||
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
|
||||
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
|
||||
tristate "AK8813/AK8814 video encoders"
|
||||
depends on I2C
|
||||
|
@ -478,6 +488,7 @@ config VIDEO_SMIAPP_PLL
|
|||
config VIDEO_OV7670
|
||||
tristate "OmniVision OV7670 sensor support"
|
||||
depends on I2C && VIDEO_V4L2
|
||||
depends on MEDIA_CAMERA_SUPPORT
|
||||
---help---
|
||||
This is a Video4Linux2 sensor-level driver for the OmniVision
|
||||
OV7670 VGA camera. It currently only works with the M88ALP01
|
||||
|
@ -486,6 +497,7 @@ config VIDEO_OV7670
|
|||
config VIDEO_VS6624
|
||||
tristate "ST VS6624 sensor support"
|
||||
depends on VIDEO_V4L2 && I2C
|
||||
depends on MEDIA_CAMERA_SUPPORT
|
||||
---help---
|
||||
This is a Video4Linux2 sensor-level driver for the ST VS6624
|
||||
camera.
|
||||
|
@ -496,6 +508,7 @@ config VIDEO_VS6624
|
|||
config VIDEO_MT9M032
|
||||
tristate "MT9M032 camera sensor support"
|
||||
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
|
||||
depends on MEDIA_CAMERA_SUPPORT
|
||||
select VIDEO_APTINA_PLL
|
||||
---help---
|
||||
This driver supports MT9M032 camera sensors from Aptina, monochrome
|
||||
|
@ -504,6 +517,7 @@ config VIDEO_MT9M032
|
|||
config VIDEO_MT9P031
|
||||
tristate "Aptina MT9P031 support"
|
||||
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
|
||||
depends on MEDIA_CAMERA_SUPPORT
|
||||
select VIDEO_APTINA_PLL
|
||||
---help---
|
||||
This is a Video4Linux2 sensor-level driver for the Aptina
|
||||
|
@ -512,6 +526,7 @@ config VIDEO_MT9P031
|
|||
config VIDEO_MT9T001
|
||||
tristate "Aptina MT9T001 support"
|
||||
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
|
||||
depends on MEDIA_CAMERA_SUPPORT
|
||||
---help---
|
||||
This is a Video4Linux2 sensor-level driver for the Aptina
|
||||
(Micron) mt0t001 3 Mpixel camera.
|
||||
|
@ -519,6 +534,7 @@ config VIDEO_MT9T001
|
|||
config VIDEO_MT9V011
|
||||
tristate "Micron mt9v011 sensor support"
|
||||
depends on I2C && VIDEO_V4L2
|
||||
depends on MEDIA_CAMERA_SUPPORT
|
||||
---help---
|
||||
This is a Video4Linux2 sensor-level driver for the Micron
|
||||
mt0v011 1.3 Mpixel camera. It currently only works with the
|
||||
|
@ -527,6 +543,7 @@ config VIDEO_MT9V011
|
|||
config VIDEO_MT9V032
|
||||
tristate "Micron MT9V032 sensor support"
|
||||
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
|
||||
depends on MEDIA_CAMERA_SUPPORT
|
||||
---help---
|
||||
This is a Video4Linux2 sensor-level driver for the Micron
|
||||
MT9V032 752x480 CMOS sensor.
|
||||
|
@ -534,6 +551,7 @@ config VIDEO_MT9V032
|
|||
config VIDEO_TCM825X
|
||||
tristate "TCM825x camera sensor support"
|
||||
depends on I2C && VIDEO_V4L2
|
||||
depends on MEDIA_CAMERA_SUPPORT
|
||||
---help---
|
||||
This is a driver for the Toshiba TCM825x VGA camera sensor.
|
||||
It is used for example in Nokia N800.
|
||||
|
@ -541,12 +559,14 @@ config VIDEO_TCM825X
|
|||
config VIDEO_SR030PC30
|
||||
tristate "Siliconfile SR030PC30 sensor support"
|
||||
depends on I2C && VIDEO_V4L2
|
||||
depends on MEDIA_CAMERA_SUPPORT
|
||||
---help---
|
||||
This driver supports SR030PC30 VGA camera from Siliconfile
|
||||
|
||||
config VIDEO_NOON010PC30
|
||||
tristate "Siliconfile NOON010PC30 sensor support"
|
||||
depends on I2C && VIDEO_V4L2 && EXPERIMENTAL && VIDEO_V4L2_SUBDEV_API
|
||||
depends on MEDIA_CAMERA_SUPPORT
|
||||
---help---
|
||||
This driver supports NOON010PC30 CIF camera from Siliconfile
|
||||
|
||||
|
@ -554,6 +574,7 @@ source "drivers/media/video/m5mols/Kconfig"
|
|||
|
||||
config VIDEO_S5K6AA
|
||||
tristate "Samsung S5K6AAFX sensor support"
|
||||
depends on MEDIA_CAMERA_SUPPORT
|
||||
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
|
||||
---help---
|
||||
This is a V4L2 sensor-level driver for Samsung S5K6AA(FX) 1.3M
|
||||
|
@ -566,6 +587,7 @@ comment "Flash devices"
|
|||
config VIDEO_ADP1653
|
||||
tristate "ADP1653 flash support"
|
||||
depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
|
||||
depends on MEDIA_CAMERA_SUPPORT
|
||||
---help---
|
||||
This is a driver for the ADP1653 flash controller. It is used for
|
||||
example in Nokia N900.
|
||||
|
@ -573,6 +595,7 @@ config VIDEO_ADP1653
|
|||
config VIDEO_AS3645A
|
||||
tristate "AS3645A flash driver support"
|
||||
depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
|
||||
depends on MEDIA_CAMERA_SUPPORT
|
||||
---help---
|
||||
This is a driver for the AS3645A and LM3555 flash controllers. It has
|
||||
build in control for flash, torch and indicator LEDs.
|
||||
|
@ -647,30 +670,14 @@ menuconfig V4L_USB_DRIVERS
|
|||
depends on USB
|
||||
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/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/cpia2/Kconfig"
|
||||
|
@ -711,15 +718,46 @@ config USB_S2255
|
|||
Say Y here if you want support for the Sensoray 2255 USB device.
|
||||
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
|
||||
|
||||
#
|
||||
# PCI drivers configuration
|
||||
# PCI drivers configuration - No devices here are for webcams
|
||||
#
|
||||
|
||||
menuconfig V4L_PCI_DRIVERS
|
||||
bool "V4L PCI(e) devices"
|
||||
depends on PCI
|
||||
depends on MEDIA_ANALOG_TV_SUPPORT
|
||||
default y
|
||||
---help---
|
||||
Say Y here to enable support for these PCI(e) drivers.
|
||||
|
@ -814,11 +852,13 @@ endif # V4L_PCI_DRIVERS
|
|||
|
||||
#
|
||||
# ISA & parallel port drivers configuration
|
||||
# All devices here are webcam or grabber devices
|
||||
#
|
||||
|
||||
menuconfig V4L_ISA_PARPORT_DRIVERS
|
||||
bool "V4L ISA and parallel port devices"
|
||||
depends on ISA || PARPORT
|
||||
depends on MEDIA_CAMERA_SUPPORT
|
||||
default n
|
||||
---help---
|
||||
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
|
||||
|
||||
#
|
||||
# Platform drivers
|
||||
# All drivers here are currently for webcam support
|
||||
|
||||
menuconfig V4L_PLATFORM_DRIVERS
|
||||
bool "V4L platform devices"
|
||||
depends on MEDIA_CAMERA_SUPPORT
|
||||
default n
|
||||
---help---
|
||||
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_ADV7183) += adv7183.o
|
||||
obj-$(CONFIG_VIDEO_ADV7343) += adv7343.o
|
||||
obj-$(CONFIG_VIDEO_ADV7393) += adv7393.o
|
||||
obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o
|
||||
obj-$(CONFIG_VIDEO_VS6624) += vs6624.o
|
||||
obj-$(CONFIG_VIDEO_BT819) += bt819.o
|
||||
|
|
487
drivers/media/video/adv7393.c
Normal file
487
drivers/media/video/adv7393.c
Normal file
|
@ -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);
|
188
drivers/media/video/adv7393_regs.h
Normal file
188
drivers/media/video/adv7393_regs.h
Normal file
|
@ -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_addr = ADDR_UNSET,
|
||||
.has_remote = 1,
|
||||
.has_radio = 1, /* not every card has radio */
|
||||
},
|
||||
[BTTV_BOARD_VOBIS_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,
|
||||
.depth = 16,
|
||||
.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",
|
||||
.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->m.offset = cam->buffers[buf->index].data - cam->frame_buffer;
|
||||
buf->length = cam->frame_size;
|
||||
buf->input = 0;
|
||||
buf->reserved2 = 0;
|
||||
buf->reserved = 0;
|
||||
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;
|
||||
}
|
||||
|
||||
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 = {
|
||||
.vidioc_querycap = cx18_querycap,
|
||||
.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_frequency(struct file *file, void *fh, struct v4l2_frequency *vf);
|
||||
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,
|
||||
.read = cx18_v4l2_read,
|
||||
.open = cx18_v4l2_open,
|
||||
/* FIXME change to video_ioctl2 if serialization lock can be removed */
|
||||
.unlocked_ioctl = cx18_v4l2_ioctl,
|
||||
.unlocked_ioctl = video_ioctl2,
|
||||
.release = cx18_v4l2_close,
|
||||
.poll = cx18_v4l2_enc_poll,
|
||||
.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->release = video_device_release;
|
||||
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);
|
||||
cx18_set_funcs(s->video_dev);
|
||||
return 0;
|
||||
|
|
|
@ -89,7 +89,7 @@ void initGPIO(struct cx231xx *dev)
|
|||
verve_read_byte(dev, 0x07, &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, GBULK_BIT_EN, 0xFFFDFFFF);
|
||||
|
@ -99,7 +99,7 @@ void uninitGPIO(struct cx231xx *dev)
|
|||
{
|
||||
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);
|
||||
cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
|
||||
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) {
|
||||
switch (media_type) {
|
||||
case 81: /* audio */
|
||||
case Audio:
|
||||
cx231xx_info("%s: Audio enter HANC\n", __func__);
|
||||
status =
|
||||
cx231xx_mode_register(dev, TS_MODE_REG, 0x9300);
|
||||
break;
|
||||
|
||||
case 2: /* vbi */
|
||||
case Vbi:
|
||||
cx231xx_info("%s: set vanc registers\n", __func__);
|
||||
status = cx231xx_mode_register(dev, TS_MODE_REG, 0x300);
|
||||
break;
|
||||
|
||||
case 3: /* sliced cc */
|
||||
case Sliced_cc:
|
||||
cx231xx_info("%s: set hanc registers\n", __func__);
|
||||
status =
|
||||
cx231xx_mode_register(dev, TS_MODE_REG, 0x1300);
|
||||
break;
|
||||
|
||||
case 0: /* video */
|
||||
case Raw_Video:
|
||||
cx231xx_info("%s: set video registers\n", __func__);
|
||||
status = cx231xx_mode_register(dev, TS_MODE_REG, 0x100);
|
||||
break;
|
||||
|
||||
case 4: /* ts1 */
|
||||
case TS1_serial_mode:
|
||||
cx231xx_info("%s: set ts1 registers", __func__);
|
||||
|
||||
if (dev->board.has_417) {
|
||||
|
@ -2569,7 +2569,7 @@ int cx231xx_initialize_stream_xfer(struct cx231xx *dev, u32 media_type)
|
|||
}
|
||||
break;
|
||||
|
||||
case 6: /* ts1 parallel mode */
|
||||
case TS1_parallel_mode:
|
||||
cx231xx_info("%s: set ts1 parallel mode registers\n",
|
||||
__func__);
|
||||
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 */
|
||||
pcb_config = (struct pcb_config *)&dev->current_pcb_config;
|
||||
|
||||
if (pcb_config->config_num == 1) {
|
||||
if (pcb_config->config_num) {
|
||||
switch (media_type) {
|
||||
case 0: /* Video */
|
||||
case Raw_Video:
|
||||
ep_mask = ENABLE_EP4; /* ep4 [00:1000] */
|
||||
break;
|
||||
case 1: /* Audio */
|
||||
case Audio:
|
||||
ep_mask = ENABLE_EP3; /* ep3 [00:0100] */
|
||||
break;
|
||||
case 2: /* Vbi */
|
||||
case Vbi:
|
||||
ep_mask = ENABLE_EP5; /* ep5 [01:0000] */
|
||||
break;
|
||||
case 3: /* Sliced_cc */
|
||||
case Sliced_cc:
|
||||
ep_mask = ENABLE_EP6; /* ep6 [10:0000] */
|
||||
break;
|
||||
case 4: /* ts1 */
|
||||
case 6: /* ts1 parallel mode */
|
||||
case TS1_serial_mode:
|
||||
case TS1_parallel_mode:
|
||||
ep_mask = ENABLE_EP1; /* ep1 [00:0001] */
|
||||
break;
|
||||
case 5: /* ts2 */
|
||||
case TS2:
|
||||
ep_mask = ENABLE_EP2; /* ep2 [00:0010] */
|
||||
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) {
|
||||
|
|
|
@ -1023,7 +1023,6 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
|
|||
int nr = 0, ifnum;
|
||||
int i, isoc_pipe = 0;
|
||||
char *speed;
|
||||
char descr[255] = "";
|
||||
struct usb_interface_assoc_descriptor *assoc_desc;
|
||||
|
||||
udev = usb_get_dev(interface_to_usbdev(interface));
|
||||
|
@ -1098,20 +1097,10 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
|
|||
speed = "unknown";
|
||||
}
|
||||
|
||||
if (udev->manufacturer)
|
||||
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 "
|
||||
cx231xx_info("New device %s %s @ %s Mbps "
|
||||
"(%04x:%04x) with %d interfaces\n",
|
||||
descr,
|
||||
udev->manufacturer ? udev->manufacturer : "",
|
||||
udev->product ? udev->product : "",
|
||||
speed,
|
||||
le16_to_cpu(udev->descriptor.idVendor),
|
||||
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);
|
||||
struct cx88_core *core = chip->core;
|
||||
struct v4l2_control client_ctl;
|
||||
int left = value->value.integer.value[0];
|
||||
int right = value->value.integer.value[1];
|
||||
int v, b;
|
||||
|
||||
memset(&client_ctl, 0, sizeof(client_ctl));
|
||||
|
||||
/* Pass volume & balance onto any WM8775 */
|
||||
if (left >= right) {
|
||||
v = left << 10;
|
||||
|
@ -600,13 +597,8 @@ static void snd_cx88_wm8775_volume_put(struct snd_kcontrol *kcontrol,
|
|||
v = right << 10;
|
||||
b = right ? 0xffff - (0x8000 * left) / right : 0x8000;
|
||||
}
|
||||
client_ctl.value = v;
|
||||
client_ctl.id = V4L2_CID_AUDIO_VOLUME;
|
||||
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);
|
||||
wm8775_s_ctrl(core, V4L2_CID_AUDIO_VOLUME, v);
|
||||
wm8775_s_ctrl(core, V4L2_CID_AUDIO_BALANCE, b);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
/* Pass mute onto any WM8775 */
|
||||
if ((core->board.audio_chip == V4L2_IDENT_WM8775) &&
|
||||
((1<<6) == bit)) {
|
||||
struct v4l2_control client_ctl;
|
||||
|
||||
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);
|
||||
}
|
||||
((1<<6) == bit))
|
||||
wm8775_s_ctrl(core, V4L2_CID_AUDIO_MUTE, 0 != (vol & bit));
|
||||
ret = 1;
|
||||
}
|
||||
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);
|
||||
struct cx88_core *core = chip->core;
|
||||
struct v4l2_control client_ctl;
|
||||
|
||||
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;
|
||||
s32 val;
|
||||
|
||||
val = wm8775_g_ctrl(core, V4L2_CID_AUDIO_LOUDNESS);
|
||||
value->value.integer.value[0] = val ? 1 : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <linux/firmware.h>
|
||||
#include <media/v4l2-common.h>
|
||||
#include <media/v4l2-ioctl.h>
|
||||
#include <media/v4l2-event.h>
|
||||
#include <media/cx2341x.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,
|
||||
dev->height, dev->width);
|
||||
|
||||
dev->params.width = dev->width;
|
||||
dev->params.height = dev->height;
|
||||
dev->params.is_50hz = (dev->core->tvnorm & V4L2_STD_625_50) != 0;
|
||||
|
||||
cx2341x_update(dev, blackbird_mbox_func, NULL, &dev->params);
|
||||
dev->cxhdl.width = dev->width;
|
||||
dev->cxhdl.height = dev->height;
|
||||
cx2341x_handler_set_50hz(&dev->cxhdl, dev->core->tvnorm & V4L2_STD_625_50);
|
||||
cx2341x_handler_setup(&dev->cxhdl);
|
||||
}
|
||||
|
||||
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 */
|
||||
blackbird_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0);
|
||||
|
||||
cx2341x_handler_set_busy(&dev->cxhdl, 1);
|
||||
|
||||
/* start capturing to the host interface */
|
||||
blackbird_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0,
|
||||
BLACKBIRD_MPEG_CAPTURE,
|
||||
|
@ -636,6 +638,8 @@ static int blackbird_stop_codec(struct cx8802_dev *dev)
|
|||
BLACKBIRD_RAW_BITS_NONE
|
||||
);
|
||||
|
||||
cx2341x_handler_set_busy(&dev->cxhdl, 0);
|
||||
|
||||
dev->mpeg_active = 0;
|
||||
return 0;
|
||||
}
|
||||
|
@ -685,58 +689,15 @@ static struct videobuf_queue_ops blackbird_qops = {
|
|||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static const u32 *ctrl_classes[] = {
|
||||
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,
|
||||
static int vidioc_querycap(struct file *file, void *priv,
|
||||
struct v4l2_capability *cap)
|
||||
{
|
||||
struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
|
||||
struct cx88_core *core = dev->core;
|
||||
|
||||
strcpy(cap->driver, "cx88_blackbird");
|
||||
strlcpy(cap->card, core->board.name, sizeof(cap->card));
|
||||
sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));
|
||||
cap->capabilities =
|
||||
V4L2_CAP_VIDEO_CAPTURE |
|
||||
V4L2_CAP_READWRITE |
|
||||
V4L2_CAP_STREAMING;
|
||||
if (UNSET != core->board.tuner_type)
|
||||
cap->capabilities |= V4L2_CAP_TUNER;
|
||||
sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
|
||||
cx88_querycap(file, core, cap);
|
||||
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));
|
||||
f->pixelformat = V4L2_PIX_FMT_MPEG;
|
||||
f->flags = V4L2_FMT_FLAG_COMPRESSED;
|
||||
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.bytesperline = 0;
|
||||
f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */
|
||||
f->fmt.pix.colorspace = 0;
|
||||
f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */;
|
||||
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
|
||||
f->fmt.pix.width = dev->width;
|
||||
f->fmt.pix.height = dev->height;
|
||||
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 );
|
||||
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.bytesperline = 0;
|
||||
f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */;
|
||||
f->fmt.pix.colorspace = 0;
|
||||
dprintk(0,"VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
|
||||
f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */;
|
||||
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
|
||||
dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
|
||||
dev->width, dev->height, fh->mpegq.field );
|
||||
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.bytesperline = 0;
|
||||
f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */;
|
||||
f->fmt.pix.colorspace = 0;
|
||||
f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */;
|
||||
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
|
||||
dev->width = f->fmt.pix.width;
|
||||
dev->height = f->fmt.pix.height;
|
||||
fh->mpegq.field = 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,
|
||||
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 );
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
|
||||
{
|
||||
struct cx8802_fh *fh = priv;
|
||||
return videobuf_streamoff(&fh->mpegq);
|
||||
}
|
||||
|
||||
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;
|
||||
struct cx8802_dev *dev = fh->dev;
|
||||
|
||||
if (dev->mpeg_active)
|
||||
blackbird_stop_codec(dev);
|
||||
|
||||
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;
|
||||
return videobuf_streamoff(&fh->mpegq);
|
||||
}
|
||||
|
||||
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 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)
|
||||
blackbird_stop_codec(dev);
|
||||
|
||||
|
@ -914,29 +841,11 @@ static int vidioc_log_status (struct file *file, void *priv)
|
|||
char name[32 + 2];
|
||||
|
||||
snprintf(name, sizeof(name), "%s/2", core->name);
|
||||
printk("%s/2: ============ START LOG STATUS ============\n",
|
||||
core->name);
|
||||
call_all(core, core, log_status);
|
||||
cx2341x_log_status(&dev->params, name);
|
||||
printk("%s/2: ============= END LOG STATUS =============\n",
|
||||
core->name);
|
||||
v4l2_ctrl_handler_log_status(&dev->cxhdl.hdl, name);
|
||||
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,
|
||||
struct v4l2_input *i)
|
||||
{
|
||||
|
@ -944,22 +853,6 @@ static int vidioc_enum_input (struct file *file, void *priv,
|
|||
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,
|
||||
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))
|
||||
return -EINVAL;
|
||||
if (unlikely(f->tuner != 0))
|
||||
return -EINVAL;
|
||||
|
||||
f->type = V4L2_TUNER_ANALOG_TV;
|
||||
f->frequency = core->freq;
|
||||
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)
|
||||
return -EINVAL;
|
||||
if (0 == INPUT(i).type)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&core->lock);
|
||||
cx88_newstation(core);
|
||||
|
@ -1010,9 +906,9 @@ static int vidioc_g_tuner (struct file *file, void *priv,
|
|||
return -EINVAL;
|
||||
|
||||
strcpy(t->name, "Television");
|
||||
t->type = V4L2_TUNER_ANALOG_TV;
|
||||
t->capability = V4L2_TUNER_CAP_NORM;
|
||||
t->rangehigh = 0xffffffffUL;
|
||||
call_all(core, tuner, g_tuner, t);
|
||||
|
||||
cx88_get_stereo(core ,t);
|
||||
reg = cx_read(MO_DEVICE_STATUS);
|
||||
|
@ -1034,6 +930,14 @@ static int vidioc_s_tuner (struct file *file, void *priv,
|
|||
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)
|
||||
{
|
||||
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);
|
||||
return -ENOMEM;
|
||||
}
|
||||
v4l2_fh_init(&fh->fh, vdev);
|
||||
file->private_data = fh;
|
||||
fh->dev = dev;
|
||||
|
||||
|
@ -1103,6 +1008,7 @@ static int mpeg_open(struct file *file)
|
|||
|
||||
dev->core->mpeg_users++;
|
||||
mutex_unlock(&dev->core->lock);
|
||||
v4l2_fh_add(&fh->fh);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1123,6 +1029,8 @@ static int mpeg_release(struct file *file)
|
|||
|
||||
videobuf_mmap_free(&fh->mpegq);
|
||||
|
||||
v4l2_fh_del(&fh->fh);
|
||||
v4l2_fh_exit(&fh->fh);
|
||||
file->private_data = NULL;
|
||||
kfree(fh);
|
||||
|
||||
|
@ -1155,13 +1063,14 @@ mpeg_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
|
|||
static unsigned int
|
||||
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_dev *dev = fh->dev;
|
||||
|
||||
if (!dev->mpeg_active)
|
||||
if (!dev->mpeg_active && (req_events & (POLLIN | POLLRDNORM)))
|
||||
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
|
||||
|
@ -1180,11 +1089,10 @@ static const struct v4l2_file_operations mpeg_fops =
|
|||
.read = mpeg_read,
|
||||
.poll = mpeg_poll,
|
||||
.mmap = mpeg_mmap,
|
||||
.ioctl = video_ioctl2,
|
||||
.unlocked_ioctl = video_ioctl2,
|
||||
};
|
||||
|
||||
static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
|
||||
.vidioc_querymenu = vidioc_querymenu,
|
||||
.vidioc_querycap = vidioc_querycap,
|
||||
.vidioc_enum_fmt_vid_cap = vidioc_enum_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_streamon = vidioc_streamon,
|
||||
.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_log_status = vidioc_log_status,
|
||||
.vidioc_queryctrl = vidioc_queryctrl,
|
||||
.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_input = vidioc_g_input,
|
||||
.vidioc_s_input = vidioc_s_input,
|
||||
.vidioc_g_tuner = vidioc_g_tuner,
|
||||
.vidioc_s_tuner = vidioc_s_tuner,
|
||||
.vidioc_g_std = vidioc_g_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 = {
|
||||
|
@ -1218,7 +1123,6 @@ static struct video_device cx8802_mpeg_template = {
|
|||
.fops = &mpeg_fops,
|
||||
.ioctl_ops = &mpeg_ioctl_ops,
|
||||
.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,
|
||||
&cx8802_mpeg_template,"mpeg");
|
||||
dev->mpeg_dev->ctrl_handler = &dev->cxhdl.hdl;
|
||||
video_set_drvdata(dev->mpeg_dev, dev);
|
||||
err = video_register_device(dev->mpeg_dev,VFL_TYPE_GRABBER, -1);
|
||||
if (err < 0) {
|
||||
|
@ -1318,17 +1223,20 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv)
|
|||
goto fail_core;
|
||||
|
||||
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) {
|
||||
dev->height = 480;
|
||||
} else {
|
||||
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 */
|
||||
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);
|
||||
|
||||
blackbird_initialize_codec(dev);
|
||||
blackbird_register_video(dev);
|
||||
|
||||
/* initial device configuration: needed ? */
|
||||
// init_controls(core);
|
||||
cx88_set_tvnorm(core,core->tvnorm);
|
||||
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;
|
||||
|
||||
|
@ -1351,8 +1261,12 @@ static int cx8802_blackbird_probe(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_unregister_video(drv->core->dvbdev);
|
||||
v4l2_ctrl_handler_free(&dev->cxhdl.hdl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -3693,7 +3693,22 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
|
|||
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)) {
|
||||
v4l2_ctrl_handler_free(&core->video_hdl);
|
||||
v4l2_ctrl_handler_free(&core->audio_hdl);
|
||||
v4l2_device_unregister(&core->v4l2_dev);
|
||||
kfree(core);
|
||||
return NULL;
|
||||
|
@ -3706,6 +3721,11 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
|
|||
core->bmmio = (u8 __iomem *)core->lmmio;
|
||||
|
||||
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);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -1012,6 +1012,9 @@ int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm)
|
|||
// tell i2c chips
|
||||
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
|
||||
return 0;
|
||||
}
|
||||
|
@ -1030,10 +1033,10 @@ struct video_device *cx88_vdev_init(struct cx88_core *core,
|
|||
return NULL;
|
||||
*vfd = *template_;
|
||||
vfd->v4l2_dev = &core->v4l2_dev;
|
||||
vfd->parent = &pci->dev;
|
||||
vfd->release = video_device_release;
|
||||
snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
|
||||
core->name, type, core->board.name);
|
||||
set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
|
||||
return vfd;
|
||||
}
|
||||
|
||||
|
@ -1086,6 +1089,8 @@ void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
|
|||
iounmap(core->lmmio);
|
||||
cx88_devcount--;
|
||||
mutex_unlock(&devlist);
|
||||
v4l2_ctrl_handler_free(&core->video_hdl);
|
||||
v4l2_ctrl_handler_free(&core->audio_hdl);
|
||||
v4l2_device_unregister(&core->v4l2_dev);
|
||||
kfree(core);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -26,6 +26,7 @@
|
|||
#include <linux/kdev_t.h>
|
||||
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-fh.h>
|
||||
#include <media/tuner.h>
|
||||
#include <media/tveeprom.h>
|
||||
#include <media/videobuf-dma-sg.h>
|
||||
|
@ -115,15 +116,6 @@ struct cx8800_fmt {
|
|||
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) */
|
||||
|
||||
|
@ -359,6 +351,10 @@ struct cx88_core {
|
|||
|
||||
/* config info -- analog */
|
||||
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;
|
||||
unsigned int boardnr;
|
||||
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);
|
||||
}
|
||||
|
||||
#define WM8775_GID (1 << 0)
|
||||
|
||||
#define call_hw(core, grpid, o, f, args...) \
|
||||
do { \
|
||||
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 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 cx8802_dev;
|
||||
|
||||
|
@ -431,19 +455,11 @@ struct cx8802_dev;
|
|||
/* function 0: video stuff */
|
||||
|
||||
struct cx8800_fh {
|
||||
struct v4l2_fh fh;
|
||||
struct cx8800_dev *dev;
|
||||
enum v4l2_buf_type type;
|
||||
int radio;
|
||||
unsigned int resources;
|
||||
|
||||
/* video overlay */
|
||||
struct v4l2_window win;
|
||||
struct v4l2_clip *clips;
|
||||
unsigned int nclips;
|
||||
|
||||
/* video capture */
|
||||
const struct cx8800_fmt *fmt;
|
||||
unsigned int width,height;
|
||||
struct videobuf_queue vidq;
|
||||
|
||||
/* vbi capture */
|
||||
|
@ -468,6 +484,8 @@ struct cx8800_dev {
|
|||
struct pci_dev *pci;
|
||||
unsigned char pci_rev,pci_lat;
|
||||
|
||||
const struct cx8800_fmt *fmt;
|
||||
unsigned int width, height;
|
||||
|
||||
/* capture queues */
|
||||
struct cx88_dmaqueue vidq;
|
||||
|
@ -488,6 +506,7 @@ struct cx8800_dev {
|
|||
/* function 2: mpeg stuff */
|
||||
|
||||
struct cx8802_fh {
|
||||
struct v4l2_fh fh;
|
||||
struct cx8802_dev *dev;
|
||||
struct videobuf_queue mpegq;
|
||||
};
|
||||
|
@ -552,7 +571,7 @@ struct cx8802_dev {
|
|||
unsigned char mpeg_active; /* nonzero if mpeg encoder is active */
|
||||
|
||||
/* mpeg params */
|
||||
struct cx2341x_mpeg_params params;
|
||||
struct cx2341x_handler cxhdl;
|
||||
#endif
|
||||
|
||||
#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*/
|
||||
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_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);
|
||||
void cx88_querycap(struct file *file, struct cx88_core *core,
|
||||
struct v4l2_capability *cap);
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include <sound/initval.h>
|
||||
#include <sound/control.h>
|
||||
#include <sound/tlv.h>
|
||||
#include <sound/ac97_codec.h>
|
||||
#include <media/v4l2-common.h>
|
||||
#include "em28xx.h"
|
||||
|
||||
|
@ -679,19 +680,19 @@ static int em28xx_audio_init(struct em28xx *dev)
|
|||
INIT_WORK(&dev->wq_trigger, audio_trigger);
|
||||
|
||||
if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
|
||||
em28xx_cvol_new(card, dev, "Video", AC97_VIDEO_VOL);
|
||||
em28xx_cvol_new(card, dev, "Line In", AC97_LINEIN_VOL);
|
||||
em28xx_cvol_new(card, dev, "Phone", AC97_PHONE_VOL);
|
||||
em28xx_cvol_new(card, dev, "Microphone", AC97_PHONE_VOL);
|
||||
em28xx_cvol_new(card, dev, "CD", AC97_CD_VOL);
|
||||
em28xx_cvol_new(card, dev, "AUX", AC97_AUX_VOL);
|
||||
em28xx_cvol_new(card, dev, "PCM", AC97_PCM_OUT_VOL);
|
||||
em28xx_cvol_new(card, dev, "Video", AC97_VIDEO);
|
||||
em28xx_cvol_new(card, dev, "Line In", AC97_LINE);
|
||||
em28xx_cvol_new(card, dev, "Phone", AC97_PHONE);
|
||||
em28xx_cvol_new(card, dev, "Microphone", AC97_MIC);
|
||||
em28xx_cvol_new(card, dev, "CD", AC97_CD);
|
||||
em28xx_cvol_new(card, dev, "AUX", AC97_AUX);
|
||||
em28xx_cvol_new(card, dev, "PCM", AC97_PCM);
|
||||
|
||||
em28xx_cvol_new(card, dev, "Master", AC97_MASTER_VOL);
|
||||
em28xx_cvol_new(card, dev, "Line", AC97_LINE_LEVEL_VOL);
|
||||
em28xx_cvol_new(card, dev, "Mono", AC97_MASTER_MONO_VOL);
|
||||
em28xx_cvol_new(card, dev, "LFE", AC97_LFE_MASTER_VOL);
|
||||
em28xx_cvol_new(card, dev, "Surround", AC97_SURR_MASTER_VOL);
|
||||
em28xx_cvol_new(card, dev, "Master", AC97_MASTER);
|
||||
em28xx_cvol_new(card, dev, "Line", AC97_HEADPHONE);
|
||||
em28xx_cvol_new(card, dev, "Mono", AC97_MASTER_MONO);
|
||||
em28xx_cvol_new(card, dev, "LFE", AC97_CENTER_LFE_MASTER);
|
||||
em28xx_cvol_new(card, dev, "Surround", AC97_SURROUND_MASTER);
|
||||
}
|
||||
|
||||
err = snd_card_register(card);
|
||||
|
|
|
@ -975,12 +975,7 @@ struct em28xx_board em28xx_boards[] = {
|
|||
.name = "Terratec Cinergy HTC Stick",
|
||||
.has_dvb = 1,
|
||||
.ir_codes = RC_MAP_NEC_TERRATEC_CINERGY_XS,
|
||||
#if 0
|
||||
.tuner_type = TUNER_PHILIPS_TDA8290,
|
||||
.tuner_addr = 0x41,
|
||||
.dvb_gpio = terratec_h5_digital, /* FIXME: probably wrong */
|
||||
.tuner_gpio = terratec_h5_gpio,
|
||||
#endif
|
||||
.tuner_type = TUNER_ABSENT,
|
||||
.i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT |
|
||||
EM28XX_I2C_CLK_WAIT_ENABLE |
|
||||
EM28XX_I2C_FREQ_400_KHZ,
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <sound/ac97_codec.h>
|
||||
#include <media/v4l2-common.h>
|
||||
|
||||
#include "em28xx.h"
|
||||
|
@ -326,13 +327,13 @@ struct em28xx_vol_itable {
|
|||
};
|
||||
|
||||
static struct em28xx_vol_itable inputs[] = {
|
||||
{ EM28XX_AMUX_VIDEO, AC97_VIDEO_VOL },
|
||||
{ EM28XX_AMUX_LINE_IN, AC97_LINEIN_VOL },
|
||||
{ EM28XX_AMUX_PHONE, AC97_PHONE_VOL },
|
||||
{ EM28XX_AMUX_MIC, AC97_MIC_VOL },
|
||||
{ EM28XX_AMUX_CD, AC97_CD_VOL },
|
||||
{ EM28XX_AMUX_AUX, AC97_AUX_VOL },
|
||||
{ EM28XX_AMUX_PCM_OUT, AC97_PCM_OUT_VOL },
|
||||
{ EM28XX_AMUX_VIDEO, AC97_VIDEO },
|
||||
{ EM28XX_AMUX_LINE_IN, AC97_LINE },
|
||||
{ EM28XX_AMUX_PHONE, AC97_PHONE },
|
||||
{ EM28XX_AMUX_MIC, AC97_MIC },
|
||||
{ EM28XX_AMUX_CD, AC97_CD },
|
||||
{ EM28XX_AMUX_AUX, AC97_AUX },
|
||||
{ EM28XX_AMUX_PCM_OUT, AC97_PCM },
|
||||
};
|
||||
|
||||
static int set_ac97_input(struct em28xx *dev)
|
||||
|
@ -415,11 +416,11 @@ struct em28xx_vol_otable {
|
|||
};
|
||||
|
||||
static const struct em28xx_vol_otable outputs[] = {
|
||||
{ EM28XX_AOUT_MASTER, AC97_MASTER_VOL },
|
||||
{ EM28XX_AOUT_LINE, AC97_LINE_LEVEL_VOL },
|
||||
{ EM28XX_AOUT_MONO, AC97_MASTER_MONO_VOL },
|
||||
{ EM28XX_AOUT_LFE, AC97_LFE_MASTER_VOL },
|
||||
{ EM28XX_AOUT_SURR, AC97_SURR_MASTER_VOL },
|
||||
{ EM28XX_AOUT_MASTER, AC97_MASTER },
|
||||
{ EM28XX_AOUT_LINE, AC97_HEADPHONE },
|
||||
{ EM28XX_AOUT_MONO, AC97_MASTER_MONO },
|
||||
{ EM28XX_AOUT_LFE, AC97_CENTER_LFE_MASTER },
|
||||
{ EM28XX_AOUT_SURR, AC97_SURROUND_MASTER },
|
||||
};
|
||||
|
||||
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) {
|
||||
int vol;
|
||||
|
||||
em28xx_write_ac97(dev, AC97_POWER_DOWN_CTRL, 0x4200);
|
||||
em28xx_write_ac97(dev, AC97_EXT_AUD_CTRL, 0x0031);
|
||||
em28xx_write_ac97(dev, AC97_PCM_IN_SRATE, 0xbb80);
|
||||
em28xx_write_ac97(dev, AC97_POWERDOWN, 0x4200);
|
||||
em28xx_write_ac97(dev, AC97_EXTENDED_STATUS, 0x0031);
|
||||
em28xx_write_ac97(dev, AC97_PCM_LR_ADC_RATE, 0xbb80);
|
||||
|
||||
/* LSB: left channel - both channels with the same level */
|
||||
vol = (0x1f - dev->volume) | ((0x1f - dev->volume) << 8);
|
||||
|
@ -487,7 +488,7 @@ int em28xx_audio_analog_set(struct em28xx *dev)
|
|||
channels */
|
||||
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,
|
||||
};
|
||||
|
||||
struct drxk_config terratec_h5_drxk = {
|
||||
static struct drxk_config terratec_h5_drxk = {
|
||||
.adr = 0x29,
|
||||
.single_master = 1,
|
||||
.no_i2c_bridge = 1,
|
||||
.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,
|
||||
.single_master = 1,
|
||||
.no_i2c_bridge = 1,
|
||||
.microcode_name = "dvb-usb-hauppauge-hvr930c-drxk.fw",
|
||||
.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,
|
||||
.single_master = 1,
|
||||
.no_i2c_bridge = 1,
|
||||
};
|
||||
|
||||
struct drxk_config pctv_520e_drxk = {
|
||||
static struct drxk_config pctv_520e_drxk = {
|
||||
.adr = 0x29,
|
||||
.single_master = 1,
|
||||
.microcode_name = "dvb-demod-drxk-pctv.fw",
|
||||
.qam_demod_parameter_count = 2,
|
||||
.chunk_size = 58,
|
||||
.antenna_dvbt = true, /* 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);
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
/*
|
||||
|
@ -944,7 +1011,6 @@ static int em28xx_dvb_init(struct em28xx *dev)
|
|||
break;
|
||||
}
|
||||
case EM2884_BOARD_TERRATEC_H5:
|
||||
case EM2884_BOARD_CINERGY_HTC_STICK:
|
||||
terratec_h5_init(dev);
|
||||
|
||||
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;
|
||||
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:
|
||||
em28xx_errdev("/2: The frontend of your DVB/ATSC card"
|
||||
" isn't supported yet\n");
|
||||
|
|
|
@ -475,6 +475,7 @@ static struct i2c_client em28xx_client_template = {
|
|||
*/
|
||||
static char *i2c_devs[128] = {
|
||||
[0x4a >> 1] = "saa7113h",
|
||||
[0x52 >> 1] = "drxk",
|
||||
[0x60 >> 1] = "remote IR sensor",
|
||||
[0x8e >> 1] = "remote IR sensor",
|
||||
[0x86 >> 1] = "tda9887",
|
||||
|
|
|
@ -345,7 +345,7 @@ static void em28xx_ir_stop(struct rc_dev *rc)
|
|||
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;
|
||||
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 */
|
||||
#define EM202_EXT_MODEM_CTRL 0x3e
|
||||
#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;
|
||||
}
|
||||
|
||||
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 = {
|
||||
.vidioc_querycap = ivtv_querycap,
|
||||
.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);
|
||||
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);
|
||||
long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -50,7 +50,7 @@ static const struct v4l2_file_operations ivtv_v4l2_enc_fops = {
|
|||
.read = ivtv_v4l2_read,
|
||||
.write = ivtv_v4l2_write,
|
||||
.open = ivtv_v4l2_open,
|
||||
.unlocked_ioctl = ivtv_v4l2_ioctl,
|
||||
.unlocked_ioctl = video_ioctl2,
|
||||
.release = ivtv_v4l2_close,
|
||||
.poll = ivtv_v4l2_enc_poll,
|
||||
};
|
||||
|
@ -60,7 +60,7 @@ static const struct v4l2_file_operations ivtv_v4l2_dec_fops = {
|
|||
.read = ivtv_v4l2_read,
|
||||
.write = ivtv_v4l2_write,
|
||||
.open = ivtv_v4l2_open,
|
||||
.unlocked_ioctl = ivtv_v4l2_ioctl,
|
||||
.unlocked_ioctl = video_ioctl2,
|
||||
.release = ivtv_v4l2_close,
|
||||
.poll = ivtv_v4l2_dec_poll,
|
||||
};
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
config VIDEO_M5MOLS
|
||||
tristate "Fujitsu M-5MOLS 8MP sensor support"
|
||||
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
|
||||
depends on MEDIA_CAMERA_SUPPORT
|
||||
---help---
|
||||
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_NUM_TILES 8
|
||||
|
||||
/* Flags that indicate processing mode */
|
||||
#define MEM2MEM_HFLIP (1 << 0)
|
||||
#define MEM2MEM_VFLIP (1 << 1)
|
||||
|
||||
#define dprintk(dev, fmt, arg...) \
|
||||
v4l2_dbg(1, 1, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
|
||||
|
||||
|
@ -115,6 +119,24 @@ enum {
|
|||
|
||||
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,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Transaction time (msec)",
|
||||
|
@ -181,6 +203,9 @@ struct m2mtest_ctx {
|
|||
/* Abort requested by m2m */
|
||||
int aborting;
|
||||
|
||||
/* Processing mode */
|
||||
int mode;
|
||||
|
||||
struct v4l2_m2m_ctx *m2m_ctx;
|
||||
|
||||
/* 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;
|
||||
w = 0;
|
||||
|
||||
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;
|
||||
switch (ctx->mode) {
|
||||
case MEM2MEM_HFLIP | MEM2MEM_VFLIP:
|
||||
p_out += bytesperline * height - bytes_left;
|
||||
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;
|
||||
}
|
||||
++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;
|
||||
|
@ -648,6 +738,14 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
|
|||
struct m2mtest_ctx *ctx = priv;
|
||||
|
||||
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:
|
||||
ctrl->value = ctx->transtime;
|
||||
break;
|
||||
|
@ -691,6 +789,20 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
|
|||
return ret;
|
||||
|
||||
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:
|
||||
ctx->transtime = ctrl->value;
|
||||
break;
|
||||
|
@ -861,6 +973,7 @@ static int m2mtest_open(struct file *file)
|
|||
ctx->translen = MEM2MEM_DEF_TRANSLEN;
|
||||
ctx->transtime = MEM2MEM_DEF_TRANSTIME;
|
||||
ctx->num_processed = 0;
|
||||
ctx->mode = 0;
|
||||
|
||||
ctx->q_data[V4L2_M2M_SRC].fmt = &formats[0];
|
||||
ctx->q_data[V4L2_M2M_DST].fmt = &formats[0];
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
|
|
|
@ -688,11 +688,17 @@ static const struct v4l2_subdev_ops mt9m032_ops = {
|
|||
static int mt9m032_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *devid)
|
||||
{
|
||||
struct mt9m032_platform_data *pdata = client->dev.platform_data;
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
struct mt9m032 *sensor;
|
||||
int chip_version;
|
||||
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)) {
|
||||
dev_warn(&client->dev,
|
||||
"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);
|
||||
|
||||
sensor->pdata = client->dev.platform_data;
|
||||
sensor->pdata = pdata;
|
||||
|
||||
v4l2_i2c_subdev_init(&sensor->subdev, client, &mt9m032_ops);
|
||||
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.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_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,
|
||||
MT9M032_SHUTTER_WIDTH_MAX, 1,
|
||||
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) {
|
||||
ret = sensor->ctrls.error;
|
||||
|
|
|
@ -214,7 +214,6 @@ struct mt9m111 {
|
|||
int power_count;
|
||||
const struct mt9m111_datafmt *fmt;
|
||||
int lastpage; /* PageMap cache value */
|
||||
unsigned char datawidth;
|
||||
};
|
||||
|
||||
/* 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->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_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_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
|
||||
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)
|
||||
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;
|
||||
|
||||
/* Configure the pixel clock polarity */
|
||||
if (pdata && pdata->clk_pol) {
|
||||
if (pdata->clk_pol) {
|
||||
ret = mt9t001_write(client, MT9T001_PIXEL_CLOCK,
|
||||
MT9T001_PIXEL_CLOCK_INVERT);
|
||||
if (ret < 0)
|
||||
|
@ -715,10 +715,16 @@ static int mt9t001_video_probe(struct i2c_client *client)
|
|||
static int mt9t001_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *did)
|
||||
{
|
||||
struct mt9t001_platform_data *pdata = client->dev.platform_data;
|
||||
struct mt9t001 *mt9t001;
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
if (pdata == NULL) {
|
||||
dev_err(&client->dev, "No platform data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!i2c_check_functionality(client->adapter,
|
||||
I2C_FUNC_SMBUS_WORD_DATA)) {
|
||||
dev_warn(&client->adapter->dev,
|
||||
|
@ -735,7 +741,7 @@ static int mt9t001_probe(struct i2c_client *client,
|
|||
return -ENOMEM;
|
||||
|
||||
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_CID_EXPOSURE, MT9T001_SHUTTER_WIDTH_MIN,
|
||||
|
@ -743,6 +749,9 @@ static int mt9t001_probe(struct i2c_client *client,
|
|||
MT9T001_SHUTTER_WIDTH_DEF);
|
||||
v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops,
|
||||
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)
|
||||
v4l2_ctrl_new_custom(&mt9t001->ctrls, &mt9t001_ctrls[i], NULL);
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
|
|
|
@ -2014,7 +2014,7 @@ static int ccdc_get_selection(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
|
|||
return -EINVAL;
|
||||
|
||||
switch (sel->target) {
|
||||
case V4L2_SUBDEV_SEL_TGT_CROP_BOUNDS:
|
||||
case V4L2_SEL_TGT_CROP_BOUNDS:
|
||||
sel->r.left = 0;
|
||||
sel->r.top = 0;
|
||||
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);
|
||||
break;
|
||||
|
||||
case V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL:
|
||||
case V4L2_SEL_TGT_CROP:
|
||||
sel->r = *__ccdc_get_crop(ccdc, fh, sel->which);
|
||||
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 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)
|
||||
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
|
||||
* 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);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1949,7 +1949,7 @@ static int preview_get_selection(struct v4l2_subdev *sd,
|
|||
return -EINVAL;
|
||||
|
||||
switch (sel->target) {
|
||||
case V4L2_SUBDEV_SEL_TGT_CROP_BOUNDS:
|
||||
case V4L2_SEL_TGT_CROP_BOUNDS:
|
||||
sel->r.left = 0;
|
||||
sel->r.top = 0;
|
||||
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);
|
||||
break;
|
||||
|
||||
case V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL:
|
||||
case V4L2_SEL_TGT_CROP:
|
||||
sel->r = *__preview_get_crop(prev, fh, sel->which);
|
||||
break;
|
||||
|
||||
|
@ -1988,7 +1988,7 @@ static int preview_set_selection(struct v4l2_subdev *sd,
|
|||
struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
|
||||
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)
|
||||
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
|
||||
* 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);
|
||||
return 0;
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue