Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media

Pull media updates from Mauro Carvalho Chehab:
 "This is the first part of the media patches for v3.6.

  This patch series contain:
   - new DVB frontend: rtl2832
   - new video drivers: adv7393
   - some unused files got removed
   - a selection API cleanup between V4L2 and V4L2 subdev API's
   - a major redesign at v4l-ioctl2, in order to clean it up
   - several driver fixes and improvements."

* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (174 commits)
  v4l: Export v4l2-common.h in include/linux/Kbuild
  media: Revert "[media] Terratec Cinergy S2 USB HD Rev.2"
  [media] media: Use pr_info not homegrown pr_reg macro
  [media] Terratec Cinergy S2 USB HD Rev.2
  [media] v4l: Correct conflicting V4L2 subdev selection API documentation
  [media] Feature removal: V4L2 selections API target and flag definitions
  [media] v4l: Unify selection flags documentation
  [media] v4l: Unify selection flags
  [media] v4l: Common documentation for selection targets
  [media] v4l: Unify selection targets across V4L2 and V4L2 subdev interfaces
  [media] v4l: Remove "_ACTUAL" from subdev selection API target definition names
  [media] V4L: Remove "_ACTIVE" from the selection target name definitions
  [media] media: dvb-usb: print mac address via native %pM
  [media] s5p-tv: Use module_i2c_driver in sii9234_drv.c file
  [media] media: gpio-ir-recv: add allowed_protos for platform data
  [media] s5p-jpeg: Use module_platform_driver in jpeg-core.c file
  [media] saa7134: fix spelling of detach in label
  [media] cx88-blackbird: replace ioctl by unlocked_ioctl
  [media] cx88: don't use current_norm
  [media] cx88: fix a number of v4l2-compliance violations
  ...
This commit is contained in:
Linus Torvalds 2012-07-30 19:03:41 -07:00
commit 6df419e45d
156 changed files with 7730 additions and 5669 deletions

View File

@ -194,7 +194,7 @@ in the frequency range from 87,5 to 108,0 MHz</title>
<corpauthor>National Radio Systems Committee <corpauthor>National Radio Systems Committee
(<ulink url="http://www.nrscstandards.org">http://www.nrscstandards.org</ulink>)</corpauthor> (<ulink url="http://www.nrscstandards.org">http://www.nrscstandards.org</ulink>)</corpauthor>
</authorgroup> </authorgroup>
<title>NTSC-4: United States RBDS Standard</title> <title>NRSC-4: United States RBDS Standard</title>
</biblioentry> </biblioentry>
<biblioentry id="iso12232"> <biblioentry id="iso12232">

View File

@ -464,14 +464,14 @@ The <structfield>type</structfield> field of the respective
<structfield>tuner</structfield> field contains the index number of <structfield>tuner</structfield> field contains the index number of
the tuner.</para> the tuner.</para>
<para>Radio devices have exactly one tuner with index zero, no <para>Radio input devices have exactly one tuner with index zero, no
video inputs.</para> video inputs.</para>
<para>To query and change tuner properties applications use the <para>To query and change tuner properties applications use the
&VIDIOC-G-TUNER; and &VIDIOC-S-TUNER; ioctl, respectively. The &VIDIOC-G-TUNER; and &VIDIOC-S-TUNER; ioctl, respectively. The
&v4l2-tuner; returned by <constant>VIDIOC_G_TUNER</constant> also &v4l2-tuner; returned by <constant>VIDIOC_G_TUNER</constant> also
contains signal status information applicable when the tuner of the contains signal status information applicable when the tuner of the
current video input, or a radio tuner is queried. Note that current video or radio input is queried. Note that
<constant>VIDIOC_S_TUNER</constant> does not switch the current tuner, <constant>VIDIOC_S_TUNER</constant> does not switch the current tuner,
when there is more than one at all. The tuner is solely determined by when there is more than one at all. The tuner is solely determined by
the current video input. Drivers must support both ioctls and set the the current video input. Drivers must support both ioctls and set the
@ -491,8 +491,17 @@ the modulator. The <structfield>type</structfield> field of the
respective &v4l2-output; returned by the &VIDIOC-ENUMOUTPUT; ioctl is respective &v4l2-output; returned by the &VIDIOC-ENUMOUTPUT; ioctl is
set to <constant>V4L2_OUTPUT_TYPE_MODULATOR</constant> and its set to <constant>V4L2_OUTPUT_TYPE_MODULATOR</constant> and its
<structfield>modulator</structfield> field contains the index number <structfield>modulator</structfield> field contains the index number
of the modulator. This specification does not define radio output of the modulator.</para>
devices.</para>
<para>Radio output devices have exactly one modulator with index
zero, no video outputs.</para>
<para>A video or radio device cannot support both a tuner and a
modulator. Two separate device nodes will have to be used for such
hardware, one that supports the tuner functionality and one that supports
the modulator functionality. The reason is a limitation with the
&VIDIOC-S-FREQUENCY; ioctl where you cannot specify whether the frequency
is for a tuner or a modulator.</para>
<para>To query and change modulator properties applications use <para>To query and change modulator properties applications use
the &VIDIOC-G-MODULATOR; and &VIDIOC-S-MODULATOR; ioctl. Note that the &VIDIOC-G-MODULATOR; and &VIDIOC-S-MODULATOR; ioctl. Note that

View File

@ -2377,10 +2377,11 @@ that used it. It was originally scheduled for removal in 2.6.35.
<para>V4L2_CTRL_FLAG_VOLATILE was added to signal volatile controls to userspace.</para> <para>V4L2_CTRL_FLAG_VOLATILE was added to signal volatile controls to userspace.</para>
</listitem> </listitem>
<listitem> <listitem>
<para>Add selection API for extended control over cropping and <para>Add selection API for extended control over cropping
composing. Does not affect the compatibility of current drivers and and composing. Does not affect the compatibility of current
applications. See <link linkend="selection-api"> selection API </link> for drivers and applications. See <link
details.</para> linkend="selection-api"> selection API </link> for
details.</para>
</listitem> </listitem>
</orderedlist> </orderedlist>
</section> </section>
@ -2458,6 +2459,18 @@ details.</para>
</orderedlist> </orderedlist>
</section> </section>
<section>
<title>V4L2 in Linux 3.5</title>
<orderedlist>
<listitem>
<para>Replaced <structfield>input</structfield> in
<structname>v4l2_buffer</structname> by
<structfield>reserved2</structfield> and removed
<constant>V4L2_BUF_FLAG_INPUT</constant>.</para>
</listitem>
</orderedlist>
</section>
<section id="other"> <section id="other">
<title>Relation of V4L2 to other Linux multimedia APIs</title> <title>Relation of V4L2 to other Linux multimedia APIs</title>

View File

@ -276,7 +276,7 @@
</para> </para>
</section> </section>
<section> <section id="v4l2-subdev-selections">
<title>Selections: cropping, scaling and composition</title> <title>Selections: cropping, scaling and composition</title>
<para>Many sub-devices support cropping frames on their input or output <para>Many sub-devices support cropping frames on their input or output
@ -290,8 +290,8 @@
size. Both the coordinates and sizes are expressed in pixels.</para> size. Both the coordinates and sizes are expressed in pixels.</para>
<para>As for pad formats, drivers store try and active <para>As for pad formats, drivers store try and active
rectangles for the selection targets of ACTUAL type <xref rectangles for the selection targets <xref
linkend="v4l2-subdev-selection-targets">.</xref></para> linkend="v4l2-selections-common" />.</para>
<para>On sink pads, cropping is applied relative to the <para>On sink pads, cropping is applied relative to the
current pad format. The pad format represents the image size as current pad format. The pad format represents the image size as
@ -308,7 +308,7 @@
<para>Scaling support is optional. When supported by a subdev, <para>Scaling support is optional. When supported by a subdev,
the crop rectangle on the subdev's sink pad is scaled to the the crop rectangle on the subdev's sink pad is scaled to the
size configured using the &VIDIOC-SUBDEV-S-SELECTION; IOCTL size configured using the &VIDIOC-SUBDEV-S-SELECTION; IOCTL
using <constant>V4L2_SUBDEV_SEL_COMPOSE_ACTUAL</constant> using <constant>V4L2_SEL_TGT_COMPOSE</constant>
selection target on the same pad. If the subdev supports scaling selection target on the same pad. If the subdev supports scaling
but not composing, the top and left values are not used and must but not composing, the top and left values are not used and must
always be set to zero.</para> always be set to zero.</para>
@ -323,32 +323,32 @@
<para>The drivers should always use the closest possible <para>The drivers should always use the closest possible
rectangle the user requests on all selection targets, unless rectangle the user requests on all selection targets, unless
specifically told otherwise. specifically told otherwise.
<constant>V4L2_SUBDEV_SEL_FLAG_SIZE_GE</constant> and <constant>V4L2_SEL_FLAG_GE</constant> and
<constant>V4L2_SUBDEV_SEL_FLAG_SIZE_LE</constant> flags may be <constant>V4L2_SEL_FLAG_LE</constant> flags may be
used to round the image size either up or down. <xref used to round the image size either up or down. <xref
linkend="v4l2-subdev-selection-flags"></xref></para> linkend="v4l2-selection-flags" /></para>
</section> </section>
<section> <section>
<title>Types of selection targets</title> <title>Types of selection targets</title>
<section> <section>
<title>ACTUAL targets</title> <title>Actual targets</title>
<para>ACTUAL targets reflect the actual hardware configuration <para>Actual targets (without a postfix) reflect the actual
at any point of time. There is a BOUNDS target hardware configuration at any point of time. There is a BOUNDS
corresponding to every ACTUAL.</para> target corresponding to every actual target.</para>
</section> </section>
<section> <section>
<title>BOUNDS targets</title> <title>BOUNDS targets</title>
<para>BOUNDS targets is the smallest rectangle that contains <para>BOUNDS targets is the smallest rectangle that contains all
all valid ACTUAL rectangles. It may not be possible to set the valid actual rectangles. It may not be possible to set the actual
ACTUAL rectangle as large as the BOUNDS rectangle, however. rectangle as large as the BOUNDS rectangle, however. This may be
This may be because e.g. a sensor's pixel array is not because e.g. a sensor's pixel array is not rectangular but
rectangular but cross-shaped or round. The maximum size may cross-shaped or round. The maximum size may also be smaller than the
also be smaller than the BOUNDS rectangle.</para> BOUNDS rectangle.</para>
</section> </section>
</section> </section>
@ -362,7 +362,7 @@
performed by the user: the changes made will be propagated to performed by the user: the changes made will be propagated to
any subsequent stages. If this behaviour is not desired, the any subsequent stages. If this behaviour is not desired, the
user must set user must set
<constant>V4L2_SUBDEV_SEL_FLAG_KEEP_CONFIG</constant> flag. This <constant>V4L2_SEL_FLAG_KEEP_CONFIG</constant> flag. This
flag causes no propagation of the changes are allowed in any flag causes no propagation of the changes are allowed in any
circumstances. This may also cause the accessed rectangle to be circumstances. This may also cause the accessed rectangle to be
adjusted by the driver, depending on the properties of the adjusted by the driver, depending on the properties of the

View File

@ -683,14 +683,12 @@ memory, set by the application. See <xref linkend="userp" /> for details.
</row> </row>
<row> <row>
<entry>__u32</entry> <entry>__u32</entry>
<entry><structfield>input</structfield></entry> <entry><structfield>reserved2</structfield></entry>
<entry></entry> <entry></entry>
<entry>Some video capture drivers support rapid and <entry>A place holder for future extensions and custom
synchronous video input changes, a function useful for example in (driver defined) buffer types
video surveillance applications. For this purpose applications set the <constant>V4L2_BUF_TYPE_PRIVATE</constant> and higher. Applications
<constant>V4L2_BUF_FLAG_INPUT</constant> flag, and this field to the should set this to 0.</entry>
number of a video input as in &v4l2-input; field
<structfield>index</structfield>.</entry>
</row> </row>
<row> <row>
<entry>__u32</entry> <entry>__u32</entry>
@ -921,13 +919,6 @@ previous key frame.</entry>
<entry>The <structfield>timecode</structfield> field is valid. <entry>The <structfield>timecode</structfield> field is valid.
Drivers set or clear this flag when the <constant>VIDIOC_DQBUF</constant> Drivers set or clear this flag when the <constant>VIDIOC_DQBUF</constant>
ioctl is called.</entry> ioctl is called.</entry>
</row>
<row>
<entry><constant>V4L2_BUF_FLAG_INPUT</constant></entry>
<entry>0x0200</entry>
<entry>The <structfield>input</structfield> field is valid.
Applications set or clear this flag before calling the
<constant>VIDIOC_QBUF</constant> ioctl.</entry>
</row> </row>
<row> <row>
<entry><constant>V4L2_BUF_FLAG_PREPARED</constant></entry> <entry><constant>V4L2_BUF_FLAG_PREPARED</constant></entry>

View File

@ -53,11 +53,11 @@ cropping and composing rectangles have the same size.</para>
</mediaobject> </mediaobject>
</figure> </figure>
For complete list of the available selection targets see table <xref
linkend="v4l2-sel-target"/>
</section> </section>
See <xref linkend="v4l2-selection-targets" /> for more
information.
<section> <section>
<title>Configuration</title> <title>Configuration</title>
@ -74,7 +74,7 @@ cropping/composing rectangles may have to be aligned, and both the source and
the sink may have arbitrary upper and lower size limits. Therefore, as usual, the sink may have arbitrary upper and lower size limits. Therefore, as usual,
drivers are expected to adjust the requested parameters and return the actual drivers are expected to adjust the requested parameters and return the actual
values selected. An application can control the rounding behaviour using <link values selected. An application can control the rounding behaviour using <link
linkend="v4l2-sel-flags"> constraint flags </link>.</para> linkend="v4l2-selection-flags"> constraint flags </link>.</para>
<section> <section>
@ -91,7 +91,7 @@ top/left corner at position <constant> (0,0) </constant>. The rectangle's
coordinates are expressed in pixels.</para> coordinates are expressed in pixels.</para>
<para>The top left corner, width and height of the source rectangle, that is <para>The top left corner, width and height of the source rectangle, that is
the area actually sampled, is given by the <constant> V4L2_SEL_TGT_CROP_ACTIVE the area actually sampled, is given by the <constant> V4L2_SEL_TGT_CROP
</constant> target. It uses the same coordinate system as <constant> </constant> target. It uses the same coordinate system as <constant>
V4L2_SEL_TGT_CROP_BOUNDS </constant>. The active cropping area must lie V4L2_SEL_TGT_CROP_BOUNDS </constant>. The active cropping area must lie
completely inside the capture boundaries. The driver may further adjust the completely inside the capture boundaries. The driver may further adjust the
@ -111,13 +111,13 @@ height are equal to the image size set by <constant> VIDIOC_S_FMT </constant>.
</para> </para>
<para>The part of a buffer into which the image is inserted by the hardware is <para>The part of a buffer into which the image is inserted by the hardware is
controlled by the <constant> V4L2_SEL_TGT_COMPOSE_ACTIVE </constant> target. controlled by the <constant> V4L2_SEL_TGT_COMPOSE </constant> target.
The rectangle's coordinates are also expressed in the same coordinate system as The rectangle's coordinates are also expressed in the same coordinate system as
the bounds rectangle. The composing rectangle must lie completely inside bounds the bounds rectangle. The composing rectangle must lie completely inside bounds
rectangle. The driver must adjust the composing rectangle to fit to the rectangle. The driver must adjust the composing rectangle to fit to the
bounding limits. Moreover, the driver can perform other adjustments according bounding limits. Moreover, the driver can perform other adjustments according
to hardware limitations. The application can control rounding behaviour using to hardware limitations. The application can control rounding behaviour using
<link linkend="v4l2-sel-flags"> constraint flags </link>.</para> <link linkend="v4l2-selection-flags"> constraint flags </link>.</para>
<para>For capture devices the default composing rectangle is queried using <para>For capture devices the default composing rectangle is queried using
<constant> V4L2_SEL_TGT_COMPOSE_DEFAULT </constant>. It is usually equal to the <constant> V4L2_SEL_TGT_COMPOSE_DEFAULT </constant>. It is usually equal to the
@ -125,7 +125,7 @@ bounding rectangle.</para>
<para>The part of a buffer that is modified by the hardware is given by <para>The part of a buffer that is modified by the hardware is given by
<constant> V4L2_SEL_TGT_COMPOSE_PADDED </constant>. It contains all pixels <constant> V4L2_SEL_TGT_COMPOSE_PADDED </constant>. It contains all pixels
defined using <constant> V4L2_SEL_TGT_COMPOSE_ACTIVE </constant> plus all defined using <constant> V4L2_SEL_TGT_COMPOSE </constant> plus all
padding data modified by hardware during insertion process. All pixels outside padding data modified by hardware during insertion process. All pixels outside
this rectangle <emphasis>must not</emphasis> be changed by the hardware. The this rectangle <emphasis>must not</emphasis> be changed by the hardware. The
content of pixels that lie inside the padded area but outside active area is content of pixels that lie inside the padded area but outside active area is
@ -153,7 +153,7 @@ specified using <constant> VIDIOC_S_FMT </constant> ioctl.</para>
<para>The top left corner, width and height of the source rectangle, that is <para>The top left corner, width and height of the source rectangle, that is
the area from which image date are processed by the hardware, is given by the the area from which image date are processed by the hardware, is given by the
<constant> V4L2_SEL_TGT_CROP_ACTIVE </constant>. Its coordinates are expressed <constant> V4L2_SEL_TGT_CROP </constant>. Its coordinates are expressed
in in the same coordinate system as the bounds rectangle. The active cropping in in the same coordinate system as the bounds rectangle. The active cropping
area must lie completely inside the crop boundaries and the driver may further area must lie completely inside the crop boundaries and the driver may further
adjust the requested size and/or position according to hardware adjust the requested size and/or position according to hardware
@ -165,7 +165,7 @@ bounding rectangle.</para>
<para>The part of a video signal or graphics display where the image is <para>The part of a video signal or graphics display where the image is
inserted by the hardware is controlled by <constant> inserted by the hardware is controlled by <constant>
V4L2_SEL_TGT_COMPOSE_ACTIVE </constant> target. The rectangle's coordinates V4L2_SEL_TGT_COMPOSE </constant> target. The rectangle's coordinates
are expressed in pixels. The composing rectangle must lie completely inside the are expressed in pixels. The composing rectangle must lie completely inside the
bounds rectangle. The driver must adjust the area to fit to the bounding bounds rectangle. The driver must adjust the area to fit to the bounding
limits. Moreover, the driver can perform other adjustments according to limits. Moreover, the driver can perform other adjustments according to
@ -184,7 +184,7 @@ such a padded area is driver-dependent feature not covered by this document.
Driver developers are encouraged to keep padded rectangle equal to active one. Driver developers are encouraged to keep padded rectangle equal to active one.
The padded target is accessed by the <constant> V4L2_SEL_TGT_COMPOSE_PADDED The padded target is accessed by the <constant> V4L2_SEL_TGT_COMPOSE_PADDED
</constant> identifier. It must contain all pixels from the <constant> </constant> identifier. It must contain all pixels from the <constant>
V4L2_SEL_TGT_COMPOSE_ACTIVE </constant> target.</para> V4L2_SEL_TGT_COMPOSE </constant> target.</para>
</section> </section>
@ -193,8 +193,8 @@ V4L2_SEL_TGT_COMPOSE_ACTIVE </constant> target.</para>
<title>Scaling control</title> <title>Scaling control</title>
<para>An application can detect if scaling is performed by comparing the width <para>An application can detect if scaling is performed by comparing the width
and the height of rectangles obtained using <constant> V4L2_SEL_TGT_CROP_ACTIVE and the height of rectangles obtained using <constant> V4L2_SEL_TGT_CROP
</constant> and <constant> V4L2_SEL_TGT_COMPOSE_ACTIVE </constant> targets. If </constant> and <constant> V4L2_SEL_TGT_COMPOSE </constant> targets. If
these are not equal then the scaling is applied. The application can compute these are not equal then the scaling is applied. The application can compute
the scaling ratios using these values.</para> the scaling ratios using these values.</para>
@ -252,7 +252,7 @@ area)</para>
ret = ioctl(fd, &VIDIOC-G-SELECTION;, &amp;sel); ret = ioctl(fd, &VIDIOC-G-SELECTION;, &amp;sel);
if (ret) if (ret)
exit(-1); exit(-1);
sel.target = V4L2_SEL_TGT_CROP_ACTIVE; sel.target = V4L2_SEL_TGT_CROP;
ret = ioctl(fd, &VIDIOC-S-SELECTION;, &amp;sel); ret = ioctl(fd, &VIDIOC-S-SELECTION;, &amp;sel);
if (ret) if (ret)
exit(-1); exit(-1);
@ -281,7 +281,7 @@ area)</para>
r.left = sel.r.width / 4; r.left = sel.r.width / 4;
r.top = sel.r.height / 4; r.top = sel.r.height / 4;
sel.r = r; sel.r = r;
sel.target = V4L2_SEL_TGT_COMPOSE_ACTIVE; sel.target = V4L2_SEL_TGT_COMPOSE;
sel.flags = V4L2_SEL_FLAG_LE; sel.flags = V4L2_SEL_FLAG_LE;
ret = ioctl(fd, &VIDIOC-S-SELECTION;, &amp;sel); ret = ioctl(fd, &VIDIOC-S-SELECTION;, &amp;sel);
if (ret) if (ret)
@ -298,11 +298,11 @@ V4L2_BUF_TYPE_VIDEO_OUTPUT </constant> for other devices</para>
&v4l2-selection; compose = { &v4l2-selection; compose = {
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT, .type = V4L2_BUF_TYPE_VIDEO_OUTPUT,
.target = V4L2_SEL_TGT_COMPOSE_ACTIVE, .target = V4L2_SEL_TGT_COMPOSE,
}; };
&v4l2-selection; crop = { &v4l2-selection; crop = {
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT, .type = V4L2_BUF_TYPE_VIDEO_OUTPUT,
.target = V4L2_SEL_TGT_CROP_ACTIVE, .target = V4L2_SEL_TGT_CROP,
}; };
double hscale, vscale; double hscale, vscale;

View 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 &lt;&lt; 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 &lt;&lt; 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 &lt;&lt; 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>

View File

@ -589,6 +589,11 @@ and discussions on the V4L mailing list.</revremark>
&sub-write; &sub-write;
</appendix> </appendix>
<appendix>
<title>Common definitions for V4L2 and V4L2 subdev interfaces</title>
&sub-selections-common;
</appendix>
<appendix id="videodev"> <appendix id="videodev">
<title>Video For Linux Two Header File</title> <title>Video For Linux Two Header File</title>
&sub-videodev2-h; &sub-videodev2-h;

View File

@ -97,7 +97,13 @@ information.</para>
<row> <row>
<entry>__u32</entry> <entry>__u32</entry>
<entry><structfield>count</structfield></entry> <entry><structfield>count</structfield></entry>
<entry>The number of buffers requested or granted.</entry> <entry>The number of buffers requested or granted. If count == 0, then
<constant>VIDIOC_CREATE_BUFS</constant> will set <structfield>index</structfield>
to the current number of created buffers, and it will check the validity of
<structfield>memory</structfield> and <structfield>format.type</structfield>.
If those are invalid -1 is returned and errno is set to &EINVAL;,
otherwise <constant>VIDIOC_CREATE_BUFS</constant> returns 0. It will
never set errno to &EBUSY; in this particular case.</entry>
</row> </row>
<row> <row>
<entry>__u32</entry> <entry>__u32</entry>

View File

@ -135,6 +135,12 @@ bounds or the value in the <structfield>type</structfield> field is
wrong.</para> wrong.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><errorcode>EBUSY</errorcode></term>
<listitem>
<para>A hardware seek is in progress.</para>
</listitem>
</varlistentry>
</variablelist> </variablelist>
</refsect1> </refsect1>
</refentry> </refentry>

View File

@ -65,9 +65,9 @@ Do not use multiplanar buffers. Use <constant> V4L2_BUF_TYPE_VIDEO_CAPTURE
</constant>. Use <constant> V4L2_BUF_TYPE_VIDEO_OUTPUT </constant> instead of </constant>. Use <constant> V4L2_BUF_TYPE_VIDEO_OUTPUT </constant> instead of
<constant> V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE </constant>. The next step is <constant> V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE </constant>. The next step is
setting the value of &v4l2-selection; <structfield>target</structfield> field setting the value of &v4l2-selection; <structfield>target</structfield> field
to <constant> V4L2_SEL_TGT_CROP_ACTIVE </constant> (<constant> to <constant> V4L2_SEL_TGT_CROP </constant> (<constant>
V4L2_SEL_TGT_COMPOSE_ACTIVE </constant>). Please refer to table <xref V4L2_SEL_TGT_COMPOSE </constant>). Please refer to table <xref
linkend="v4l2-sel-target" /> or <xref linkend="selection-api" /> for additional linkend="v4l2-selections-common" /> or <xref linkend="selection-api" /> for additional
targets. The <structfield>flags</structfield> and <structfield>reserved targets. The <structfield>flags</structfield> and <structfield>reserved
</structfield> fields of &v4l2-selection; are ignored and they must be filled </structfield> fields of &v4l2-selection; are ignored and they must be filled
with zeros. The driver fills the rest of the structure or with zeros. The driver fills the rest of the structure or
@ -86,9 +86,9 @@ use multiplanar buffers. Use <constant> V4L2_BUF_TYPE_VIDEO_CAPTURE
</constant>. Use <constant> V4L2_BUF_TYPE_VIDEO_OUTPUT </constant> instead of </constant>. Use <constant> V4L2_BUF_TYPE_VIDEO_OUTPUT </constant> instead of
<constant> V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE </constant>. The next step is <constant> V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE </constant>. The next step is
setting the value of &v4l2-selection; <structfield>target</structfield> to setting the value of &v4l2-selection; <structfield>target</structfield> to
<constant>V4L2_SEL_TGT_CROP_ACTIVE</constant> (<constant> <constant>V4L2_SEL_TGT_CROP</constant> (<constant>
V4L2_SEL_TGT_COMPOSE_ACTIVE </constant>). Please refer to table <xref V4L2_SEL_TGT_COMPOSE </constant>). Please refer to table <xref
linkend="v4l2-sel-target" /> or <xref linkend="selection-api" /> for additional linkend="v4l2-selections-common" /> or <xref linkend="selection-api" /> for additional
targets. The &v4l2-rect; <structfield>r</structfield> rectangle need to be targets. The &v4l2-rect; <structfield>r</structfield> rectangle need to be
set to the desired active area. Field &v4l2-selection; <structfield> reserved set to the desired active area. Field &v4l2-selection; <structfield> reserved
</structfield> is ignored and must be filled with zeros. The driver may adjust </structfield> is ignored and must be filled with zeros. The driver may adjust
@ -154,74 +154,8 @@ exist no rectangle </emphasis> that satisfies the constraints.</para>
</refsect1> </refsect1>
<refsect1> <para>Selection targets and flags are documented in <xref
<table frame="none" pgwide="1" id="v4l2-sel-target"> linkend="v4l2-selections-common"/>.</para>
<title>Selection targets.</title>
<tgroup cols="3">
&cs-def;
<tbody valign="top">
<row>
<entry><constant>V4L2_SEL_TGT_CROP_ACTIVE</constant></entry>
<entry>0x0000</entry>
<entry>The area that is currently cropped by hardware.</entry>
</row>
<row>
<entry><constant>V4L2_SEL_TGT_CROP_DEFAULT</constant></entry>
<entry>0x0001</entry>
<entry>Suggested cropping rectangle that covers the "whole picture".</entry>
</row>
<row>
<entry><constant>V4L2_SEL_TGT_CROP_BOUNDS</constant></entry>
<entry>0x0002</entry>
<entry>Limits for the cropping rectangle.</entry>
</row>
<row>
<entry><constant>V4L2_SEL_TGT_COMPOSE_ACTIVE</constant></entry>
<entry>0x0100</entry>
<entry>The area to which data is composed by hardware.</entry>
</row>
<row>
<entry><constant>V4L2_SEL_TGT_COMPOSE_DEFAULT</constant></entry>
<entry>0x0101</entry>
<entry>Suggested composing rectangle that covers the "whole picture".</entry>
</row>
<row>
<entry><constant>V4L2_SEL_TGT_COMPOSE_BOUNDS</constant></entry>
<entry>0x0102</entry>
<entry>Limits for the composing rectangle.</entry>
</row>
<row>
<entry><constant>V4L2_SEL_TGT_COMPOSE_PADDED</constant></entry>
<entry>0x0103</entry>
<entry>The active area and all padding pixels that are inserted or modified by hardware.</entry>
</row>
</tbody>
</tgroup>
</table>
</refsect1>
<refsect1>
<table frame="none" pgwide="1" id="v4l2-sel-flags">
<title>Selection constraint flags</title>
<tgroup cols="3">
&cs-def;
<tbody valign="top">
<row>
<entry><constant>V4L2_SEL_FLAG_GE</constant></entry>
<entry>0x00000001</entry>
<entry>Indicates that the adjusted rectangle must contain the original
&v4l2-selection; <structfield>r</structfield> rectangle.</entry>
</row>
<row>
<entry><constant>V4L2_SEL_FLAG_LE</constant></entry>
<entry>0x00000002</entry>
<entry>Indicates that the adjusted rectangle must be inside the original
&v4l2-rect; <structfield>r</structfield> rectangle.</entry>
</row>
</tbody>
</tgroup>
</table>
</refsect1>
<section> <section>
<figure id="sel-const-adjust"> <figure id="sel-const-adjust">
@ -252,14 +186,14 @@ exist no rectangle </emphasis> that satisfies the constraints.</para>
<row> <row>
<entry>__u32</entry> <entry>__u32</entry>
<entry><structfield>target</structfield></entry> <entry><structfield>target</structfield></entry>
<entry>Used to select between <link linkend="v4l2-sel-target"> cropping <entry>Used to select between <link linkend="v4l2-selections-common"> cropping
and composing rectangles</link>.</entry> and composing rectangles</link>.</entry>
</row> </row>
<row> <row>
<entry>__u32</entry> <entry>__u32</entry>
<entry><structfield>flags</structfield></entry> <entry><structfield>flags</structfield></entry>
<entry>Flags controlling the selection rectangle adjustments, refer to <entry>Flags controlling the selection rectangle adjustments, refer to
<link linkend="v4l2-sel-flags">selection flags</link>.</entry> <link linkend="v4l2-selection-flags">selection flags</link>.</entry>
</row> </row>
<row> <row>
<entry>&v4l2-rect;</entry> <entry>&v4l2-rect;</entry>

View File

@ -275,6 +275,18 @@ can or must be switched. (B/G PAL tuners for example are typically not
see the description of ioctl &VIDIOC-ENUMINPUT; for details. Only see the description of ioctl &VIDIOC-ENUMINPUT; for details. Only
<constant>V4L2_TUNER_ANALOG_TV</constant> tuners can have this capability.</entry> <constant>V4L2_TUNER_ANALOG_TV</constant> tuners can have this capability.</entry>
</row> </row>
<row>
<entry><constant>V4L2_TUNER_CAP_HWSEEK_BOUNDED</constant></entry>
<entry>0x0004</entry>
<entry>If set, then this tuner supports the hardware seek functionality
where the seek stops when it reaches the end of the frequency range.</entry>
</row>
<row>
<entry><constant>V4L2_TUNER_CAP_HWSEEK_WRAP</constant></entry>
<entry>0x0008</entry>
<entry>If set, then this tuner supports the hardware seek functionality
where the seek wraps around when it reaches the end of the frequency range.</entry>
</row>
<row> <row>
<entry><constant>V4L2_TUNER_CAP_STEREO</constant></entry> <entry><constant>V4L2_TUNER_CAP_STEREO</constant></entry>
<entry>0x0010</entry> <entry>0x0010</entry>

View File

@ -71,12 +71,9 @@ initialize the <structfield>bytesused</structfield>,
<structfield>field</structfield> and <structfield>field</structfield> and
<structfield>timestamp</structfield> fields, see <xref <structfield>timestamp</structfield> fields, see <xref
linkend="buffer" /> for details. linkend="buffer" /> for details.
Applications must also set <structfield>flags</structfield> to 0. If a driver Applications must also set <structfield>flags</structfield> to 0.
supports capturing from specific video inputs and you want to specify a video The <structfield>reserved2</structfield> and
input, then <structfield>flags</structfield> should be set to <structfield>reserved</structfield> fields must be set to 0. When using
<constant>V4L2_BUF_FLAG_INPUT</constant> and the field
<structfield>input</structfield> must be initialized to the desired input.
The <structfield>reserved</structfield> field must be set to 0. When using
the <link linkend="planar-apis">multi-planar API</link>, the the <link linkend="planar-apis">multi-planar API</link>, the
<structfield>m.planes</structfield> field must contain a userspace pointer <structfield>m.planes</structfield> field must contain a userspace pointer
to a filled-in array of &v4l2-plane; and the <structfield>length</structfield> to a filled-in array of &v4l2-plane; and the <structfield>length</structfield>

View File

@ -58,6 +58,9 @@ To do this applications initialize the <structfield>tuner</structfield>,
call the <constant>VIDIOC_S_HW_FREQ_SEEK</constant> ioctl with a pointer call the <constant>VIDIOC_S_HW_FREQ_SEEK</constant> ioctl with a pointer
to this structure.</para> to this structure.</para>
<para>If an error is returned, then the original frequency will
be restored.</para>
<para>This ioctl is supported if the <constant>V4L2_CAP_HW_FREQ_SEEK</constant> capability is set.</para> <para>This ioctl is supported if the <constant>V4L2_CAP_HW_FREQ_SEEK</constant> capability is set.</para>
<table pgwide="1" frame="none" id="v4l2-hw-freq-seek"> <table pgwide="1" frame="none" id="v4l2-hw-freq-seek">
@ -87,7 +90,10 @@ field and the &v4l2-tuner; <structfield>index</structfield> field.</entry>
<row> <row>
<entry>__u32</entry> <entry>__u32</entry>
<entry><structfield>wrap_around</structfield></entry> <entry><structfield>wrap_around</structfield></entry>
<entry>If non-zero, wrap around when at the end of the frequency range, else stop seeking.</entry> <entry>If non-zero, wrap around when at the end of the frequency range, else stop seeking.
The &v4l2-tuner; <structfield>capability</structfield> field will tell you what the
hardware supports.
</entry>
</row> </row>
<row> <row>
<entry>__u32</entry> <entry>__u32</entry>
@ -118,9 +124,15 @@ wrong.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><errorcode>EAGAIN</errorcode></term> <term><errorcode>ENODATA</errorcode></term>
<listitem> <listitem>
<para>The ioctl timed-out. Try again.</para> <para>The hardware seek found no channels.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><errorcode>EBUSY</errorcode></term>
<listitem>
<para>Another hardware seek is already in progress.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
</variablelist> </variablelist>

View File

@ -72,10 +72,10 @@
<section> <section>
<title>Types of selection targets</title> <title>Types of selection targets</title>
<para>There are two types of selection targets: actual and bounds. <para>There are two types of selection targets: actual and bounds. The
The ACTUAL targets are the targets which configure the hardware. actual targets are the targets which configure the hardware. The BOUNDS
The BOUNDS target will return a rectangle that contain all target will return a rectangle that contain all possible actual
possible ACTUAL rectangles.</para> rectangles.</para>
</section> </section>
<section> <section>
@ -87,71 +87,8 @@
<constant>EINVAL</constant>.</para> <constant>EINVAL</constant>.</para>
</section> </section>
<table pgwide="1" frame="none" id="v4l2-subdev-selection-targets"> <para>Selection targets and flags are documented in <xref
<title>V4L2 subdev selection targets</title> linkend="v4l2-selections-common"/>.</para>
<tgroup cols="3">
&cs-def;
<tbody valign="top">
<row>
<entry><constant>V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL</constant></entry>
<entry>0x0000</entry>
<entry>Actual crop. Defines the cropping
performed by the processing step.</entry>
</row>
<row>
<entry><constant>V4L2_SUBDEV_SEL_TGT_CROP_BOUNDS</constant></entry>
<entry>0x0002</entry>
<entry>Bounds of the crop rectangle.</entry>
</row>
<row>
<entry><constant>V4L2_SUBDEV_SEL_TGT_COMPOSE_ACTUAL</constant></entry>
<entry>0x0100</entry>
<entry>Actual compose rectangle. Used to configure scaling
on sink pads and composition on source pads.</entry>
</row>
<row>
<entry><constant>V4L2_SUBDEV_SEL_TGT_COMPOSE_BOUNDS</constant></entry>
<entry>0x0102</entry>
<entry>Bounds of the compose rectangle.</entry>
</row>
</tbody>
</tgroup>
</table>
<table pgwide="1" frame="none" id="v4l2-subdev-selection-flags">
<title>V4L2 subdev selection flags</title>
<tgroup cols="3">
&cs-def;
<tbody valign="top">
<row>
<entry><constant>V4L2_SUBDEV_SEL_FLAG_SIZE_GE</constant></entry>
<entry>(1 &lt;&lt; 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 &lt;&lt; 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 &lt;&lt; 2)</entry>
<entry>The configuration should not be propagated to any
further processing steps. If this flag is not given, the
configuration is propagated inside the subdevice to all
further processing steps.</entry>
</row>
</tbody>
</tgroup>
</table>
<table pgwide="1" frame="none" id="v4l2-subdev-selection"> <table pgwide="1" frame="none" id="v4l2-subdev-selection">
<title>struct <structname>v4l2_subdev_selection</structname></title> <title>struct <structname>v4l2_subdev_selection</structname></title>
@ -173,13 +110,13 @@
<entry>__u32</entry> <entry>__u32</entry>
<entry><structfield>target</structfield></entry> <entry><structfield>target</structfield></entry>
<entry>Target selection rectangle. See <entry>Target selection rectangle. See
<xref linkend="v4l2-subdev-selection-targets">.</xref>.</entry> <xref linkend="v4l2-selections-common" />.</entry>
</row> </row>
<row> <row>
<entry>__u32</entry> <entry>__u32</entry>
<entry><structfield>flags</structfield></entry> <entry><structfield>flags</structfield></entry>
<entry>Flags. See <entry>Flags. See
<xref linkend="v4l2-subdev-selection-flags">.</xref></entry> <xref linkend="v4l2-selection-flags" />.</entry>
</row> </row>
<row> <row>
<entry>&v4l2-rect;</entry> <entry>&v4l2-rect;</entry>

View File

@ -29,7 +29,7 @@ use IO::Handle;
"af9015", "ngene", "az6027", "lme2510_lg", "lme2510c_s7395", "af9015", "ngene", "az6027", "lme2510_lg", "lme2510c_s7395",
"lme2510c_s7395_old", "drxk", "drxk_terratec_h5", "lme2510c_s7395_old", "drxk", "drxk_terratec_h5",
"drxk_hauppauge_hvr930c", "tda10071", "it9135", "it9137", "drxk_hauppauge_hvr930c", "tda10071", "it9135", "it9137",
"drxk_pctv"); "drxk_pctv", "drxk_terratec_htc_stick", "sms1xxx_hcw");
# Check args # Check args
syntax() if (scalar(@ARGV) != 1); syntax() if (scalar(@ARGV) != 1);
@ -676,6 +676,24 @@ sub drxk_terratec_h5 {
"$fwfile" "$fwfile"
} }
sub drxk_terratec_htc_stick {
my $url = "http://ftp.terratec.de/Receiver/Cinergy_HTC_Stick/Updates/";
my $zipfile = "Cinergy_HTC_Stick_Drv_5.09.1202.00_XP_Vista_7.exe";
my $hash = "6722a2442a05423b781721fbc069ed5e";
my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 0);
my $drvfile = "Cinergy HTC Stick/BDA Driver 5.09.1202.00/Windows 32 Bit/emOEM.sys";
my $fwfile = "dvb-usb-terratec-htc-stick-drxk.fw";
checkstandard();
wgetfile($zipfile, $url . $zipfile);
verify($zipfile, $hash);
unzip($zipfile, $tmpdir);
extract("$tmpdir/$drvfile", 0x4e5c0, 42692, "$fwfile");
"$fwfile"
}
sub it9135 { sub it9135 {
my $sourcefile = "dvb-usb-it9135.zip"; my $sourcefile = "dvb-usb-it9135.zip";
my $url = "http://www.ite.com.tw/uploads/firmware/v3.6.0.0/$sourcefile"; my $url = "http://www.ite.com.tw/uploads/firmware/v3.6.0.0/$sourcefile";
@ -748,6 +766,28 @@ sub drxk_pctv {
"$fwfile"; "$fwfile";
} }
sub sms1xxx_hcw {
my $url = "http://steventoth.net/linux/sms1xxx/";
my %files = (
'sms1xxx-hcw-55xxx-dvbt-01.fw' => "afb6f9fb9a71d64392e8564ef9577e5a",
'sms1xxx-hcw-55xxx-dvbt-02.fw' => "b44807098ba26e52cbedeadc052ba58f",
'sms1xxx-hcw-55xxx-isdbt-02.fw' => "dae934eeea85225acbd63ce6cfe1c9e4",
);
checkstandard();
my $allfiles;
foreach my $fwfile (keys %files) {
wgetfile($fwfile, "$url/$fwfile");
verify($fwfile, $files{$fwfile});
$allfiles .= " $fwfile";
}
$allfiles =~ s/^\s//;
$allfiles;
}
# --------------------------------------------------------------- # ---------------------------------------------------------------
# Utilities # Utilities

View File

@ -600,3 +600,21 @@ When: June 2013
Why: Unsupported/unmaintained/unused since 2.6 Why: Unsupported/unmaintained/unused since 2.6
---------------------------- ----------------------------
What: V4L2 selections API target rectangle and flags unification, the
following definitions will be removed: V4L2_SEL_TGT_CROP_ACTIVE,
V4L2_SEL_TGT_COMPOSE_ACTIVE, V4L2_SUBDEV_SEL_*, V4L2_SUBDEV_SEL_FLAG_*
in favor of common V4L2_SEL_TGT_* and V4L2_SEL_FLAG_* definitions.
For more details see include/linux/v4l2-common.h.
When: 3.8
Why: The regular V4L2 selections and the subdev selection API originally
defined distinct names for the target rectangles and flags - V4L2_SEL_*
and V4L2_SUBDEV_SEL_*. Although, it turned out that the meaning of these
target rectangles is virtually identical and the APIs were consolidated
to use single set of names - V4L2_SEL_*. This didn't involve any ABI
changes. Alias definitions were created for the original ones to avoid
any instabilities in the user space interface. After few cycles these
backward compatibility definitions will be removed.
Who: Sylwester Nawrocki <sylvester.nawrocki@gmail.com>
----------------------------

View File

@ -594,6 +594,15 @@ You should also set these fields:
unlocked_ioctl file operation is called this lock will be taken by the unlocked_ioctl file operation is called this lock will be taken by the
core and released afterwards. See the next section for more details. core and released afterwards. See the next section for more details.
- queue: a pointer to the struct vb2_queue associated with this device node.
If queue is non-NULL, and queue->lock is non-NULL, then queue->lock is
used for the queuing ioctls (VIDIOC_REQBUFS, CREATE_BUFS, QBUF, DQBUF,
QUERYBUF, PREPARE_BUF, STREAMON and STREAMOFF) instead of the lock above.
That way the vb2 queuing framework does not have to wait for other ioctls.
This queue pointer is also used by the vb2 helper functions to check for
queuing ownership (i.e. is the filehandle calling it allowed to do the
operation).
- prio: keeps track of the priorities. Used to implement VIDIOC_G/S_PRIORITY. - prio: keeps track of the priorities. Used to implement VIDIOC_G/S_PRIORITY.
If left to NULL, then it will use the struct v4l2_prio_state in v4l2_device. If left to NULL, then it will use the struct v4l2_prio_state in v4l2_device.
If you want to have a separate priority state per (group of) device node(s), If you want to have a separate priority state per (group of) device node(s),
@ -647,47 +656,43 @@ manually set the struct media_entity type and name fields.
A reference to the entity will be automatically acquired/released when the A reference to the entity will be automatically acquired/released when the
video device is opened/closed. video device is opened/closed.
v4l2_file_operations and locking ioctls and locking
-------------------------------- ------------------
You can set a pointer to a mutex_lock in struct video_device. Usually this The V4L core provides optional locking services. The main service is the
will be either a top-level mutex or a mutex per device node. By default this lock field in struct video_device, which is a pointer to a mutex. If you set
lock will be used for unlocked_ioctl, but you can disable locking for this pointer, then that will be used by unlocked_ioctl to serialize all ioctls.
selected ioctls by calling:
void v4l2_disable_ioctl_locking(struct video_device *vdev, unsigned int cmd); If you are using the videobuf2 framework, then there is a second lock that you
can set: video_device->queue->lock. If set, then this lock will be used instead
of video_device->lock to serialize all queuing ioctls (see the previous section
for the full list of those ioctls).
E.g.: v4l2_disable_ioctl_locking(vdev, VIDIOC_DQBUF); The advantage of using a different lock for the queuing ioctls is that for some
drivers (particularly USB drivers) certain commands such as setting controls
can take a long time, so you want to use a separate lock for the buffer queuing
ioctls. That way your VIDIOC_DQBUF doesn't stall because the driver is busy
changing the e.g. exposure of the webcam.
You have to call this before you register the video_device. Of course, you can always do all the locking yourself by leaving both lock
pointers at NULL.
Particularly with USB drivers where certain commands such as setting controls If you use the old videobuf then you must pass the video_device lock to the
can take a long time you may want to do your own locking for the buffer queuing videobuf queue initialize function: if videobuf has to wait for a frame to
ioctls. arrive, then it will temporarily unlock the lock and relock it afterwards. If
your driver also waits in the code, then you should do the same to allow other
If you want still finer-grained locking then you have to set mutex_lock to NULL processes to access the device node while the first process is waiting for
and do you own locking completely. something.
It is up to the driver developer to decide which method to use. However, if
your driver has high-latency operations (for example, changing the exposure
of a USB webcam might take a long time), then you might be better off with
doing your own locking if you want to allow the user to do other things with
the device while waiting for the high-latency command to finish.
If a lock is specified then all ioctl commands will be serialized on that
lock. If you use videobuf then you must pass the same lock to the videobuf
queue initialize function: if videobuf has to wait for a frame to arrive, then
it will temporarily unlock the lock and relock it afterwards. If your driver
also waits in the code, then you should do the same to allow other processes
to access the device node while the first process is waiting for something.
In the case of videobuf2 you will need to implement the wait_prepare and In the case of videobuf2 you will need to implement the wait_prepare and
wait_finish callbacks to unlock/lock if applicable. In particular, if you use wait_finish callbacks to unlock/lock if applicable. If you use the queue->lock
the lock in struct video_device then you must unlock/lock this mutex in pointer, then you can use the helper functions vb2_ops_wait_prepare/finish.
wait_prepare and wait_finish.
The implementation of a hotplug disconnect should also take the lock before The implementation of a hotplug disconnect should also take the lock from
calling v4l2_device_disconnect. video_device before calling v4l2_device_disconnect. If you are also using
video_device->queue->lock, then you have to first lock video_device->queue->lock
followed by video_device->lock. That way you can be sure no ioctl is running
when you call v4l2_device_disconnect.
video_device registration video_device registration
------------------------- -------------------------

View File

@ -3156,8 +3156,7 @@ S: Maintained
F: drivers/media/video/gspca/t613.c F: drivers/media/video/gspca/t613.c
GSPCA USB WEBCAM DRIVER GSPCA USB WEBCAM DRIVER
M: Jean-Francois Moine <moinejf@free.fr> M: Hans de Goede <hdegoede@redhat.com>
W: http://moinejf.free.fr
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
S: Maintained S: Maintained

View File

@ -1311,6 +1311,37 @@ module_exit(i2c_exit);
* ---------------------------------------------------- * ----------------------------------------------------
*/ */
/**
* __i2c_transfer - unlocked flavor of i2c_transfer
* @adap: Handle to I2C bus
* @msgs: One or more messages to execute before STOP is issued to
* terminate the operation; each message begins with a START.
* @num: Number of messages to be executed.
*
* Returns negative errno, else the number of messages executed.
*
* Adapter lock must be held when calling this function. No debug logging
* takes place. adap->algo->master_xfer existence isn't checked.
*/
int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
{
unsigned long orig_jiffies;
int ret, try;
/* Retry automatically on arbitration loss */
orig_jiffies = jiffies;
for (ret = 0, try = 0; try <= adap->retries; try++) {
ret = adap->algo->master_xfer(adap, msgs, num);
if (ret != -EAGAIN)
break;
if (time_after(jiffies, orig_jiffies + adap->timeout))
break;
}
return ret;
}
EXPORT_SYMBOL(__i2c_transfer);
/** /**
* i2c_transfer - execute a single or combined I2C message * i2c_transfer - execute a single or combined I2C message
* @adap: Handle to I2C bus * @adap: Handle to I2C bus
@ -1325,8 +1356,7 @@ module_exit(i2c_exit);
*/ */
int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
{ {
unsigned long orig_jiffies; int ret;
int ret, try;
/* REVISIT the fault reporting model here is weak: /* REVISIT the fault reporting model here is weak:
* *
@ -1364,15 +1394,7 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
i2c_lock_adapter(adap); i2c_lock_adapter(adap);
} }
/* Retry automatically on arbitration loss */ ret = __i2c_transfer(adap, msgs, num);
orig_jiffies = jiffies;
for (ret = 0, try = 0; try <= adap->retries; try++) {
ret = adap->algo->master_xfer(adap, msgs, num);
if (ret != -EAGAIN)
break;
if (time_after(jiffies, orig_jiffies + adap->timeout))
break;
}
i2c_unlock_adapter(adap); i2c_unlock_adapter(adap);
return ret; return ret;

View File

@ -6,20 +6,82 @@ menuconfig MEDIA_SUPPORT
tristate "Multimedia support" tristate "Multimedia support"
depends on HAS_IOMEM depends on HAS_IOMEM
help help
If you want to use Video for Linux, DVB for Linux, or DAB adapters, If you want to use Webcams, Video grabber devices and/or TV devices
enable this option and other options below. enable this option and other options below.
Additional info and docs are available on the web at
<http://linuxtv.org>
if MEDIA_SUPPORT if MEDIA_SUPPORT
comment "Multimedia core support" comment "Multimedia core support"
#
# Multimedia support - automatically enable V4L2 and DVB core
#
config MEDIA_CAMERA_SUPPORT
bool "Cameras/video grabbers support"
---help---
Enable support for webcams and video grabbers.
Say Y when you have a webcam or a video capture grabber board.
config MEDIA_ANALOG_TV_SUPPORT
bool "Analog TV support"
---help---
Enable analog TV support.
Say Y when you have a TV board with analog support or with a
hybrid analog/digital TV chipset.
Note: There are several DVB cards that are based on chips that
support both analog and digital TV. Disabling this option
will disable support for them.
config MEDIA_DIGITAL_TV_SUPPORT
bool "Digital TV support"
---help---
Enable digital TV support.
Say Y when you have a board with digital support or a board with
hybrid digital TV and analog TV.
config MEDIA_RADIO_SUPPORT
bool "AM/FM radio receivers/transmitters support"
---help---
Enable AM/FM radio support.
Additional info and docs are available on the web at
<http://linuxtv.org>
Say Y when you have a board with radio support.
Note: There are several TV cards that are based on chips that
support radio reception. Disabling this option will
disable support for them.
config MEDIA_RC_SUPPORT
bool "Remote Controller support"
depends on INPUT
---help---
Enable support for Remote Controllers on Linux. This is
needed in order to support several video capture adapters,
standalone IR receivers/transmitters, and RF receivers.
Enable this option if you have a video capture board even
if you don't need IR, as otherwise, you may not be able to
compile the driver for your adapter.
Say Y when you have a TV or an IR device.
# #
# Media controller # Media controller
# Selectable only for webcam/grabbers, as other drivers don't use it
# #
config MEDIA_CONTROLLER config MEDIA_CONTROLLER
bool "Media Controller API (EXPERIMENTAL)" bool "Media Controller API (EXPERIMENTAL)"
depends on EXPERIMENTAL depends on EXPERIMENTAL
depends on MEDIA_CAMERA_SUPPORT
---help--- ---help---
Enable the media controller API used to query media devices internal Enable the media controller API used to query media devices internal
topology and configure it dynamically. topology and configure it dynamically.
@ -27,26 +89,15 @@ config MEDIA_CONTROLLER
This API is mostly used by camera interfaces in embedded platforms. This API is mostly used by camera interfaces in embedded platforms.
# #
# V4L core and enabled API's # Video4Linux support
# Only enables if one of the V4L2 types (ATV, webcam, radio) is selected
# #
config VIDEO_DEV config VIDEO_DEV
tristate "Video For Linux" tristate
---help--- depends on MEDIA_SUPPORT
V4L core support for video capture and overlay devices, webcams and depends on MEDIA_CAMERA_SUPPORT || MEDIA_ANALOG_TV_SUPPORT || MEDIA_RADIO_SUPPORT
AM/FM radio cards. default y
This kernel includes support for the new Video for Linux Two API,
(V4L2).
Additional info and docs are available on the web at
<http://linuxtv.org>
Documentation for V4L2 is also available on the web at
<http://bytesex.org/v4l/>.
To compile this driver as a module, choose M here: the
module will be called videodev.
config VIDEO_V4L2_COMMON config VIDEO_V4L2_COMMON
tristate tristate
@ -64,25 +115,15 @@ config VIDEO_V4L2_SUBDEV_API
# #
# DVB Core # DVB Core
# Only enables if one of DTV is selected
# #
config DVB_CORE config DVB_CORE
tristate "DVB for Linux" tristate
depends on MEDIA_SUPPORT
depends on MEDIA_DIGITAL_TV_SUPPORT
default y
select CRC32 select CRC32
help
DVB core utility functions for device handling, software fallbacks etc.
Enable this if you own a DVB/ATSC adapter and want to use it or if
you compile Linux for a digital SetTopBox.
Say Y when you have a DVB or an ATSC card and want to use it.
API specs and user tools are available from <http://www.linuxtv.org/>.
Please report problems regarding this support to the LinuxDVB
mailing list.
If unsure say N.
config DVB_NET config DVB_NET
bool "DVB Network Support" bool "DVB Network Support"
@ -97,12 +138,7 @@ config DVB_NET
You may want to disable the network support on embedded devices. If You may want to disable the network support on embedded devices. If
unsure say Y. unsure say Y.
config VIDEO_MEDIA comment "Media drivers"
tristate
default (DVB_CORE && (VIDEO_DEV = n)) || (VIDEO_DEV && (DVB_CORE = n)) || (DVB_CORE && VIDEO_DEV)
comment "Multimedia drivers"
source "drivers/media/common/Kconfig" source "drivers/media/common/Kconfig"
source "drivers/media/rc/Kconfig" source "drivers/media/rc/Kconfig"

View File

@ -1,7 +1,8 @@
config MEDIA_ATTACH config MEDIA_ATTACH
bool "Load and attach frontend and tuner driver modules as needed" bool "Load and attach frontend and tuner driver modules as needed"
depends on VIDEO_MEDIA depends on MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT || MEDIA_RADIO_SUPPORT
depends on MODULES depends on MODULES
default y if !EXPERT
help help
Remove the static dependency of DVB card drivers on all Remove the static dependency of DVB card drivers on all
frontend modules for all possible card variants. Instead, frontend modules for all possible card variants. Instead,
@ -19,15 +20,15 @@ config MEDIA_ATTACH
config MEDIA_TUNER config MEDIA_TUNER
tristate tristate
default VIDEO_MEDIA && I2C depends on (MEDIA_ANALOG_TV_SUPPORT || MEDIA_RADIO_SUPPORT) && I2C
depends on VIDEO_MEDIA && I2C default y
select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_XC4000 if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_XC4000 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMISE && EXPERIMENTAL select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMISE && MEDIA_RADIO_SUPPORT && EXPERIMENTAL
select MEDIA_TUNER_TEA5767 if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_TEA5767 if !MEDIA_TUNER_CUSTOMISE && MEDIA_RADIO_SUPPORT
select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_TDA9887 if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_TDA9887 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_MC44S803 if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_MC44S803 if !MEDIA_TUNER_CUSTOMISE
@ -47,10 +48,11 @@ config MEDIA_TUNER_CUSTOMISE
menu "Customize TV tuners" menu "Customize TV tuners"
visible if MEDIA_TUNER_CUSTOMISE visible if MEDIA_TUNER_CUSTOMISE
depends on MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT || MEDIA_RADIO_SUPPORT
config MEDIA_TUNER_SIMPLE config MEDIA_TUNER_SIMPLE
tristate "Simple tuner support" tristate "Simple tuner support"
depends on VIDEO_MEDIA && I2C depends on MEDIA_SUPPORT && I2C
select MEDIA_TUNER_TDA9887 select MEDIA_TUNER_TDA9887
default m if MEDIA_TUNER_CUSTOMISE default m if MEDIA_TUNER_CUSTOMISE
help help
@ -58,7 +60,7 @@ config MEDIA_TUNER_SIMPLE
config MEDIA_TUNER_TDA8290 config MEDIA_TUNER_TDA8290
tristate "TDA 8290/8295 + 8275(a)/18271 tuner combo" tristate "TDA 8290/8295 + 8275(a)/18271 tuner combo"
depends on VIDEO_MEDIA && I2C depends on MEDIA_SUPPORT && I2C
select MEDIA_TUNER_TDA827X select MEDIA_TUNER_TDA827X
select MEDIA_TUNER_TDA18271 select MEDIA_TUNER_TDA18271
default m if MEDIA_TUNER_CUSTOMISE default m if MEDIA_TUNER_CUSTOMISE
@ -67,21 +69,21 @@ config MEDIA_TUNER_TDA8290
config MEDIA_TUNER_TDA827X config MEDIA_TUNER_TDA827X
tristate "Philips TDA827X silicon tuner" tristate "Philips TDA827X silicon tuner"
depends on VIDEO_MEDIA && I2C depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE default m if MEDIA_TUNER_CUSTOMISE
help help
A DVB-T silicon tuner module. Say Y when you want to support this tuner. A DVB-T silicon tuner module. Say Y when you want to support this tuner.
config MEDIA_TUNER_TDA18271 config MEDIA_TUNER_TDA18271
tristate "NXP TDA18271 silicon tuner" tristate "NXP TDA18271 silicon tuner"
depends on VIDEO_MEDIA && I2C depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE default m if MEDIA_TUNER_CUSTOMISE
help help
A silicon tuner module. Say Y when you want to support this tuner. A silicon tuner module. Say Y when you want to support this tuner.
config MEDIA_TUNER_TDA9887 config MEDIA_TUNER_TDA9887
tristate "TDA 9885/6/7 analog IF demodulator" tristate "TDA 9885/6/7 analog IF demodulator"
depends on VIDEO_MEDIA && I2C depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE default m if MEDIA_TUNER_CUSTOMISE
help help
Say Y here to include support for Philips TDA9885/6/7 Say Y here to include support for Philips TDA9885/6/7
@ -89,7 +91,7 @@ config MEDIA_TUNER_TDA9887
config MEDIA_TUNER_TEA5761 config MEDIA_TUNER_TEA5761
tristate "TEA 5761 radio tuner (EXPERIMENTAL)" tristate "TEA 5761 radio tuner (EXPERIMENTAL)"
depends on VIDEO_MEDIA && I2C depends on MEDIA_SUPPORT && I2C
depends on EXPERIMENTAL depends on EXPERIMENTAL
default m if MEDIA_TUNER_CUSTOMISE default m if MEDIA_TUNER_CUSTOMISE
help help
@ -97,63 +99,63 @@ config MEDIA_TUNER_TEA5761
config MEDIA_TUNER_TEA5767 config MEDIA_TUNER_TEA5767
tristate "TEA 5767 radio tuner" tristate "TEA 5767 radio tuner"
depends on VIDEO_MEDIA && I2C depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE default m if MEDIA_TUNER_CUSTOMISE
help help
Say Y here to include support for the Philips TEA5767 radio tuner. Say Y here to include support for the Philips TEA5767 radio tuner.
config MEDIA_TUNER_MT20XX config MEDIA_TUNER_MT20XX
tristate "Microtune 2032 / 2050 tuners" tristate "Microtune 2032 / 2050 tuners"
depends on VIDEO_MEDIA && I2C depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE default m if MEDIA_TUNER_CUSTOMISE
help help
Say Y here to include support for the MT2032 / MT2050 tuner. Say Y here to include support for the MT2032 / MT2050 tuner.
config MEDIA_TUNER_MT2060 config MEDIA_TUNER_MT2060
tristate "Microtune MT2060 silicon IF tuner" tristate "Microtune MT2060 silicon IF tuner"
depends on VIDEO_MEDIA && I2C depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE default m if MEDIA_TUNER_CUSTOMISE
help help
A driver for the silicon IF tuner MT2060 from Microtune. A driver for the silicon IF tuner MT2060 from Microtune.
config MEDIA_TUNER_MT2063 config MEDIA_TUNER_MT2063
tristate "Microtune MT2063 silicon IF tuner" tristate "Microtune MT2063 silicon IF tuner"
depends on VIDEO_MEDIA && I2C depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE default m if MEDIA_TUNER_CUSTOMISE
help help
A driver for the silicon IF tuner MT2063 from Microtune. A driver for the silicon IF tuner MT2063 from Microtune.
config MEDIA_TUNER_MT2266 config MEDIA_TUNER_MT2266
tristate "Microtune MT2266 silicon tuner" tristate "Microtune MT2266 silicon tuner"
depends on VIDEO_MEDIA && I2C depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE default m if MEDIA_TUNER_CUSTOMISE
help help
A driver for the silicon baseband tuner MT2266 from Microtune. A driver for the silicon baseband tuner MT2266 from Microtune.
config MEDIA_TUNER_MT2131 config MEDIA_TUNER_MT2131
tristate "Microtune MT2131 silicon tuner" tristate "Microtune MT2131 silicon tuner"
depends on VIDEO_MEDIA && I2C depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE default m if MEDIA_TUNER_CUSTOMISE
help help
A driver for the silicon baseband tuner MT2131 from Microtune. A driver for the silicon baseband tuner MT2131 from Microtune.
config MEDIA_TUNER_QT1010 config MEDIA_TUNER_QT1010
tristate "Quantek QT1010 silicon tuner" tristate "Quantek QT1010 silicon tuner"
depends on VIDEO_MEDIA && I2C depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE default m if MEDIA_TUNER_CUSTOMISE
help help
A driver for the silicon tuner QT1010 from Quantek. A driver for the silicon tuner QT1010 from Quantek.
config MEDIA_TUNER_XC2028 config MEDIA_TUNER_XC2028
tristate "XCeive xc2028/xc3028 tuners" tristate "XCeive xc2028/xc3028 tuners"
depends on VIDEO_MEDIA && I2C depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE default m if MEDIA_TUNER_CUSTOMISE
help help
Say Y here to include support for the xc2028/xc3028 tuners. Say Y here to include support for the xc2028/xc3028 tuners.
config MEDIA_TUNER_XC5000 config MEDIA_TUNER_XC5000
tristate "Xceive XC5000 silicon tuner" tristate "Xceive XC5000 silicon tuner"
depends on VIDEO_MEDIA && I2C depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE default m if MEDIA_TUNER_CUSTOMISE
help help
A driver for the silicon tuner XC5000 from Xceive. A driver for the silicon tuner XC5000 from Xceive.
@ -162,7 +164,7 @@ config MEDIA_TUNER_XC5000
config MEDIA_TUNER_XC4000 config MEDIA_TUNER_XC4000
tristate "Xceive XC4000 silicon tuner" tristate "Xceive XC4000 silicon tuner"
depends on VIDEO_MEDIA && I2C depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE default m if MEDIA_TUNER_CUSTOMISE
help help
A driver for the silicon tuner XC4000 from Xceive. A driver for the silicon tuner XC4000 from Xceive.
@ -171,70 +173,70 @@ config MEDIA_TUNER_XC4000
config MEDIA_TUNER_MXL5005S config MEDIA_TUNER_MXL5005S
tristate "MaxLinear MSL5005S silicon tuner" tristate "MaxLinear MSL5005S silicon tuner"
depends on VIDEO_MEDIA && I2C depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE default m if MEDIA_TUNER_CUSTOMISE
help help
A driver for the silicon tuner MXL5005S from MaxLinear. A driver for the silicon tuner MXL5005S from MaxLinear.
config MEDIA_TUNER_MXL5007T config MEDIA_TUNER_MXL5007T
tristate "MaxLinear MxL5007T silicon tuner" tristate "MaxLinear MxL5007T silicon tuner"
depends on VIDEO_MEDIA && I2C depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE default m if MEDIA_TUNER_CUSTOMISE
help help
A driver for the silicon tuner MxL5007T from MaxLinear. A driver for the silicon tuner MxL5007T from MaxLinear.
config MEDIA_TUNER_MC44S803 config MEDIA_TUNER_MC44S803
tristate "Freescale MC44S803 Low Power CMOS Broadband tuners" tristate "Freescale MC44S803 Low Power CMOS Broadband tuners"
depends on VIDEO_MEDIA && I2C depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE default m if MEDIA_TUNER_CUSTOMISE
help help
Say Y here to support the Freescale MC44S803 based tuners Say Y here to support the Freescale MC44S803 based tuners
config MEDIA_TUNER_MAX2165 config MEDIA_TUNER_MAX2165
tristate "Maxim MAX2165 silicon tuner" tristate "Maxim MAX2165 silicon tuner"
depends on VIDEO_MEDIA && I2C depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE default m if MEDIA_TUNER_CUSTOMISE
help help
A driver for the silicon tuner MAX2165 from Maxim. A driver for the silicon tuner MAX2165 from Maxim.
config MEDIA_TUNER_TDA18218 config MEDIA_TUNER_TDA18218
tristate "NXP TDA18218 silicon tuner" tristate "NXP TDA18218 silicon tuner"
depends on VIDEO_MEDIA && I2C depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE default m if MEDIA_TUNER_CUSTOMISE
help help
NXP TDA18218 silicon tuner driver. NXP TDA18218 silicon tuner driver.
config MEDIA_TUNER_FC0011 config MEDIA_TUNER_FC0011
tristate "Fitipower FC0011 silicon tuner" tristate "Fitipower FC0011 silicon tuner"
depends on VIDEO_MEDIA && I2C depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE default m if MEDIA_TUNER_CUSTOMISE
help help
Fitipower FC0011 silicon tuner driver. Fitipower FC0011 silicon tuner driver.
config MEDIA_TUNER_FC0012 config MEDIA_TUNER_FC0012
tristate "Fitipower FC0012 silicon tuner" tristate "Fitipower FC0012 silicon tuner"
depends on VIDEO_MEDIA && I2C depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE default m if MEDIA_TUNER_CUSTOMISE
help help
Fitipower FC0012 silicon tuner driver. Fitipower FC0012 silicon tuner driver.
config MEDIA_TUNER_FC0013 config MEDIA_TUNER_FC0013
tristate "Fitipower FC0013 silicon tuner" tristate "Fitipower FC0013 silicon tuner"
depends on VIDEO_MEDIA && I2C depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE default m if MEDIA_TUNER_CUSTOMISE
help help
Fitipower FC0013 silicon tuner driver. Fitipower FC0013 silicon tuner driver.
config MEDIA_TUNER_TDA18212 config MEDIA_TUNER_TDA18212
tristate "NXP TDA18212 silicon tuner" tristate "NXP TDA18212 silicon tuner"
depends on VIDEO_MEDIA && I2C depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE default m if MEDIA_TUNER_CUSTOMISE
help help
NXP TDA18212 silicon tuner driver. NXP TDA18212 silicon tuner driver.
config MEDIA_TUNER_TUA9001 config MEDIA_TUNER_TUA9001
tristate "Infineon TUA 9001 silicon tuner" tristate "Infineon TUA 9001 silicon tuner"
depends on VIDEO_MEDIA && I2C depends on MEDIA_SUPPORT && I2C
default m if MEDIA_TUNER_CUSTOMISE default m if MEDIA_TUNER_CUSTOMISE
help help
Infineon TUA 9001 silicon tuner driver. Infineon TUA 9001 silicon tuner driver.

View File

@ -90,11 +90,22 @@ struct firmware_properties {
int scode_nr; int scode_nr;
}; };
enum xc2028_state {
XC2028_NO_FIRMWARE = 0,
XC2028_WAITING_FIRMWARE,
XC2028_ACTIVE,
XC2028_SLEEP,
XC2028_NODEV,
};
struct xc2028_data { struct xc2028_data {
struct list_head hybrid_tuner_instance_list; struct list_head hybrid_tuner_instance_list;
struct tuner_i2c_props i2c_props; struct tuner_i2c_props i2c_props;
__u32 frequency; __u32 frequency;
enum xc2028_state state;
const char *fname;
struct firmware_description *firm; struct firmware_description *firm;
int firm_size; int firm_size;
__u16 firm_version; __u16 firm_version;
@ -255,6 +266,21 @@ static v4l2_std_id parse_audio_std_option(void)
return 0; return 0;
} }
static int check_device_status(struct xc2028_data *priv)
{
switch (priv->state) {
case XC2028_NO_FIRMWARE:
case XC2028_WAITING_FIRMWARE:
return -EAGAIN;
case XC2028_ACTIVE:
case XC2028_SLEEP:
return 0;
case XC2028_NODEV:
return -ENODEV;
}
return 0;
}
static void free_firmware(struct xc2028_data *priv) static void free_firmware(struct xc2028_data *priv)
{ {
int i; int i;
@ -270,45 +296,28 @@ static void free_firmware(struct xc2028_data *priv)
priv->firm = NULL; priv->firm = NULL;
priv->firm_size = 0; priv->firm_size = 0;
priv->state = XC2028_NO_FIRMWARE;
memset(&priv->cur_fw, 0, sizeof(priv->cur_fw)); memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
} }
static int load_all_firmwares(struct dvb_frontend *fe) static int load_all_firmwares(struct dvb_frontend *fe,
const struct firmware *fw)
{ {
struct xc2028_data *priv = fe->tuner_priv; struct xc2028_data *priv = fe->tuner_priv;
const struct firmware *fw = NULL;
const unsigned char *p, *endp; const unsigned char *p, *endp;
int rc = 0; int rc = 0;
int n, n_array; int n, n_array;
char name[33]; char name[33];
char *fname;
tuner_dbg("%s called\n", __func__); tuner_dbg("%s called\n", __func__);
if (!firmware_name[0])
fname = priv->ctrl.fname;
else
fname = firmware_name;
tuner_dbg("Reading firmware %s\n", fname);
rc = request_firmware(&fw, fname, priv->i2c_props.adap->dev.parent);
if (rc < 0) {
if (rc == -ENOENT)
tuner_err("Error: firmware %s not found.\n",
fname);
else
tuner_err("Error %d while requesting firmware %s \n",
rc, fname);
return rc;
}
p = fw->data; p = fw->data;
endp = p + fw->size; endp = p + fw->size;
if (fw->size < sizeof(name) - 1 + 2 + 2) { if (fw->size < sizeof(name) - 1 + 2 + 2) {
tuner_err("Error: firmware file %s has invalid size!\n", tuner_err("Error: firmware file %s has invalid size!\n",
fname); priv->fname);
goto corrupt; goto corrupt;
} }
@ -323,7 +332,7 @@ static int load_all_firmwares(struct dvb_frontend *fe)
p += 2; p += 2;
tuner_info("Loading %d firmware images from %s, type: %s, ver %d.%d\n", tuner_info("Loading %d firmware images from %s, type: %s, ver %d.%d\n",
n_array, fname, name, n_array, priv->fname, name,
priv->firm_version >> 8, priv->firm_version & 0xff); priv->firm_version >> 8, priv->firm_version & 0xff);
priv->firm = kcalloc(n_array, sizeof(*priv->firm), GFP_KERNEL); priv->firm = kcalloc(n_array, sizeof(*priv->firm), GFP_KERNEL);
@ -417,9 +426,10 @@ err:
free_firmware(priv); free_firmware(priv);
done: done:
release_firmware(fw);
if (rc == 0) if (rc == 0)
tuner_dbg("Firmware files loaded.\n"); tuner_dbg("Firmware files loaded.\n");
else
priv->state = XC2028_NODEV;
return rc; return rc;
} }
@ -707,22 +717,15 @@ static int check_firmware(struct dvb_frontend *fe, unsigned int type,
{ {
struct xc2028_data *priv = fe->tuner_priv; struct xc2028_data *priv = fe->tuner_priv;
struct firmware_properties new_fw; struct firmware_properties new_fw;
int rc = 0, retry_count = 0; int rc, retry_count = 0;
u16 version, hwmodel; u16 version, hwmodel;
v4l2_std_id std0; v4l2_std_id std0;
tuner_dbg("%s called\n", __func__); tuner_dbg("%s called\n", __func__);
if (!priv->firm) { rc = check_device_status(priv);
if (!priv->ctrl.fname) { if (rc < 0)
tuner_info("xc2028/3028 firmware name not set!\n"); return rc;
return -EINVAL;
}
rc = load_all_firmwares(fe);
if (rc < 0)
return rc;
}
if (priv->ctrl.mts && !(type & FM)) if (priv->ctrl.mts && !(type & FM))
type |= MTS; type |= MTS;
@ -749,9 +752,13 @@ retry:
printk("scode_nr %d\n", new_fw.scode_nr); printk("scode_nr %d\n", new_fw.scode_nr);
} }
/* No need to reload base firmware if it matches */ /*
if (((BASE | new_fw.type) & BASE_TYPES) == * No need to reload base firmware if it matches and if the tuner
(priv->cur_fw.type & BASE_TYPES)) { * is not at sleep mode
*/
if ((priv->state = XC2028_ACTIVE) &&
(((BASE | new_fw.type) & BASE_TYPES) ==
(priv->cur_fw.type & BASE_TYPES))) {
tuner_dbg("BASE firmware not changed.\n"); tuner_dbg("BASE firmware not changed.\n");
goto skip_base; goto skip_base;
} }
@ -872,10 +879,13 @@ read_not_reliable:
* 2. Tell whether BASE firmware was just changed the next time through. * 2. Tell whether BASE firmware was just changed the next time through.
*/ */
priv->cur_fw.type |= BASE; priv->cur_fw.type |= BASE;
priv->state = XC2028_ACTIVE;
return 0; return 0;
fail: fail:
priv->state = XC2028_SLEEP;
memset(&priv->cur_fw, 0, sizeof(priv->cur_fw)); memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
if (retry_count < 8) { if (retry_count < 8) {
msleep(50); msleep(50);
@ -893,28 +903,39 @@ static int xc2028_signal(struct dvb_frontend *fe, u16 *strength)
{ {
struct xc2028_data *priv = fe->tuner_priv; struct xc2028_data *priv = fe->tuner_priv;
u16 frq_lock, signal = 0; u16 frq_lock, signal = 0;
int rc; int rc, i;
tuner_dbg("%s called\n", __func__); tuner_dbg("%s called\n", __func__);
rc = check_device_status(priv);
if (rc < 0)
return rc;
mutex_lock(&priv->lock); mutex_lock(&priv->lock);
/* Sync Lock Indicator */ /* Sync Lock Indicator */
rc = xc2028_get_reg(priv, XREG_LOCK, &frq_lock); for (i = 0; i < 3; i++) {
if (rc < 0) rc = xc2028_get_reg(priv, XREG_LOCK, &frq_lock);
goto ret; if (rc < 0)
goto ret;
/* Frequency is locked */ if (frq_lock)
if (frq_lock == 1) break;
signal = 1 << 11; msleep(6);
}
/* Frequency didn't lock */
if (frq_lock == 2)
goto ret;
/* Get SNR of the video signal */ /* Get SNR of the video signal */
rc = xc2028_get_reg(priv, XREG_SNR, &signal); rc = xc2028_get_reg(priv, XREG_SNR, &signal);
if (rc < 0) if (rc < 0)
goto ret; goto ret;
/* Use both frq_lock and signal to generate the result */ /* Signal level is 3 bits only */
signal = signal || ((signal & 0x07) << 12);
signal = ((1 << 12) - 1) | ((signal & 0x07) << 12);
ret: ret:
mutex_unlock(&priv->lock); mutex_unlock(&priv->lock);
@ -926,6 +947,49 @@ ret:
return rc; return rc;
} }
static int xc2028_get_afc(struct dvb_frontend *fe, s32 *afc)
{
struct xc2028_data *priv = fe->tuner_priv;
int i, rc;
u16 frq_lock = 0;
s16 afc_reg = 0;
rc = check_device_status(priv);
if (rc < 0)
return rc;
mutex_lock(&priv->lock);
/* Sync Lock Indicator */
for (i = 0; i < 3; i++) {
rc = xc2028_get_reg(priv, XREG_LOCK, &frq_lock);
if (rc < 0)
goto ret;
if (frq_lock)
break;
msleep(6);
}
/* Frequency didn't lock */
if (frq_lock == 2)
goto ret;
/* Get AFC */
rc = xc2028_get_reg(priv, XREG_FREQ_ERROR, &afc_reg);
if (rc < 0)
return rc;
*afc = afc_reg * 15625; /* Hz */
tuner_dbg("AFC is %d Hz\n", *afc);
ret:
mutex_unlock(&priv->lock);
return rc;
}
#define DIV 15625 #define DIV 15625
static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */, static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
@ -1111,11 +1175,16 @@ static int xc2028_set_params(struct dvb_frontend *fe)
u32 delsys = c->delivery_system; u32 delsys = c->delivery_system;
u32 bw = c->bandwidth_hz; u32 bw = c->bandwidth_hz;
struct xc2028_data *priv = fe->tuner_priv; struct xc2028_data *priv = fe->tuner_priv;
unsigned int type=0; int rc;
unsigned int type = 0;
u16 demod = 0; u16 demod = 0;
tuner_dbg("%s called\n", __func__); tuner_dbg("%s called\n", __func__);
rc = check_device_status(priv);
if (rc < 0)
return rc;
switch (delsys) { switch (delsys) {
case SYS_DVBT: case SYS_DVBT:
case SYS_DVBT2: case SYS_DVBT2:
@ -1201,7 +1270,11 @@ static int xc2028_set_params(struct dvb_frontend *fe)
static int xc2028_sleep(struct dvb_frontend *fe) static int xc2028_sleep(struct dvb_frontend *fe)
{ {
struct xc2028_data *priv = fe->tuner_priv; struct xc2028_data *priv = fe->tuner_priv;
int rc = 0; int rc;
rc = check_device_status(priv);
if (rc < 0)
return rc;
/* Avoid firmware reload on slow devices or if PM disabled */ /* Avoid firmware reload on slow devices or if PM disabled */
if (no_poweroff || priv->ctrl.disable_power_mgmt) if (no_poweroff || priv->ctrl.disable_power_mgmt)
@ -1220,7 +1293,7 @@ static int xc2028_sleep(struct dvb_frontend *fe)
else else
rc = send_seq(priv, {0x80, XREG_POWER_DOWN, 0x00, 0x00}); rc = send_seq(priv, {0x80, XREG_POWER_DOWN, 0x00, 0x00});
priv->cur_fw.type = 0; /* need firmware reload */ priv->state = XC2028_SLEEP;
mutex_unlock(&priv->lock); mutex_unlock(&priv->lock);
@ -1237,8 +1310,9 @@ static int xc2028_dvb_release(struct dvb_frontend *fe)
/* only perform final cleanup if this is the last instance */ /* only perform final cleanup if this is the last instance */
if (hybrid_tuner_report_instance_count(priv) == 1) { if (hybrid_tuner_report_instance_count(priv) == 1) {
kfree(priv->ctrl.fname);
free_firmware(priv); free_firmware(priv);
kfree(priv->ctrl.fname);
priv->ctrl.fname = NULL;
} }
if (priv) if (priv)
@ -1254,14 +1328,42 @@ static int xc2028_dvb_release(struct dvb_frontend *fe)
static int xc2028_get_frequency(struct dvb_frontend *fe, u32 *frequency) static int xc2028_get_frequency(struct dvb_frontend *fe, u32 *frequency)
{ {
struct xc2028_data *priv = fe->tuner_priv; struct xc2028_data *priv = fe->tuner_priv;
int rc;
tuner_dbg("%s called\n", __func__); tuner_dbg("%s called\n", __func__);
rc = check_device_status(priv);
if (rc < 0)
return rc;
*frequency = priv->frequency; *frequency = priv->frequency;
return 0; return 0;
} }
static void load_firmware_cb(const struct firmware *fw,
void *context)
{
struct dvb_frontend *fe = context;
struct xc2028_data *priv = fe->tuner_priv;
int rc;
tuner_dbg("request_firmware_nowait(): %s\n", fw ? "OK" : "error");
if (!fw) {
tuner_err("Could not load firmware %s.\n", priv->fname);
priv->state = XC2028_NODEV;
return;
}
rc = load_all_firmwares(fe, fw);
release_firmware(fw);
if (rc < 0)
return;
priv->state = XC2028_SLEEP;
}
static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg) static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg)
{ {
struct xc2028_data *priv = fe->tuner_priv; struct xc2028_data *priv = fe->tuner_priv;
@ -1272,21 +1374,49 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg)
mutex_lock(&priv->lock); mutex_lock(&priv->lock);
/*
* Copy the config data.
* For the firmware name, keep a local copy of the string,
* in order to avoid troubles during device release.
*/
if (priv->ctrl.fname)
kfree(priv->ctrl.fname);
memcpy(&priv->ctrl, p, sizeof(priv->ctrl)); memcpy(&priv->ctrl, p, sizeof(priv->ctrl));
if (priv->ctrl.max_len < 9)
priv->ctrl.max_len = 13;
if (p->fname) { if (p->fname) {
if (priv->ctrl.fname && strcmp(p->fname, priv->ctrl.fname)) {
kfree(priv->ctrl.fname);
free_firmware(priv);
}
priv->ctrl.fname = kstrdup(p->fname, GFP_KERNEL); priv->ctrl.fname = kstrdup(p->fname, GFP_KERNEL);
if (priv->ctrl.fname == NULL) if (priv->ctrl.fname == NULL)
rc = -ENOMEM; rc = -ENOMEM;
} }
/*
* If firmware name changed, frees firmware. As free_firmware will
* reset the status to NO_FIRMWARE, this forces a new request_firmware
*/
if (!firmware_name[0] && p->fname &&
priv->fname && strcmp(p->fname, priv->fname))
free_firmware(priv);
if (priv->ctrl.max_len < 9)
priv->ctrl.max_len = 13;
if (priv->state == XC2028_NO_FIRMWARE) {
if (!firmware_name[0])
priv->fname = priv->ctrl.fname;
else
priv->fname = firmware_name;
rc = request_firmware_nowait(THIS_MODULE, 1,
priv->fname,
priv->i2c_props.adap->dev.parent,
GFP_KERNEL,
fe, load_firmware_cb);
if (rc < 0) {
tuner_err("Failed to request firmware %s\n",
priv->fname);
priv->state = XC2028_NODEV;
}
priv->state = XC2028_WAITING_FIRMWARE;
}
mutex_unlock(&priv->lock); mutex_unlock(&priv->lock);
return rc; return rc;
@ -1305,6 +1435,7 @@ static const struct dvb_tuner_ops xc2028_dvb_tuner_ops = {
.release = xc2028_dvb_release, .release = xc2028_dvb_release,
.get_frequency = xc2028_get_frequency, .get_frequency = xc2028_get_frequency,
.get_rf_strength = xc2028_signal, .get_rf_strength = xc2028_signal,
.get_afc = xc2028_get_afc,
.set_params = xc2028_set_params, .set_params = xc2028_set_params,
.sleep = xc2028_sleep, .sleep = xc2028_sleep,
}; };
@ -1375,3 +1506,5 @@ MODULE_DESCRIPTION("Xceive xc2028/xc3028 tuner driver");
MODULE_AUTHOR("Michel Ludwig <michel.ludwig@gmail.com>"); MODULE_AUTHOR("Michel Ludwig <michel.ludwig@gmail.com>");
MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_FIRMWARE(XC2028_DEFAULT_FIRMWARE);
MODULE_FIRMWARE(XC3028L_DEFAULT_FIRMWARE);

View File

@ -717,6 +717,12 @@ static int xc5000_set_params(struct dvb_frontend *fe)
priv->freq_hz = freq - 1750000; priv->freq_hz = freq - 1750000;
priv->video_standard = DTV6; priv->video_standard = DTV6;
break; break;
case SYS_ISDBT:
/* All ISDB-T are currently for 6 MHz bw */
if (!bw)
bw = 6000000;
/* fall to OFDM handling */
case SYS_DMBTH:
case SYS_DVBT: case SYS_DVBT:
case SYS_DVBT2: case SYS_DVBT2:
dprintk(1, "%s() OFDM\n", __func__); dprintk(1, "%s() OFDM\n", __func__);

View File

@ -578,6 +578,7 @@ static int demod_attach_drxk(struct ddb_input *input)
memset(&config, 0, sizeof(config)); memset(&config, 0, sizeof(config));
config.microcode_name = "drxk_a3.mc"; config.microcode_name = "drxk_a3.mc";
config.qam_demod_parameter_count = 4;
config.adr = 0x29 + (input->nr & 1); config.adr = 0x29 + (input->nr & 1);
fe = input->fe = dvb_attach(drxk_attach, &config, i2c); fe = input->fe = dvb_attach(drxk_attach, &config, i2c);

View File

@ -220,6 +220,7 @@ struct dvb_tuner_ops {
#define TUNER_STATUS_STEREO 2 #define TUNER_STATUS_STEREO 2
int (*get_status)(struct dvb_frontend *fe, u32 *status); int (*get_status)(struct dvb_frontend *fe, u32 *status);
int (*get_rf_strength)(struct dvb_frontend *fe, u16 *strength); int (*get_rf_strength)(struct dvb_frontend *fe, u16 *strength);
int (*get_afc)(struct dvb_frontend *fe, s32 *afc);
/** These are provided separately from set_params in order to facilitate silicon /** These are provided separately from set_params in order to facilitate silicon
* tuners which require sophisticated tuning loops, controlling each parameter separately. */ * tuners which require sophisticated tuning loops, controlling each parameter separately. */

View File

@ -418,9 +418,12 @@ config DVB_USB_RTL28XXU
tristate "Realtek RTL28xxU DVB USB support" tristate "Realtek RTL28xxU DVB USB support"
depends on DVB_USB && EXPERIMENTAL depends on DVB_USB && EXPERIMENTAL
select DVB_RTL2830 select DVB_RTL2830
select DVB_RTL2832
select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_FC0012 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_FC0013 if !MEDIA_TUNER_CUSTOMISE
help help
Say Y here to support the Realtek RTL28xxU DVB USB receiver. Say Y here to support the Realtek RTL28xxU DVB USB receiver.

View File

@ -593,9 +593,7 @@ static int az6007_read_mac_addr(struct dvb_usb_device *d, u8 mac[6])
memcpy(mac, st->data, sizeof(mac)); memcpy(mac, st->data, sizeof(mac));
if (ret > 0) if (ret > 0)
deb_info("%s: mac is %02x:%02x:%02x:%02x:%02x:%02x\n", deb_info("%s: mac is %pM\n", __func__, mac);
__func__, mac[0], mac[1], mac[2],
mac[3], mac[4], mac[5]);
return ret; return ret;
} }

View File

@ -100,6 +100,7 @@
#define USB_PID_CONCEPTRONIC_CTVDIGRCU 0xe397 #define USB_PID_CONCEPTRONIC_CTVDIGRCU 0xe397
#define USB_PID_CONEXANT_D680_DMB 0x86d6 #define USB_PID_CONEXANT_D680_DMB 0x86d6
#define USB_PID_CREATIX_CTX1921 0x1921 #define USB_PID_CREATIX_CTX1921 0x1921
#define USB_PID_DELOCK_USB2_DVBT 0xb803
#define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064 #define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064
#define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065 #define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065
#define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8 #define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8
@ -160,6 +161,7 @@
#define USB_PID_TERRATEC_CINERGY_T_STICK 0x0093 #define USB_PID_TERRATEC_CINERGY_T_STICK 0x0093
#define USB_PID_TERRATEC_CINERGY_T_STICK_RC 0x0097 #define USB_PID_TERRATEC_CINERGY_T_STICK_RC 0x0097
#define USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC 0x0099 #define USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC 0x0099
#define USB_PID_TERRATEC_CINERGY_T_STICK_BLACK_REV1 0x00a9
#define USB_PID_TWINHAN_VP7041_COLD 0x3201 #define USB_PID_TWINHAN_VP7041_COLD 0x3201
#define USB_PID_TWINHAN_VP7041_WARM 0x3202 #define USB_PID_TWINHAN_VP7041_WARM 0x3202
#define USB_PID_TWINHAN_VP7020_COLD 0x3203 #define USB_PID_TWINHAN_VP7020_COLD 0x3203
@ -245,6 +247,7 @@
#define USB_PID_TERRATEC_H7_2 0x10a3 #define USB_PID_TERRATEC_H7_2 0x10a3
#define USB_PID_TERRATEC_T3 0x10a0 #define USB_PID_TERRATEC_T3 0x10a0
#define USB_PID_TERRATEC_T5 0x10a1 #define USB_PID_TERRATEC_T5 0x10a1
#define USB_PID_NOXON_DAB_STICK 0x00b3
#define USB_PID_PINNACLE_EXPRESSCARD_320CX 0x022e #define USB_PID_PINNACLE_EXPRESSCARD_320CX 0x022e
#define USB_PID_PINNACLE_PCTV2000E 0x022c #define USB_PID_PINNACLE_PCTV2000E 0x022c
#define USB_PID_PINNACLE_PCTV_DVB_T_FLASH 0x0228 #define USB_PID_PINNACLE_PCTV_DVB_T_FLASH 0x0228

View File

@ -3,6 +3,7 @@
* *
* Copyright (C) 2009 Antti Palosaari <crope@iki.fi> * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
* Copyright (C) 2011 Antti Palosaari <crope@iki.fi> * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
* Copyright (C) 2012 Thomas Mair <thomas.mair86@googlemail.com>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -22,10 +23,13 @@
#include "rtl28xxu.h" #include "rtl28xxu.h"
#include "rtl2830.h" #include "rtl2830.h"
#include "rtl2832.h"
#include "qt1010.h" #include "qt1010.h"
#include "mt2060.h" #include "mt2060.h"
#include "mxl5005s.h" #include "mxl5005s.h"
#include "fc0012.h"
#include "fc0013.h"
/* debug */ /* debug */
static int dvb_usb_rtl28xxu_debug; static int dvb_usb_rtl28xxu_debug;
@ -80,7 +84,7 @@ err:
return ret; return ret;
} }
static int rtl2831_wr_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len) static int rtl28xx_wr_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len)
{ {
struct rtl28xxu_req req; struct rtl28xxu_req req;
@ -116,12 +120,12 @@ static int rtl2831_rd_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len)
return rtl28xxu_ctrl_msg(d, &req); return rtl28xxu_ctrl_msg(d, &req);
} }
static int rtl2831_wr_reg(struct dvb_usb_device *d, u16 reg, u8 val) static int rtl28xx_wr_reg(struct dvb_usb_device *d, u16 reg, u8 val)
{ {
return rtl2831_wr_regs(d, reg, &val, 1); return rtl28xx_wr_regs(d, reg, &val, 1);
} }
static int rtl2831_rd_reg(struct dvb_usb_device *d, u16 reg, u8 *val) static int rtl28xx_rd_reg(struct dvb_usb_device *d, u16 reg, u8 *val)
{ {
return rtl2831_rd_regs(d, reg, val, 1); return rtl2831_rd_regs(d, reg, val, 1);
} }
@ -308,12 +312,12 @@ static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap)
*/ */
/* GPIO direction */ /* GPIO direction */
ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_DIR, 0x0a); ret = rtl28xx_wr_reg(adap->dev, SYS_GPIO_DIR, 0x0a);
if (ret) if (ret)
goto err; goto err;
/* enable as output GPIO0, GPIO2, GPIO4 */ /* enable as output GPIO0, GPIO2, GPIO4 */
ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_OUT_EN, 0x15); ret = rtl28xx_wr_reg(adap->dev, SYS_GPIO_OUT_EN, 0x15);
if (ret) if (ret)
goto err; goto err;
@ -381,34 +385,159 @@ err:
return ret; return ret;
} }
static struct rtl2832_config rtl28xxu_rtl2832_fc0012_config = {
.i2c_addr = 0x10, /* 0x20 */
.xtal = 28800000,
.if_dvbt = 0,
.tuner = TUNER_RTL2832_FC0012
};
static struct rtl2832_config rtl28xxu_rtl2832_fc0013_config = {
.i2c_addr = 0x10, /* 0x20 */
.xtal = 28800000,
.if_dvbt = 0,
.tuner = TUNER_RTL2832_FC0013
};
static int rtl2832u_fc0012_tuner_callback(struct dvb_usb_device *d,
int cmd, int arg)
{
int ret;
u8 val;
deb_info("%s cmd=%d arg=%d\n", __func__, cmd, arg);
switch (cmd) {
case FC_FE_CALLBACK_VHF_ENABLE:
/* set output values */
ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &val);
if (ret)
goto err;
if (arg)
val &= 0xbf; /* set GPIO6 low */
else
val |= 0x40; /* set GPIO6 high */
ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, val);
if (ret)
goto err;
break;
default:
ret = -EINVAL;
goto err;
}
return 0;
err:
err("%s: failed=%d\n", __func__, ret);
return ret;
}
static int rtl2832u_fc0013_tuner_callback(struct dvb_usb_device *d,
int cmd, int arg)
{
/* TODO implement*/
return 0;
}
static int rtl2832u_tuner_callback(struct dvb_usb_device *d, int cmd, int arg)
{
struct rtl28xxu_priv *priv = d->priv;
switch (priv->tuner) {
case TUNER_RTL2832_FC0012:
return rtl2832u_fc0012_tuner_callback(d, cmd, arg);
case TUNER_RTL2832_FC0013:
return rtl2832u_fc0013_tuner_callback(d, cmd, arg);
default:
break;
}
return -ENODEV;
}
static int rtl2832u_frontend_callback(void *adapter_priv, int component,
int cmd, int arg)
{
struct i2c_adapter *adap = adapter_priv;
struct dvb_usb_device *d = i2c_get_adapdata(adap);
switch (component) {
case DVB_FRONTEND_COMPONENT_TUNER:
return rtl2832u_tuner_callback(d, cmd, arg);
default:
break;
}
return -EINVAL;
}
static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap) static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
{ {
int ret; int ret;
struct rtl28xxu_priv *priv = adap->dev->priv; struct rtl28xxu_priv *priv = adap->dev->priv;
u8 buf[1]; struct rtl2832_config *rtl2832_config;
u8 buf[2], val;
/* open RTL2832U/RTL2832 I2C gate */ /* open RTL2832U/RTL2832 I2C gate */
struct rtl28xxu_req req_gate_open = {0x0120, 0x0011, 0x0001, "\x18"}; struct rtl28xxu_req req_gate_open = {0x0120, 0x0011, 0x0001, "\x18"};
/* close RTL2832U/RTL2832 I2C gate */ /* close RTL2832U/RTL2832 I2C gate */
struct rtl28xxu_req req_gate_close = {0x0120, 0x0011, 0x0001, "\x10"}; struct rtl28xxu_req req_gate_close = {0x0120, 0x0011, 0x0001, "\x10"};
/* for FC0012 tuner probe */
struct rtl28xxu_req req_fc0012 = {0x00c6, CMD_I2C_RD, 1, buf};
/* for FC0013 tuner probe */
struct rtl28xxu_req req_fc0013 = {0x00c6, CMD_I2C_RD, 1, buf};
/* for MT2266 tuner probe */
struct rtl28xxu_req req_mt2266 = {0x00c0, CMD_I2C_RD, 1, buf};
/* for FC2580 tuner probe */ /* for FC2580 tuner probe */
struct rtl28xxu_req req_fc2580 = {0x01ac, CMD_I2C_RD, 1, buf}; struct rtl28xxu_req req_fc2580 = {0x01ac, CMD_I2C_RD, 1, buf};
/* for MT2063 tuner probe */
struct rtl28xxu_req req_mt2063 = {0x00c0, CMD_I2C_RD, 1, buf};
/* for MAX3543 tuner probe */
struct rtl28xxu_req req_max3543 = {0x00c0, CMD_I2C_RD, 1, buf};
/* for TUA9001 tuner probe */
struct rtl28xxu_req req_tua9001 = {0x7ec0, CMD_I2C_RD, 2, buf};
/* for MXL5007T tuner probe */
struct rtl28xxu_req req_mxl5007t = {0xd9c0, CMD_I2C_RD, 1, buf};
/* for E4000 tuner probe */
struct rtl28xxu_req req_e4000 = {0x02c8, CMD_I2C_RD, 1, buf};
/* for TDA18272 tuner probe */
struct rtl28xxu_req req_tda18272 = {0x00c0, CMD_I2C_RD, 2, buf};
deb_info("%s:\n", __func__); deb_info("%s:\n", __func__);
/* GPIO direction */
ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_DIR, 0x0a); ret = rtl28xx_rd_reg(adap->dev, SYS_GPIO_DIR, &val);
if (ret) if (ret)
goto err; goto err;
/* enable as output GPIO0, GPIO2, GPIO4 */ val &= 0xbf;
ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_OUT_EN, 0x15);
ret = rtl28xx_wr_reg(adap->dev, SYS_GPIO_DIR, val);
if (ret) if (ret)
goto err; goto err;
ret = rtl2831_wr_reg(adap->dev, SYS_DEMOD_CTL, 0xe8);
/* enable as output GPIO3 and GPIO6*/
ret = rtl28xx_rd_reg(adap->dev, SYS_GPIO_OUT_EN, &val);
if (ret) if (ret)
goto err; goto err;
val |= 0x48;
ret = rtl28xx_wr_reg(adap->dev, SYS_GPIO_OUT_EN, val);
if (ret)
goto err;
/* /*
* Probe used tuner. We need to know used tuner before demod attach * Probe used tuner. We need to know used tuner before demod attach
* since there is some demod params needed to set according to tuner. * since there is some demod params needed to set according to tuner.
@ -419,25 +548,108 @@ static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
if (ret) if (ret)
goto err; goto err;
priv->tuner = TUNER_NONE;
/* check FC0012 ID register; reg=00 val=a1 */
ret = rtl28xxu_ctrl_msg(adap->dev, &req_fc0012);
if (ret == 0 && buf[0] == 0xa1) {
priv->tuner = TUNER_RTL2832_FC0012;
rtl2832_config = &rtl28xxu_rtl2832_fc0012_config;
info("%s: FC0012 tuner found", __func__);
goto found;
}
/* check FC0013 ID register; reg=00 val=a3 */
ret = rtl28xxu_ctrl_msg(adap->dev, &req_fc0013);
if (ret == 0 && buf[0] == 0xa3) {
priv->tuner = TUNER_RTL2832_FC0013;
rtl2832_config = &rtl28xxu_rtl2832_fc0013_config;
info("%s: FC0013 tuner found", __func__);
goto found;
}
/* check MT2266 ID register; reg=00 val=85 */
ret = rtl28xxu_ctrl_msg(adap->dev, &req_mt2266);
if (ret == 0 && buf[0] == 0x85) {
priv->tuner = TUNER_RTL2832_MT2266;
/* TODO implement tuner */
info("%s: MT2266 tuner found", __func__);
goto unsupported;
}
/* check FC2580 ID register; reg=01 val=56 */ /* check FC2580 ID register; reg=01 val=56 */
ret = rtl28xxu_ctrl_msg(adap->dev, &req_fc2580); ret = rtl28xxu_ctrl_msg(adap->dev, &req_fc2580);
if (ret == 0 && buf[0] == 0x56) { if (ret == 0 && buf[0] == 0x56) {
priv->tuner = TUNER_RTL2832_FC2580; priv->tuner = TUNER_RTL2832_FC2580;
deb_info("%s: FC2580\n", __func__); /* TODO implement tuner */
goto found; info("%s: FC2580 tuner found", __func__);
} else { goto unsupported;
deb_info("%s: FC2580 probe failed=%d - %02x\n",
__func__, ret, buf[0]);
} }
/* check MT2063 ID register; reg=00 val=9e || 9c */
ret = rtl28xxu_ctrl_msg(adap->dev, &req_mt2063);
if (ret == 0 && (buf[0] == 0x9e || buf[0] == 0x9c)) {
priv->tuner = TUNER_RTL2832_MT2063;
/* TODO implement tuner */
info("%s: MT2063 tuner found", __func__);
goto unsupported;
}
/* check MAX3543 ID register; reg=00 val=38 */
ret = rtl28xxu_ctrl_msg(adap->dev, &req_max3543);
if (ret == 0 && buf[0] == 0x38) {
priv->tuner = TUNER_RTL2832_MAX3543;
/* TODO implement tuner */
info("%s: MAX3534 tuner found", __func__);
goto unsupported;
}
/* check TUA9001 ID register; reg=7e val=2328 */
ret = rtl28xxu_ctrl_msg(adap->dev, &req_tua9001);
if (ret == 0 && buf[0] == 0x23 && buf[1] == 0x28) {
priv->tuner = TUNER_RTL2832_TUA9001;
/* TODO implement tuner */
info("%s: TUA9001 tuner found", __func__);
goto unsupported;
}
/* check MXL5007R ID register; reg=d9 val=14 */
ret = rtl28xxu_ctrl_msg(adap->dev, &req_mxl5007t);
if (ret == 0 && buf[0] == 0x14) {
priv->tuner = TUNER_RTL2832_MXL5007T;
/* TODO implement tuner */
info("%s: MXL5007T tuner found", __func__);
goto unsupported;
}
/* check E4000 ID register; reg=02 val=40 */
ret = rtl28xxu_ctrl_msg(adap->dev, &req_e4000);
if (ret == 0 && buf[0] == 0x40) {
priv->tuner = TUNER_RTL2832_E4000;
/* TODO implement tuner */
info("%s: E4000 tuner found", __func__);
goto unsupported;
}
/* check TDA18272 ID register; reg=00 val=c760 */
ret = rtl28xxu_ctrl_msg(adap->dev, &req_tda18272);
if (ret == 0 && (buf[0] == 0xc7 || buf[1] == 0x60)) {
priv->tuner = TUNER_RTL2832_TDA18272;
/* TODO implement tuner */
info("%s: TDA18272 tuner found", __func__);
goto unsupported;
}
unsupported:
/* close demod I2C gate */ /* close demod I2C gate */
ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate_close); ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate_close);
if (ret) if (ret)
goto err; goto err;
/* tuner not found */ /* tuner not found */
deb_info("No compatible tuner found");
ret = -ENODEV; ret = -ENODEV;
goto err; return ret;
found: found:
/* close demod I2C gate */ /* close demod I2C gate */
@ -446,9 +658,18 @@ found:
goto err; goto err;
/* attach demodulator */ /* attach demodulator */
/* TODO: */ adap->fe_adap[0].fe = dvb_attach(rtl2832_attach, rtl2832_config,
&adap->dev->i2c_adap);
if (adap->fe_adap[0].fe == NULL) {
ret = -ENODEV;
goto err;
}
/* set fe callbacks */
adap->fe_adap[0].fe->callback = rtl2832u_frontend_callback;
return ret; return ret;
err: err:
deb_info("%s: failed=%d\n", __func__, ret); deb_info("%s: failed=%d\n", __func__, ret);
return ret; return ret;
@ -531,10 +752,24 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
deb_info("%s:\n", __func__); deb_info("%s:\n", __func__);
switch (priv->tuner) { switch (priv->tuner) {
case TUNER_RTL2832_FC2580: case TUNER_RTL2832_FC0012:
/* TODO: */ fe = dvb_attach(fc0012_attach, adap->fe_adap[0].fe,
fe = NULL; &adap->dev->i2c_adap, 0xc6>>1, 0, FC_XTAL_28_8_MHZ);
/* since fc0012 includs reading the signal strength delegate
* that to the tuner driver */
adap->fe_adap[0].fe->ops.read_signal_strength = adap->fe_adap[0].
fe->ops.tuner_ops.get_rf_strength;
return 0;
break; break;
case TUNER_RTL2832_FC0013:
fe = dvb_attach(fc0013_attach, adap->fe_adap[0].fe,
&adap->dev->i2c_adap, 0xc6>>1, 0, FC_XTAL_28_8_MHZ);
/* fc0013 also supports signal strength reading */
adap->fe_adap[0].fe->ops.read_signal_strength = adap->fe_adap[0]
.fe->ops.tuner_ops.get_rf_strength;
return 0;
default: default:
fe = NULL; fe = NULL;
err("unknown tuner=%d", priv->tuner); err("unknown tuner=%d", priv->tuner);
@ -551,14 +786,14 @@ err:
return ret; return ret;
} }
static int rtl28xxu_streaming_ctrl(struct dvb_usb_adapter *adap , int onoff) static int rtl2831u_streaming_ctrl(struct dvb_usb_adapter *adap , int onoff)
{ {
int ret; int ret;
u8 buf[2], gpio; u8 buf[2], gpio;
deb_info("%s: onoff=%d\n", __func__, onoff); deb_info("%s: onoff=%d\n", __func__, onoff);
ret = rtl2831_rd_reg(adap->dev, SYS_GPIO_OUT_VAL, &gpio); ret = rtl28xx_rd_reg(adap->dev, SYS_GPIO_OUT_VAL, &gpio);
if (ret) if (ret)
goto err; goto err;
@ -572,11 +807,11 @@ static int rtl28xxu_streaming_ctrl(struct dvb_usb_adapter *adap , int onoff)
gpio &= (~0x04); /* LED off */ gpio &= (~0x04); /* LED off */
} }
ret = rtl2831_wr_reg(adap->dev, SYS_GPIO_OUT_VAL, gpio); ret = rtl28xx_wr_reg(adap->dev, SYS_GPIO_OUT_VAL, gpio);
if (ret) if (ret)
goto err; goto err;
ret = rtl2831_wr_regs(adap->dev, USB_EPA_CTL, buf, 2); ret = rtl28xx_wr_regs(adap->dev, USB_EPA_CTL, buf, 2);
if (ret) if (ret)
goto err; goto err;
@ -586,7 +821,33 @@ err:
return ret; return ret;
} }
static int rtl28xxu_power_ctrl(struct dvb_usb_device *d, int onoff) static int rtl2832u_streaming_ctrl(struct dvb_usb_adapter *adap , int onoff)
{
int ret;
u8 buf[2];
deb_info("%s: onoff=%d\n", __func__, onoff);
if (onoff) {
buf[0] = 0x00;
buf[1] = 0x00;
} else {
buf[0] = 0x10; /* stall EPA */
buf[1] = 0x02; /* reset EPA */
}
ret = rtl28xx_wr_regs(adap->dev, USB_EPA_CTL, buf, 2);
if (ret)
goto err;
return ret;
err:
deb_info("%s: failed=%d\n", __func__, ret);
return ret;
}
static int rtl2831u_power_ctrl(struct dvb_usb_device *d, int onoff)
{ {
int ret; int ret;
u8 gpio, sys0; u8 gpio, sys0;
@ -594,12 +855,12 @@ static int rtl28xxu_power_ctrl(struct dvb_usb_device *d, int onoff)
deb_info("%s: onoff=%d\n", __func__, onoff); deb_info("%s: onoff=%d\n", __func__, onoff);
/* demod adc */ /* demod adc */
ret = rtl2831_rd_reg(d, SYS_SYS0, &sys0); ret = rtl28xx_rd_reg(d, SYS_SYS0, &sys0);
if (ret) if (ret)
goto err; goto err;
/* tuner power, read GPIOs */ /* tuner power, read GPIOs */
ret = rtl2831_rd_reg(d, SYS_GPIO_OUT_VAL, &gpio); ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &gpio);
if (ret) if (ret)
goto err; goto err;
@ -619,12 +880,12 @@ static int rtl28xxu_power_ctrl(struct dvb_usb_device *d, int onoff)
deb_info("%s: WR SYS0=%02x GPIO_OUT_VAL=%02x\n", __func__, sys0, gpio); deb_info("%s: WR SYS0=%02x GPIO_OUT_VAL=%02x\n", __func__, sys0, gpio);
/* demod adc */ /* demod adc */
ret = rtl2831_wr_reg(d, SYS_SYS0, sys0); ret = rtl28xx_wr_reg(d, SYS_SYS0, sys0);
if (ret) if (ret)
goto err; goto err;
/* tuner power, write GPIOs */ /* tuner power, write GPIOs */
ret = rtl2831_wr_reg(d, SYS_GPIO_OUT_VAL, gpio); ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, gpio);
if (ret) if (ret)
goto err; goto err;
@ -634,6 +895,128 @@ err:
return ret; return ret;
} }
static int rtl2832u_power_ctrl(struct dvb_usb_device *d, int onoff)
{
int ret;
u8 val;
deb_info("%s: onoff=%d\n", __func__, onoff);
if (onoff) {
/* set output values */
ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &val);
if (ret)
goto err;
val |= 0x08;
val &= 0xef;
ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, val);
if (ret)
goto err;
/* demod_ctl_1 */
ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL1, &val);
if (ret)
goto err;
val &= 0xef;
ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL1, val);
if (ret)
goto err;
/* demod control */
/* PLL enable */
ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val);
if (ret)
goto err;
/* bit 7 to 1 */
val |= 0x80;
ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val);
if (ret)
goto err;
/* demod HW reset */
ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val);
if (ret)
goto err;
/* bit 5 to 0 */
val &= 0xdf;
ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val);
if (ret)
goto err;
ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val);
if (ret)
goto err;
val |= 0x20;
ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val);
if (ret)
goto err;
mdelay(5);
/*enable ADC_Q and ADC_I */
ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val);
if (ret)
goto err;
val |= 0x48;
ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val);
if (ret)
goto err;
} else {
/* demod_ctl_1 */
ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL1, &val);
if (ret)
goto err;
val |= 0x0c;
ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL1, val);
if (ret)
goto err;
/* set output values */
ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &val);
if (ret)
goto err;
val |= 0x10;
ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, val);
if (ret)
goto err;
/* demod control */
ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val);
if (ret)
goto err;
val &= 0x37;
ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val);
if (ret)
goto err;
}
return ret;
err:
deb_info("%s: failed=%d\n", __func__, ret);
return ret;
}
static int rtl2831u_rc_query(struct dvb_usb_device *d) static int rtl2831u_rc_query(struct dvb_usb_device *d)
{ {
int ret, i; int ret, i;
@ -660,7 +1043,7 @@ static int rtl2831u_rc_query(struct dvb_usb_device *d)
/* init remote controller */ /* init remote controller */
if (!priv->rc_active) { if (!priv->rc_active) {
for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) { for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) {
ret = rtl2831_wr_reg(d, rc_nec_tab[i].reg, ret = rtl28xx_wr_reg(d, rc_nec_tab[i].reg,
rc_nec_tab[i].val); rc_nec_tab[i].val);
if (ret) if (ret)
goto err; goto err;
@ -690,12 +1073,12 @@ static int rtl2831u_rc_query(struct dvb_usb_device *d)
rc_keydown(d->rc_dev, rc_code, 0); rc_keydown(d->rc_dev, rc_code, 0);
ret = rtl2831_wr_reg(d, SYS_IRRC_SR, 1); ret = rtl28xx_wr_reg(d, SYS_IRRC_SR, 1);
if (ret) if (ret)
goto err; goto err;
/* repeated intentionally to avoid extra keypress */ /* repeated intentionally to avoid extra keypress */
ret = rtl2831_wr_reg(d, SYS_IRRC_SR, 1); ret = rtl28xx_wr_reg(d, SYS_IRRC_SR, 1);
if (ret) if (ret)
goto err; goto err;
} }
@ -732,7 +1115,7 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d)
/* init remote controller */ /* init remote controller */
if (!priv->rc_active) { if (!priv->rc_active) {
for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) { for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) {
ret = rtl2831_wr_reg(d, rc_nec_tab[i].reg, ret = rtl28xx_wr_reg(d, rc_nec_tab[i].reg,
rc_nec_tab[i].val); rc_nec_tab[i].val);
if (ret) if (ret)
goto err; goto err;
@ -740,14 +1123,14 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d)
priv->rc_active = true; priv->rc_active = true;
} }
ret = rtl2831_rd_reg(d, IR_RX_IF, &buf[0]); ret = rtl28xx_rd_reg(d, IR_RX_IF, &buf[0]);
if (ret) if (ret)
goto err; goto err;
if (buf[0] != 0x83) if (buf[0] != 0x83)
goto exit; goto exit;
ret = rtl2831_rd_reg(d, IR_RX_BC, &buf[0]); ret = rtl28xx_rd_reg(d, IR_RX_BC, &buf[0]);
if (ret) if (ret)
goto err; goto err;
@ -756,9 +1139,9 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d)
/* TODO: pass raw IR to Kernel IR decoder */ /* TODO: pass raw IR to Kernel IR decoder */
ret = rtl2831_wr_reg(d, IR_RX_IF, 0x03); ret = rtl28xx_wr_reg(d, IR_RX_IF, 0x03);
ret = rtl2831_wr_reg(d, IR_RX_BUF_CTRL, 0x80); ret = rtl28xx_wr_reg(d, IR_RX_BUF_CTRL, 0x80);
ret = rtl2831_wr_reg(d, IR_RX_CTRL, 0x80); ret = rtl28xx_wr_reg(d, IR_RX_CTRL, 0x80);
exit: exit:
return ret; return ret;
@ -771,6 +1154,9 @@ enum rtl28xxu_usb_table_entry {
RTL2831U_0BDA_2831, RTL2831U_0BDA_2831,
RTL2831U_14AA_0160, RTL2831U_14AA_0160,
RTL2831U_14AA_0161, RTL2831U_14AA_0161,
RTL2832U_0CCD_00A9,
RTL2832U_1F4D_B803,
RTL2832U_0CCD_00B3,
}; };
static struct usb_device_id rtl28xxu_table[] = { static struct usb_device_id rtl28xxu_table[] = {
@ -783,6 +1169,12 @@ static struct usb_device_id rtl28xxu_table[] = {
USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT_2)}, USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT_2)},
/* RTL2832U */ /* RTL2832U */
[RTL2832U_0CCD_00A9] = {
USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_BLACK_REV1)},
[RTL2832U_1F4D_B803] = {
USB_DEVICE(USB_VID_GTEK, USB_PID_DELOCK_USB2_DVBT)},
[RTL2832U_0CCD_00B3] = {
USB_DEVICE(USB_VID_TERRATEC, USB_PID_NOXON_DAB_STICK)},
{} /* terminating entry */ {} /* terminating entry */
}; };
@ -805,7 +1197,7 @@ static struct dvb_usb_device_properties rtl28xxu_properties[] = {
{ {
.frontend_attach = rtl2831u_frontend_attach, .frontend_attach = rtl2831u_frontend_attach,
.tuner_attach = rtl2831u_tuner_attach, .tuner_attach = rtl2831u_tuner_attach,
.streaming_ctrl = rtl28xxu_streaming_ctrl, .streaming_ctrl = rtl2831u_streaming_ctrl,
.stream = { .stream = {
.type = USB_BULK, .type = USB_BULK,
.count = 6, .count = 6,
@ -821,7 +1213,7 @@ static struct dvb_usb_device_properties rtl28xxu_properties[] = {
} }
}, },
.power_ctrl = rtl28xxu_power_ctrl, .power_ctrl = rtl2831u_power_ctrl,
.rc.core = { .rc.core = {
.protocol = RC_TYPE_NEC, .protocol = RC_TYPE_NEC,
@ -867,7 +1259,7 @@ static struct dvb_usb_device_properties rtl28xxu_properties[] = {
{ {
.frontend_attach = rtl2832u_frontend_attach, .frontend_attach = rtl2832u_frontend_attach,
.tuner_attach = rtl2832u_tuner_attach, .tuner_attach = rtl2832u_tuner_attach,
.streaming_ctrl = rtl28xxu_streaming_ctrl, .streaming_ctrl = rtl2832u_streaming_ctrl,
.stream = { .stream = {
.type = USB_BULK, .type = USB_BULK,
.count = 6, .count = 6,
@ -883,7 +1275,7 @@ static struct dvb_usb_device_properties rtl28xxu_properties[] = {
} }
}, },
.power_ctrl = rtl28xxu_power_ctrl, .power_ctrl = rtl2832u_power_ctrl,
.rc.core = { .rc.core = {
.protocol = RC_TYPE_NEC, .protocol = RC_TYPE_NEC,
@ -896,10 +1288,25 @@ static struct dvb_usb_device_properties rtl28xxu_properties[] = {
.i2c_algo = &rtl28xxu_i2c_algo, .i2c_algo = &rtl28xxu_i2c_algo,
.num_device_descs = 0, /* disabled as no support for RTL2832 */ .num_device_descs = 3,
.devices = { .devices = {
{ {
.name = "Realtek RTL2832U reference design", .name = "Terratec Cinergy T Stick Black",
.warm_ids = {
&rtl28xxu_table[RTL2832U_0CCD_00A9],
},
},
{
.name = "G-Tek Electronics Group Lifeview LV5TDLX DVB-T",
.warm_ids = {
&rtl28xxu_table[RTL2832U_1F4D_B803],
},
},
{
.name = "NOXON DAB/DAB+ USB dongle",
.warm_ids = {
&rtl28xxu_table[RTL2832U_0CCD_00B3],
},
}, },
} }
}, },
@ -910,6 +1317,7 @@ static int rtl28xxu_probe(struct usb_interface *intf,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
int ret, i; int ret, i;
u8 val;
int properties_count = ARRAY_SIZE(rtl28xxu_properties); int properties_count = ARRAY_SIZE(rtl28xxu_properties);
struct dvb_usb_device *d; struct dvb_usb_device *d;
struct usb_device *udev; struct usb_device *udev;
@ -954,16 +1362,25 @@ static int rtl28xxu_probe(struct usb_interface *intf,
if (ret) if (ret)
goto err; goto err;
/* init USB endpoints */ /* init USB endpoints */
ret = rtl2831_wr_reg(d, USB_SYSCTL_0, 0x09); ret = rtl28xx_rd_reg(d, USB_SYSCTL_0, &val);
if (ret)
goto err;
/* enable DMA and Full Packet Mode*/
val |= 0x09;
ret = rtl28xx_wr_reg(d, USB_SYSCTL_0, val);
if (ret) if (ret)
goto err; goto err;
ret = rtl2831_wr_regs(d, USB_EPA_MAXPKT, "\x00\x02\x00\x00", 4); /* set EPA maximum packet size to 0x0200 */
ret = rtl28xx_wr_regs(d, USB_EPA_MAXPKT, "\x00\x02\x00\x00", 4);
if (ret) if (ret)
goto err; goto err;
ret = rtl2831_wr_regs(d, USB_EPA_FIFO_CFG, "\x14\x00\x00\x00", 4); /* change EPA FIFO length */
ret = rtl28xx_wr_regs(d, USB_EPA_FIFO_CFG, "\x14\x00\x00\x00", 4);
if (ret) if (ret)
goto err; goto err;
@ -1007,4 +1424,5 @@ module_exit(rtl28xxu_module_exit);
MODULE_DESCRIPTION("Realtek RTL28xxU DVB USB driver"); MODULE_DESCRIPTION("Realtek RTL28xxU DVB USB driver");
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
MODULE_AUTHOR("Thomas Mair <thomas.mair86@googlemail.com>");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");

View File

@ -1,6 +1,7 @@
config DVB_FE_CUSTOMISE config DVB_FE_CUSTOMISE
bool "Customise the frontend modules to build" bool "Customise the frontend modules to build"
depends on DVB_CORE depends on DVB_CORE
depends on EXPERT
default y if EXPERT default y if EXPERT
help help
This allows the user to select/deselect frontend drivers for their This allows the user to select/deselect frontend drivers for their
@ -432,6 +433,13 @@ config DVB_RTL2830
help help
Say Y when you want to support this frontend. Say Y when you want to support this frontend.
config DVB_RTL2832
tristate "Realtek RTL2832 DVB-T"
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
help
Say Y when you want to support this frontend.
comment "DVB-C (cable) frontends" comment "DVB-C (cable) frontends"
depends on DVB_CORE depends on DVB_CORE

View File

@ -99,6 +99,7 @@ obj-$(CONFIG_DVB_IT913X_FE) += it913x-fe.o
obj-$(CONFIG_DVB_A8293) += a8293.o obj-$(CONFIG_DVB_A8293) += a8293.o
obj-$(CONFIG_DVB_TDA10071) += tda10071.o obj-$(CONFIG_DVB_TDA10071) += tda10071.o
obj-$(CONFIG_DVB_RTL2830) += rtl2830.o obj-$(CONFIG_DVB_RTL2830) += rtl2830.o
obj-$(CONFIG_DVB_RTL2832) += rtl2832.o
obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o
obj-$(CONFIG_DVB_AF9033) += af9033.o obj-$(CONFIG_DVB_AF9033) += af9033.o

View File

@ -21,24 +21,6 @@
#include "dvb_frontend.h" #include "dvb_frontend.h"
#include "a8293.h" #include "a8293.h"
static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
#define LOG_PREFIX "a8293"
#undef dbg
#define dbg(f, arg...) \
if (debug) \
printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg)
#undef err
#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg)
#undef info
#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg)
#undef warn
#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
struct a8293_priv { struct a8293_priv {
struct i2c_adapter *i2c; struct i2c_adapter *i2c;
const struct a8293_config *cfg; const struct a8293_config *cfg;
@ -65,7 +47,8 @@ static int a8293_i2c(struct a8293_priv *priv, u8 *val, int len, bool rd)
if (ret == 1) { if (ret == 1) {
ret = 0; ret = 0;
} else { } else {
warn("i2c failed=%d rd=%d", ret, rd); dev_warn(&priv->i2c->dev, "%s: i2c failed=%d rd=%d\n",
KBUILD_MODNAME, ret, rd);
ret = -EREMOTEIO; ret = -EREMOTEIO;
} }
@ -88,7 +71,8 @@ static int a8293_set_voltage(struct dvb_frontend *fe,
struct a8293_priv *priv = fe->sec_priv; struct a8293_priv *priv = fe->sec_priv;
int ret; int ret;
dbg("%s: fe_sec_voltage=%d", __func__, fe_sec_voltage); dev_dbg(&priv->i2c->dev, "%s: fe_sec_voltage=%d\n", __func__,
fe_sec_voltage);
switch (fe_sec_voltage) { switch (fe_sec_voltage) {
case SEC_VOLTAGE_OFF: case SEC_VOLTAGE_OFF:
@ -114,14 +98,12 @@ static int a8293_set_voltage(struct dvb_frontend *fe,
return ret; return ret;
err: err:
dbg("%s: failed=%d", __func__, ret); dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
return ret; return ret;
} }
static void a8293_release_sec(struct dvb_frontend *fe) static void a8293_release_sec(struct dvb_frontend *fe)
{ {
dbg("%s:", __func__);
a8293_set_voltage(fe, SEC_VOLTAGE_OFF); a8293_set_voltage(fe, SEC_VOLTAGE_OFF);
kfree(fe->sec_priv); kfree(fe->sec_priv);
@ -154,7 +136,7 @@ struct dvb_frontend *a8293_attach(struct dvb_frontend *fe,
/* ENB=0 */ /* ENB=0 */
priv->reg[0] = 0x10; priv->reg[0] = 0x10;
ret = a8293_wr(priv, &priv->reg[1], 1); ret = a8293_wr(priv, &priv->reg[0], 1);
if (ret) if (ret)
goto err; goto err;
@ -164,16 +146,17 @@ struct dvb_frontend *a8293_attach(struct dvb_frontend *fe,
if (ret) if (ret)
goto err; goto err;
info("Allegro A8293 SEC attached.");
fe->ops.release_sec = a8293_release_sec; fe->ops.release_sec = a8293_release_sec;
/* override frontend ops */ /* override frontend ops */
fe->ops.set_voltage = a8293_set_voltage; fe->ops.set_voltage = a8293_set_voltage;
dev_info(&priv->i2c->dev, "%s: Allegro A8293 SEC attached\n",
KBUILD_MODNAME);
return fe; return fe;
err: err:
dbg("%s: failed=%d", __func__, ret); dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret);
kfree(priv); kfree(priv);
return NULL; return NULL;
} }

View File

@ -20,6 +20,14 @@
* means that 1=DVBC, 0 = DVBT. Zero means the opposite. * means that 1=DVBC, 0 = DVBT. Zero means the opposite.
* @mpeg_out_clk_strength: DRXK Mpeg output clock drive strength. * @mpeg_out_clk_strength: DRXK Mpeg output clock drive strength.
* @microcode_name: Name of the firmware file with the microcode * @microcode_name: Name of the firmware file with the microcode
* @qam_demod_parameter_count: The number of parameters used for the command
* to set the demodulator parameters. All
* firmwares are using the 2-parameter commmand.
* An exception is the "drxk_a3.mc" firmware,
* which uses the 4-parameter command.
* A value of 0 (default) or lower indicates that
* the correct number of parameters will be
* automatically detected.
* *
* On the *_gpio vars, bit 0 is UIO-1, bit 1 is UIO-2 and bit 2 is * On the *_gpio vars, bit 0 is UIO-1, bit 1 is UIO-2 and bit 2 is
* UIO-3. * UIO-3.
@ -38,7 +46,8 @@ struct drxk_config {
u8 mpeg_out_clk_strength; u8 mpeg_out_clk_strength;
int chunk_size; int chunk_size;
const char *microcode_name; const char *microcode_name;
int qam_demod_parameter_count;
}; };
#if defined(CONFIG_DVB_DRXK) || (defined(CONFIG_DVB_DRXK_MODULE) \ #if defined(CONFIG_DVB_DRXK) || (defined(CONFIG_DVB_DRXK_MODULE) \

View File

@ -28,6 +28,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/hardirq.h>
#include <asm/div64.h> #include <asm/div64.h>
#include "dvb_frontend.h" #include "dvb_frontend.h"
@ -308,16 +309,42 @@ static u32 Log10Times100(u32 x)
/* I2C **********************************************************************/ /* I2C **********************************************************************/
/****************************************************************************/ /****************************************************************************/
static int i2c_read1(struct i2c_adapter *adapter, u8 adr, u8 *val) static int drxk_i2c_lock(struct drxk_state *state)
{
i2c_lock_adapter(state->i2c);
state->drxk_i2c_exclusive_lock = true;
return 0;
}
static void drxk_i2c_unlock(struct drxk_state *state)
{
if (!state->drxk_i2c_exclusive_lock)
return;
i2c_unlock_adapter(state->i2c);
state->drxk_i2c_exclusive_lock = false;
}
static int drxk_i2c_transfer(struct drxk_state *state, struct i2c_msg *msgs,
unsigned len)
{
if (state->drxk_i2c_exclusive_lock)
return __i2c_transfer(state->i2c, msgs, len);
else
return i2c_transfer(state->i2c, msgs, len);
}
static int i2c_read1(struct drxk_state *state, u8 adr, u8 *val)
{ {
struct i2c_msg msgs[1] = { {.addr = adr, .flags = I2C_M_RD, struct i2c_msg msgs[1] = { {.addr = adr, .flags = I2C_M_RD,
.buf = val, .len = 1} .buf = val, .len = 1}
}; };
return i2c_transfer(adapter, msgs, 1); return drxk_i2c_transfer(state, msgs, 1);
} }
static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) static int i2c_write(struct drxk_state *state, u8 adr, u8 *data, int len)
{ {
int status; int status;
struct i2c_msg msg = { struct i2c_msg msg = {
@ -330,7 +357,7 @@ static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len)
printk(KERN_CONT " %02x", data[i]); printk(KERN_CONT " %02x", data[i]);
printk(KERN_CONT "\n"); printk(KERN_CONT "\n");
} }
status = i2c_transfer(adap, &msg, 1); status = drxk_i2c_transfer(state, &msg, 1);
if (status >= 0 && status != 1) if (status >= 0 && status != 1)
status = -EIO; status = -EIO;
@ -340,7 +367,7 @@ static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len)
return status; return status;
} }
static int i2c_read(struct i2c_adapter *adap, static int i2c_read(struct drxk_state *state,
u8 adr, u8 *msg, int len, u8 *answ, int alen) u8 adr, u8 *msg, int len, u8 *answ, int alen)
{ {
int status; int status;
@ -351,7 +378,7 @@ static int i2c_read(struct i2c_adapter *adap,
.buf = answ, .len = alen} .buf = answ, .len = alen}
}; };
status = i2c_transfer(adap, msgs, 2); status = drxk_i2c_transfer(state, msgs, 2);
if (status != 2) { if (status != 2) {
if (debug > 2) if (debug > 2)
printk(KERN_CONT ": ERROR!\n"); printk(KERN_CONT ": ERROR!\n");
@ -394,7 +421,7 @@ static int read16_flags(struct drxk_state *state, u32 reg, u16 *data, u8 flags)
len = 2; len = 2;
} }
dprintk(2, "(0x%08x, 0x%02x)\n", reg, flags); dprintk(2, "(0x%08x, 0x%02x)\n", reg, flags);
status = i2c_read(state->i2c, adr, mm1, len, mm2, 2); status = i2c_read(state, adr, mm1, len, mm2, 2);
if (status < 0) if (status < 0)
return status; return status;
if (data) if (data)
@ -428,7 +455,7 @@ static int read32_flags(struct drxk_state *state, u32 reg, u32 *data, u8 flags)
len = 2; len = 2;
} }
dprintk(2, "(0x%08x, 0x%02x)\n", reg, flags); dprintk(2, "(0x%08x, 0x%02x)\n", reg, flags);
status = i2c_read(state->i2c, adr, mm1, len, mm2, 4); status = i2c_read(state, adr, mm1, len, mm2, 4);
if (status < 0) if (status < 0)
return status; return status;
if (data) if (data)
@ -464,7 +491,7 @@ static int write16_flags(struct drxk_state *state, u32 reg, u16 data, u8 flags)
mm[len + 1] = (data >> 8) & 0xff; mm[len + 1] = (data >> 8) & 0xff;
dprintk(2, "(0x%08x, 0x%04x, 0x%02x)\n", reg, data, flags); dprintk(2, "(0x%08x, 0x%04x, 0x%02x)\n", reg, data, flags);
return i2c_write(state->i2c, adr, mm, len + 2); return i2c_write(state, adr, mm, len + 2);
} }
static int write16(struct drxk_state *state, u32 reg, u16 data) static int write16(struct drxk_state *state, u32 reg, u16 data)
@ -495,7 +522,7 @@ static int write32_flags(struct drxk_state *state, u32 reg, u32 data, u8 flags)
mm[len + 3] = (data >> 24) & 0xff; mm[len + 3] = (data >> 24) & 0xff;
dprintk(2, "(0x%08x, 0x%08x, 0x%02x)\n", reg, data, flags); dprintk(2, "(0x%08x, 0x%08x, 0x%02x)\n", reg, data, flags);
return i2c_write(state->i2c, adr, mm, len + 4); return i2c_write(state, adr, mm, len + 4);
} }
static int write32(struct drxk_state *state, u32 reg, u32 data) static int write32(struct drxk_state *state, u32 reg, u32 data)
@ -542,7 +569,7 @@ static int write_block(struct drxk_state *state, u32 Address,
printk(KERN_CONT " %02x", pBlock[i]); printk(KERN_CONT " %02x", pBlock[i]);
printk(KERN_CONT "\n"); printk(KERN_CONT "\n");
} }
status = i2c_write(state->i2c, state->demod_address, status = i2c_write(state, state->demod_address,
&state->Chunk[0], Chunk + AdrLength); &state->Chunk[0], Chunk + AdrLength);
if (status < 0) { if (status < 0) {
printk(KERN_ERR "drxk: %s: i2c write error at addr 0x%02x\n", printk(KERN_ERR "drxk: %s: i2c write error at addr 0x%02x\n",
@ -568,17 +595,17 @@ int PowerUpDevice(struct drxk_state *state)
dprintk(1, "\n"); dprintk(1, "\n");
status = i2c_read1(state->i2c, state->demod_address, &data); status = i2c_read1(state, state->demod_address, &data);
if (status < 0) { if (status < 0) {
do { do {
data = 0; data = 0;
status = i2c_write(state->i2c, state->demod_address, status = i2c_write(state, state->demod_address,
&data, 1); &data, 1);
msleep(10); msleep(10);
retryCount++; retryCount++;
if (status < 0) if (status < 0)
continue; continue;
status = i2c_read1(state->i2c, state->demod_address, status = i2c_read1(state, state->demod_address,
&data); &data);
} while (status < 0 && } while (status < 0 &&
(retryCount < DRXK_MAX_RETRIES_POWERUP)); (retryCount < DRXK_MAX_RETRIES_POWERUP));
@ -932,7 +959,7 @@ static int GetDeviceCapabilities(struct drxk_state *state)
if (status < 0) if (status < 0)
goto error; goto error;
printk(KERN_ERR "drxk: status = 0x%08x\n", sioTopJtagidLo); printk(KERN_INFO "drxk: status = 0x%08x\n", sioTopJtagidLo);
/* driver 0.9.0 */ /* driver 0.9.0 */
switch ((sioTopJtagidLo >> 29) & 0xF) { switch ((sioTopJtagidLo >> 29) & 0xF) {
@ -2824,7 +2851,7 @@ static int ConfigureI2CBridge(struct drxk_state *state, bool bEnableBridge)
dprintk(1, "\n"); dprintk(1, "\n");
if (state->m_DrxkState == DRXK_UNINITIALIZED) if (state->m_DrxkState == DRXK_UNINITIALIZED)
goto error; return 0;
if (state->m_DrxkState == DRXK_POWERED_DOWN) if (state->m_DrxkState == DRXK_POWERED_DOWN)
goto error; goto error;
@ -2977,7 +3004,7 @@ static int ADCSynchronization(struct drxk_state *state)
status = read16(state, IQM_AF_CLKNEG__A, &clkNeg); status = read16(state, IQM_AF_CLKNEG__A, &clkNeg);
if (status < 0) if (status < 0)
goto error; goto error;
if ((clkNeg | IQM_AF_CLKNEG_CLKNEGDATA__M) == if ((clkNeg & IQM_AF_CLKNEG_CLKNEGDATA__M) ==
IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_POS) { IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_POS) {
clkNeg &= (~(IQM_AF_CLKNEG_CLKNEGDATA__M)); clkNeg &= (~(IQM_AF_CLKNEG_CLKNEGDATA__M));
clkNeg |= clkNeg |=
@ -5361,7 +5388,7 @@ static int GetQAMLockStatus(struct drxk_state *state, u32 *pLockStatus)
SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK, 0, NULL, 2, SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK, 0, NULL, 2,
Result); Result);
if (status < 0) if (status < 0)
printk(KERN_ERR "drxk: %s status = %08x\n", __func__, status); printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
if (Result[1] < SCU_RAM_QAM_LOCKED_LOCKED_DEMOD_LOCKED) { if (Result[1] < SCU_RAM_QAM_LOCKED_LOCKED_DEMOD_LOCKED) {
/* 0x0000 NOT LOCKED */ /* 0x0000 NOT LOCKED */
@ -5388,12 +5415,67 @@ static int GetQAMLockStatus(struct drxk_state *state, u32 *pLockStatus)
#define QAM_LOCKRANGE__M 0x10 #define QAM_LOCKRANGE__M 0x10
#define QAM_LOCKRANGE_NORMAL 0x10 #define QAM_LOCKRANGE_NORMAL 0x10
static int QAMDemodulatorCommand(struct drxk_state *state,
int numberOfParameters)
{
int status;
u16 cmdResult;
u16 setParamParameters[4] = { 0, 0, 0, 0 };
setParamParameters[0] = state->m_Constellation; /* modulation */
setParamParameters[1] = DRXK_QAM_I12_J17; /* interleave mode */
if (numberOfParameters == 2) {
u16 setEnvParameters[1] = { 0 };
if (state->m_OperationMode == OM_QAM_ITU_C)
setEnvParameters[0] = QAM_TOP_ANNEX_C;
else
setEnvParameters[0] = QAM_TOP_ANNEX_A;
status = scu_command(state,
SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV,
1, setEnvParameters, 1, &cmdResult);
if (status < 0)
goto error;
status = scu_command(state,
SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM,
numberOfParameters, setParamParameters,
1, &cmdResult);
} else if (numberOfParameters == 4) {
if (state->m_OperationMode == OM_QAM_ITU_C)
setParamParameters[2] = QAM_TOP_ANNEX_C;
else
setParamParameters[2] = QAM_TOP_ANNEX_A;
setParamParameters[3] |= (QAM_MIRROR_AUTO_ON);
/* Env parameters */
/* check for LOCKRANGE Extented */
/* setParamParameters[3] |= QAM_LOCKRANGE_NORMAL; */
status = scu_command(state,
SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM,
numberOfParameters, setParamParameters,
1, &cmdResult);
} else {
printk(KERN_WARNING "drxk: Unknown QAM demodulator parameter "
"count %d\n", numberOfParameters);
}
error:
if (status < 0)
printk(KERN_WARNING "drxk: Warning %d on %s\n",
status, __func__);
return status;
}
static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz, static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz,
s32 tunerFreqOffset) s32 tunerFreqOffset)
{ {
int status; int status;
u16 setParamParameters[4] = { 0, 0, 0, 0 };
u16 cmdResult; u16 cmdResult;
int qamDemodParamCount = state->qam_demod_parameter_count;
dprintk(1, "\n"); dprintk(1, "\n");
/* /*
@ -5445,34 +5527,42 @@ static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz,
} }
if (status < 0) if (status < 0)
goto error; goto error;
setParamParameters[0] = state->m_Constellation; /* modulation */
setParamParameters[1] = DRXK_QAM_I12_J17; /* interleave mode */
if (state->m_OperationMode == OM_QAM_ITU_C)
setParamParameters[2] = QAM_TOP_ANNEX_C;
else
setParamParameters[2] = QAM_TOP_ANNEX_A;
setParamParameters[3] |= (QAM_MIRROR_AUTO_ON);
/* Env parameters */
/* check for LOCKRANGE Extented */
/* setParamParameters[3] |= QAM_LOCKRANGE_NORMAL; */
status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM, 4, setParamParameters, 1, &cmdResult); /* Use the 4-parameter if it's requested or we're probing for
if (status < 0) { * the correct command. */
/* Fall-back to the simpler call */ if (state->qam_demod_parameter_count == 4
if (state->m_OperationMode == OM_QAM_ITU_C) || !state->qam_demod_parameter_count) {
setParamParameters[0] = QAM_TOP_ANNEX_C; qamDemodParamCount = 4;
else status = QAMDemodulatorCommand(state, qamDemodParamCount);
setParamParameters[0] = QAM_TOP_ANNEX_A;
status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV, 1, setParamParameters, 1, &cmdResult);
if (status < 0)
goto error;
setParamParameters[0] = state->m_Constellation; /* modulation */
setParamParameters[1] = DRXK_QAM_I12_J17; /* interleave mode */
status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM, 2, setParamParameters, 1, &cmdResult);
} }
if (status < 0)
/* Use the 2-parameter command if it was requested or if we're
* probing for the correct command and the 4-parameter command
* failed. */
if (state->qam_demod_parameter_count == 2
|| (!state->qam_demod_parameter_count && status < 0)) {
qamDemodParamCount = 2;
status = QAMDemodulatorCommand(state, qamDemodParamCount);
}
if (status < 0) {
dprintk(1, "Could not set demodulator parameters. Make "
"sure qam_demod_parameter_count (%d) is correct for "
"your firmware (%s).\n",
state->qam_demod_parameter_count,
state->microcode_name);
goto error; goto error;
} else if (!state->qam_demod_parameter_count) {
dprintk(1, "Auto-probing the correct QAM demodulator command "
"parameters was successful - using %d parameters.\n",
qamDemodParamCount);
/*
* One of our commands was successful. We don't need to
* auto-probe anymore, now that we got the correct command.
*/
state->qam_demod_parameter_count = qamDemodParamCount;
}
/* /*
* STEP 3: enable the system in a mode where the ADC provides valid * STEP 3: enable the system in a mode where the ADC provides valid
@ -5968,34 +6058,15 @@ error:
return status; return status;
} }
static int load_microcode(struct drxk_state *state, const char *mc_name)
{
const struct firmware *fw = NULL;
int err = 0;
dprintk(1, "\n");
err = request_firmware(&fw, mc_name, state->i2c->dev.parent);
if (err < 0) {
printk(KERN_ERR
"drxk: Could not load firmware file %s.\n", mc_name);
printk(KERN_INFO
"drxk: Copy %s to your hotplug directory!\n", mc_name);
return err;
}
err = DownloadMicrocode(state, fw->data, fw->size);
release_firmware(fw);
return err;
}
static int init_drxk(struct drxk_state *state) static int init_drxk(struct drxk_state *state)
{ {
int status = 0; int status = 0, n = 0;
enum DRXPowerMode powerMode = DRXK_POWER_DOWN_OFDM; enum DRXPowerMode powerMode = DRXK_POWER_DOWN_OFDM;
u16 driverVersion; u16 driverVersion;
dprintk(1, "\n"); dprintk(1, "\n");
if ((state->m_DrxkState == DRXK_UNINITIALIZED)) { if ((state->m_DrxkState == DRXK_UNINITIALIZED)) {
drxk_i2c_lock(state);
status = PowerUpDevice(state); status = PowerUpDevice(state);
if (status < 0) if (status < 0)
goto error; goto error;
@ -6073,8 +6144,12 @@ static int init_drxk(struct drxk_state *state)
if (status < 0) if (status < 0)
goto error; goto error;
if (state->microcode_name) if (state->fw) {
load_microcode(state, state->microcode_name); status = DownloadMicrocode(state, state->fw->data,
state->fw->size);
if (status < 0)
goto error;
}
/* disable token-ring bus through OFDM block for possible ucode upload */ /* disable token-ring bus through OFDM block for possible ucode upload */
status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, SIO_OFDM_SH_OFDM_RING_ENABLE_OFF); status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, SIO_OFDM_SH_OFDM_RING_ENABLE_OFF);
@ -6167,19 +6242,71 @@ static int init_drxk(struct drxk_state *state)
state->m_DrxkState = DRXK_POWERED_DOWN; state->m_DrxkState = DRXK_POWERED_DOWN;
} else } else
state->m_DrxkState = DRXK_STOPPED; state->m_DrxkState = DRXK_STOPPED;
/* Initialize the supported delivery systems */
n = 0;
if (state->m_hasDVBC) {
state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_A;
state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_C;
strlcat(state->frontend.ops.info.name, " DVB-C",
sizeof(state->frontend.ops.info.name));
}
if (state->m_hasDVBT) {
state->frontend.ops.delsys[n++] = SYS_DVBT;
strlcat(state->frontend.ops.info.name, " DVB-T",
sizeof(state->frontend.ops.info.name));
}
drxk_i2c_unlock(state);
} }
error: error:
if (status < 0) if (status < 0) {
state->m_DrxkState = DRXK_NO_DEV;
drxk_i2c_unlock(state);
printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__); printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
}
return status; return status;
} }
static void load_firmware_cb(const struct firmware *fw,
void *context)
{
struct drxk_state *state = context;
dprintk(1, ": %s\n", fw ? "firmware loaded" : "firmware not loaded");
if (!fw) {
printk(KERN_ERR
"drxk: Could not load firmware file %s.\n",
state->microcode_name);
printk(KERN_INFO
"drxk: Copy %s to your hotplug directory!\n",
state->microcode_name);
state->microcode_name = NULL;
/*
* As firmware is now load asynchronous, it is not possible
* anymore to fail at frontend attach. We might silently
* return here, and hope that the driver won't crash.
* We might also change all DVB callbacks to return -ENODEV
* if the device is not initialized.
* As the DRX-K devices have their own internal firmware,
* let's just hope that it will match a firmware revision
* compatible with this driver and proceed.
*/
}
state->fw = fw;
init_drxk(state);
}
static void drxk_release(struct dvb_frontend *fe) static void drxk_release(struct dvb_frontend *fe)
{ {
struct drxk_state *state = fe->demodulator_priv; struct drxk_state *state = fe->demodulator_priv;
dprintk(1, "\n"); dprintk(1, "\n");
if (state->fw)
release_firmware(state->fw);
kfree(state); kfree(state);
} }
@ -6188,6 +6315,12 @@ static int drxk_sleep(struct dvb_frontend *fe)
struct drxk_state *state = fe->demodulator_priv; struct drxk_state *state = fe->demodulator_priv;
dprintk(1, "\n"); dprintk(1, "\n");
if (state->m_DrxkState == DRXK_NO_DEV)
return -ENODEV;
if (state->m_DrxkState == DRXK_UNINITIALIZED)
return 0;
ShutDown(state); ShutDown(state);
return 0; return 0;
} }
@ -6196,7 +6329,11 @@ static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
{ {
struct drxk_state *state = fe->demodulator_priv; struct drxk_state *state = fe->demodulator_priv;
dprintk(1, "%s\n", enable ? "enable" : "disable"); dprintk(1, ": %s\n", enable ? "enable" : "disable");
if (state->m_DrxkState == DRXK_NO_DEV)
return -ENODEV;
return ConfigureI2CBridge(state, enable ? true : false); return ConfigureI2CBridge(state, enable ? true : false);
} }
@ -6209,6 +6346,12 @@ static int drxk_set_parameters(struct dvb_frontend *fe)
dprintk(1, "\n"); dprintk(1, "\n");
if (state->m_DrxkState == DRXK_NO_DEV)
return -ENODEV;
if (state->m_DrxkState == DRXK_UNINITIALIZED)
return -EAGAIN;
if (!fe->ops.tuner_ops.get_if_frequency) { if (!fe->ops.tuner_ops.get_if_frequency) {
printk(KERN_ERR printk(KERN_ERR
"drxk: Error: get_if_frequency() not defined at tuner. Can't work without it!\n"); "drxk: Error: get_if_frequency() not defined at tuner. Can't work without it!\n");
@ -6262,6 +6405,12 @@ static int drxk_read_status(struct dvb_frontend *fe, fe_status_t *status)
u32 stat; u32 stat;
dprintk(1, "\n"); dprintk(1, "\n");
if (state->m_DrxkState == DRXK_NO_DEV)
return -ENODEV;
if (state->m_DrxkState == DRXK_UNINITIALIZED)
return -EAGAIN;
*status = 0; *status = 0;
GetLockStatus(state, &stat, 0); GetLockStatus(state, &stat, 0);
if (stat == MPEG_LOCK) if (stat == MPEG_LOCK)
@ -6275,8 +6424,15 @@ static int drxk_read_status(struct dvb_frontend *fe, fe_status_t *status)
static int drxk_read_ber(struct dvb_frontend *fe, u32 *ber) static int drxk_read_ber(struct dvb_frontend *fe, u32 *ber)
{ {
struct drxk_state *state = fe->demodulator_priv;
dprintk(1, "\n"); dprintk(1, "\n");
if (state->m_DrxkState == DRXK_NO_DEV)
return -ENODEV;
if (state->m_DrxkState == DRXK_UNINITIALIZED)
return -EAGAIN;
*ber = 0; *ber = 0;
return 0; return 0;
} }
@ -6288,6 +6444,12 @@ static int drxk_read_signal_strength(struct dvb_frontend *fe,
u32 val = 0; u32 val = 0;
dprintk(1, "\n"); dprintk(1, "\n");
if (state->m_DrxkState == DRXK_NO_DEV)
return -ENODEV;
if (state->m_DrxkState == DRXK_UNINITIALIZED)
return -EAGAIN;
ReadIFAgc(state, &val); ReadIFAgc(state, &val);
*strength = val & 0xffff; *strength = val & 0xffff;
return 0; return 0;
@ -6299,6 +6461,12 @@ static int drxk_read_snr(struct dvb_frontend *fe, u16 *snr)
s32 snr2; s32 snr2;
dprintk(1, "\n"); dprintk(1, "\n");
if (state->m_DrxkState == DRXK_NO_DEV)
return -ENODEV;
if (state->m_DrxkState == DRXK_UNINITIALIZED)
return -EAGAIN;
GetSignalToNoise(state, &snr2); GetSignalToNoise(state, &snr2);
*snr = snr2 & 0xffff; *snr = snr2 & 0xffff;
return 0; return 0;
@ -6310,6 +6478,12 @@ static int drxk_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
u16 err; u16 err;
dprintk(1, "\n"); dprintk(1, "\n");
if (state->m_DrxkState == DRXK_NO_DEV)
return -ENODEV;
if (state->m_DrxkState == DRXK_UNINITIALIZED)
return -EAGAIN;
DVBTQAMGetAccPktErr(state, &err); DVBTQAMGetAccPktErr(state, &err);
*ucblocks = (u32) err; *ucblocks = (u32) err;
return 0; return 0;
@ -6318,9 +6492,16 @@ static int drxk_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
static int drxk_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings static int drxk_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings
*sets) *sets)
{ {
struct drxk_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct dtv_frontend_properties *p = &fe->dtv_property_cache;
dprintk(1, "\n"); dprintk(1, "\n");
if (state->m_DrxkState == DRXK_NO_DEV)
return -ENODEV;
if (state->m_DrxkState == DRXK_UNINITIALIZED)
return -EAGAIN;
switch (p->delivery_system) { switch (p->delivery_system) {
case SYS_DVBC_ANNEX_A: case SYS_DVBC_ANNEX_A:
case SYS_DVBC_ANNEX_C: case SYS_DVBC_ANNEX_C:
@ -6371,10 +6552,9 @@ static struct dvb_frontend_ops drxk_ops = {
struct dvb_frontend *drxk_attach(const struct drxk_config *config, struct dvb_frontend *drxk_attach(const struct drxk_config *config,
struct i2c_adapter *i2c) struct i2c_adapter *i2c)
{ {
int n;
struct drxk_state *state = NULL; struct drxk_state *state = NULL;
u8 adr = config->adr; u8 adr = config->adr;
int status;
dprintk(1, "\n"); dprintk(1, "\n");
state = kzalloc(sizeof(struct drxk_state), GFP_KERNEL); state = kzalloc(sizeof(struct drxk_state), GFP_KERNEL);
@ -6385,6 +6565,7 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config,
state->demod_address = adr; state->demod_address = adr;
state->single_master = config->single_master; state->single_master = config->single_master;
state->microcode_name = config->microcode_name; state->microcode_name = config->microcode_name;
state->qam_demod_parameter_count = config->qam_demod_parameter_count;
state->no_i2c_bridge = config->no_i2c_bridge; state->no_i2c_bridge = config->no_i2c_bridge;
state->antenna_gpio = config->antenna_gpio; state->antenna_gpio = config->antenna_gpio;
state->antenna_dvbt = config->antenna_dvbt; state->antenna_dvbt = config->antenna_dvbt;
@ -6425,22 +6606,21 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config,
state->frontend.demodulator_priv = state; state->frontend.demodulator_priv = state;
init_state(state); init_state(state);
if (init_drxk(state) < 0)
goto error;
/* Initialize the supported delivery systems */ /* Load firmware and initialize DRX-K */
n = 0; if (state->microcode_name) {
if (state->m_hasDVBC) { status = request_firmware_nowait(THIS_MODULE, 1,
state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_A; state->microcode_name,
state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_C; state->i2c->dev.parent,
strlcat(state->frontend.ops.info.name, " DVB-C", GFP_KERNEL,
sizeof(state->frontend.ops.info.name)); state, load_firmware_cb);
} if (status < 0) {
if (state->m_hasDVBT) { printk(KERN_ERR
state->frontend.ops.delsys[n++] = SYS_DVBT; "drxk: failed to request a firmware\n");
strlcat(state->frontend.ops.info.name, " DVB-T", return NULL;
sizeof(state->frontend.ops.info.name)); }
} } else if (init_drxk(state) < 0)
goto error;
printk(KERN_INFO "drxk: frontend initialized.\n"); printk(KERN_INFO "drxk: frontend initialized.\n");
return &state->frontend; return &state->frontend;

View File

@ -94,7 +94,15 @@ enum DRXPowerMode {
enum AGC_CTRL_MODE { DRXK_AGC_CTRL_AUTO = 0, DRXK_AGC_CTRL_USER, DRXK_AGC_CTRL_OFF }; enum AGC_CTRL_MODE { DRXK_AGC_CTRL_AUTO = 0, DRXK_AGC_CTRL_USER, DRXK_AGC_CTRL_OFF };
enum EDrxkState { DRXK_UNINITIALIZED = 0, DRXK_STOPPED, DRXK_DTV_STARTED, DRXK_ATV_STARTED, DRXK_POWERED_DOWN }; enum EDrxkState {
DRXK_UNINITIALIZED = 0,
DRXK_STOPPED,
DRXK_DTV_STARTED,
DRXK_ATV_STARTED,
DRXK_POWERED_DOWN,
DRXK_NO_DEV /* If drxk init failed */
};
enum EDrxkCoefArrayIndex { enum EDrxkCoefArrayIndex {
DRXK_COEF_IDX_MN = 0, DRXK_COEF_IDX_MN = 0,
DRXK_COEF_IDX_FM , DRXK_COEF_IDX_FM ,
@ -325,6 +333,9 @@ struct drxk_state {
enum DRXPowerMode m_currentPowerMode; enum DRXPowerMode m_currentPowerMode;
/* when true, avoids other devices to use the I2C bus */
bool drxk_i2c_exclusive_lock;
/* /*
* Configurable parameters at the driver. They stores the values found * Configurable parameters at the driver. They stores the values found
* at struct drxk_config. * at struct drxk_config.
@ -338,7 +349,11 @@ struct drxk_state {
bool antenna_dvbt; bool antenna_dvbt;
u16 antenna_gpio; u16 antenna_gpio;
/* Firmware */
const char *microcode_name; const char *microcode_name;
struct completion fw_wait_load;
const struct firmware *fw;
int qam_demod_parameter_count;
}; };
#define NEVER_LOCK 0 #define NEVER_LOCK 0

View 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 = &reg,
}, {
.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");

View 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 */

View 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 */

View File

@ -634,7 +634,6 @@ static int s5h1420_set_frontend(struct dvb_frontend *fe)
struct s5h1420_state* state = fe->demodulator_priv; struct s5h1420_state* state = fe->demodulator_priv;
int frequency_delta; int frequency_delta;
struct dvb_frontend_tune_settings fesettings; struct dvb_frontend_tune_settings fesettings;
uint8_t clock_setting;
dprintk("enter %s\n", __func__); dprintk("enter %s\n", __func__);
@ -679,25 +678,6 @@ static int s5h1420_set_frontend(struct dvb_frontend *fe)
else else
state->fclk = 44000000; state->fclk = 44000000;
/* Clock */
switch (state->fclk) {
default:
case 88000000:
clock_setting = 80;
break;
case 86000000:
clock_setting = 78;
break;
case 80000000:
clock_setting = 72;
break;
case 59000000:
clock_setting = 51;
break;
case 44000000:
clock_setting = 36;
break;
}
dprintk("pll01: %d, ToneFreq: %d\n", state->fclk/1000000 - 8, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32)); dprintk("pll01: %d, ToneFreq: %d\n", state->fclk/1000000 - 8, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32));
s5h1420_writereg(state, PLL01, state->fclk/1000000 - 8); s5h1420_writereg(state, PLL01, state->fclk/1000000 - 8);
s5h1420_writereg(state, PLL02, 0x40); s5h1420_writereg(state, PLL02, 0x40);

View File

@ -1129,7 +1129,6 @@ static int stb0899_read_ber(struct dvb_frontend *fe, u32 *ber)
struct stb0899_internal *internal = &state->internal; struct stb0899_internal *internal = &state->internal;
u8 lsb, msb; u8 lsb, msb;
u32 i;
*ber = 0; *ber = 0;
@ -1137,14 +1136,9 @@ static int stb0899_read_ber(struct dvb_frontend *fe, u32 *ber)
case SYS_DVBS: case SYS_DVBS:
case SYS_DSS: case SYS_DSS:
if (internal->lock) { if (internal->lock) {
/* average 5 BER values */ lsb = stb0899_read_reg(state, STB0899_ECNT1L);
for (i = 0; i < 5; i++) { msb = stb0899_read_reg(state, STB0899_ECNT1M);
msleep(100); *ber = MAKEWORD16(msb, lsb);
lsb = stb0899_read_reg(state, STB0899_ECNT1L);
msb = stb0899_read_reg(state, STB0899_ECNT1M);
*ber += MAKEWORD16(msb, lsb);
}
*ber /= 5;
/* Viterbi Check */ /* Viterbi Check */
if (STB0899_GETFIELD(VSTATUS_PRFVIT, internal->v_status)) { if (STB0899_GETFIELD(VSTATUS_PRFVIT, internal->v_status)) {
/* Error Rate */ /* Error Rate */
@ -1157,13 +1151,9 @@ static int stb0899_read_ber(struct dvb_frontend *fe, u32 *ber)
break; break;
case SYS_DVBS2: case SYS_DVBS2:
if (internal->lock) { if (internal->lock) {
/* Average 5 PER values */ lsb = stb0899_read_reg(state, STB0899_ECNT1L);
for (i = 0; i < 5; i++) { msb = stb0899_read_reg(state, STB0899_ECNT1M);
msleep(100); *ber = MAKEWORD16(msb, lsb);
lsb = stb0899_read_reg(state, STB0899_ECNT1L);
msb = stb0899_read_reg(state, STB0899_ECNT1M);
*ber += MAKEWORD16(msb, lsb);
}
/* ber = ber * 10 ^ 7 */ /* ber = ber * 10 ^ 7 */
*ber *= 10000000; *ber *= 10000000;
*ber /= (-1 + (1 << (4 + 2 * STB0899_GETFIELD(NOE, internal->err_ctrl)))); *ber /= (-1 + (1 << (4 + 2 * STB0899_GETFIELD(NOE, internal->err_ctrl))));

View File

@ -1584,7 +1584,7 @@ static int stv0367ter_algo(struct dvb_frontend *fe)
struct stv0367ter_state *ter_state = state->ter_state; struct stv0367ter_state *ter_state = state->ter_state;
int offset = 0, tempo = 0; int offset = 0, tempo = 0;
u8 u_var; u8 u_var;
u8 /*constell,*/ counter, tps_rcvd[2]; u8 /*constell,*/ counter;
s8 step; s8 step;
s32 timing_offset = 0; s32 timing_offset = 0;
u32 trl_nomrate = 0, InternalFreq = 0, temp = 0; u32 trl_nomrate = 0, InternalFreq = 0, temp = 0;
@ -1709,9 +1709,6 @@ static int stv0367ter_algo(struct dvb_frontend *fe)
return 0; return 0;
ter_state->state = FE_TER_LOCKOK; ter_state->state = FE_TER_LOCKOK;
/* update results */
tps_rcvd[0] = stv0367_readreg(state, R367TER_TPS_RCVD2);
tps_rcvd[1] = stv0367_readreg(state, R367TER_TPS_RCVD3);
ter_state->mode = stv0367_readbits(state, F367TER_SYR_MODE); ter_state->mode = stv0367_readbits(state, F367TER_SYR_MODE);
ter_state->guard = stv0367_readbits(state, F367TER_SYR_GUARD); ter_state->guard = stv0367_readbits(state, F367TER_SYR_GUARD);

View File

@ -3172,7 +3172,7 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state)
enum stv090x_signal_state signal_state = STV090x_NOCARRIER; enum stv090x_signal_state signal_state = STV090x_NOCARRIER;
u32 reg; u32 reg;
s32 agc1_power, power_iq = 0, i; s32 agc1_power, power_iq = 0, i;
int lock = 0, low_sr = 0, no_signal = 0; int lock = 0, low_sr = 0;
reg = STV090x_READ_DEMOD(state, TSCFGH); reg = STV090x_READ_DEMOD(state, TSCFGH);
STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 1); /* Stop path 1 stream merger */ STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 1); /* Stop path 1 stream merger */
@ -3413,7 +3413,7 @@ static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state)
goto err; goto err;
} else { } else {
signal_state = STV090x_NODATA; signal_state = STV090x_NODATA;
no_signal = stv090x_chk_signal(state); stv090x_chk_signal(state);
} }
} }
return signal_state; return signal_state;

View File

@ -20,10 +20,6 @@
#include "tda10071_priv.h" #include "tda10071_priv.h"
int tda10071_debug;
module_param_named(debug, tda10071_debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
static struct dvb_frontend_ops tda10071_ops; static struct dvb_frontend_ops tda10071_ops;
/* write multiple registers */ /* write multiple registers */
@ -48,7 +44,8 @@ static int tda10071_wr_regs(struct tda10071_priv *priv, u8 reg, u8 *val,
if (ret == 1) { if (ret == 1) {
ret = 0; ret = 0;
} else { } else {
warn("i2c wr failed=%d reg=%02x len=%d", ret, reg, len); dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \
"len=%d\n", KBUILD_MODNAME, ret, reg, len);
ret = -EREMOTEIO; ret = -EREMOTEIO;
} }
return ret; return ret;
@ -79,7 +76,8 @@ static int tda10071_rd_regs(struct tda10071_priv *priv, u8 reg, u8 *val,
memcpy(val, buf, len); memcpy(val, buf, len);
ret = 0; ret = 0;
} else { } else {
warn("i2c rd failed=%d reg=%02x len=%d", ret, reg, len); dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \
"len=%d\n", KBUILD_MODNAME, ret, reg, len);
ret = -EREMOTEIO; ret = -EREMOTEIO;
} }
return ret; return ret;
@ -170,7 +168,7 @@ static int tda10071_cmd_execute(struct tda10071_priv *priv,
usleep_range(200, 5000); usleep_range(200, 5000);
} }
dbg("%s: loop=%d", __func__, i); dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i);
if (i == 0) { if (i == 0) {
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
@ -179,7 +177,7 @@ static int tda10071_cmd_execute(struct tda10071_priv *priv,
return ret; return ret;
error: error:
dbg("%s: failed=%d", __func__, ret); dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
return ret; return ret;
} }
@ -196,7 +194,8 @@ static int tda10071_set_tone(struct dvb_frontend *fe,
goto error; goto error;
} }
dbg("%s: tone_mode=%d", __func__, fe_sec_tone_mode); dev_dbg(&priv->i2c->dev, "%s: tone_mode=%d\n", __func__,
fe_sec_tone_mode);
switch (fe_sec_tone_mode) { switch (fe_sec_tone_mode) {
case SEC_TONE_ON: case SEC_TONE_ON:
@ -206,24 +205,25 @@ static int tda10071_set_tone(struct dvb_frontend *fe,
tone = 0; tone = 0;
break; break;
default: default:
dbg("%s: invalid fe_sec_tone_mode", __func__); dev_dbg(&priv->i2c->dev, "%s: invalid fe_sec_tone_mode\n",
__func__);
ret = -EINVAL; ret = -EINVAL;
goto error; goto error;
} }
cmd.args[0x00] = CMD_LNB_PCB_CONFIG; cmd.args[0] = CMD_LNB_PCB_CONFIG;
cmd.args[0x01] = 0; cmd.args[1] = 0;
cmd.args[0x02] = 0x00; cmd.args[2] = 0x00;
cmd.args[0x03] = 0x00; cmd.args[3] = 0x00;
cmd.args[0x04] = tone; cmd.args[4] = tone;
cmd.len = 0x05; cmd.len = 5;
ret = tda10071_cmd_execute(priv, &cmd); ret = tda10071_cmd_execute(priv, &cmd);
if (ret) if (ret)
goto error; goto error;
return ret; return ret;
error: error:
dbg("%s: failed=%d", __func__, ret); dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
return ret; return ret;
} }
@ -240,7 +240,7 @@ static int tda10071_set_voltage(struct dvb_frontend *fe,
goto error; goto error;
} }
dbg("%s: voltage=%d", __func__, fe_sec_voltage); dev_dbg(&priv->i2c->dev, "%s: voltage=%d\n", __func__, fe_sec_voltage);
switch (fe_sec_voltage) { switch (fe_sec_voltage) {
case SEC_VOLTAGE_13: case SEC_VOLTAGE_13:
@ -253,22 +253,23 @@ static int tda10071_set_voltage(struct dvb_frontend *fe,
voltage = 0; voltage = 0;
break; break;
default: default:
dbg("%s: invalid fe_sec_voltage", __func__); dev_dbg(&priv->i2c->dev, "%s: invalid fe_sec_voltage\n",
__func__);
ret = -EINVAL; ret = -EINVAL;
goto error; goto error;
}; };
cmd.args[0x00] = CMD_LNB_SET_DC_LEVEL; cmd.args[0] = CMD_LNB_SET_DC_LEVEL;
cmd.args[0x01] = 0; cmd.args[1] = 0;
cmd.args[0x02] = voltage; cmd.args[2] = voltage;
cmd.len = 0x03; cmd.len = 3;
ret = tda10071_cmd_execute(priv, &cmd); ret = tda10071_cmd_execute(priv, &cmd);
if (ret) if (ret)
goto error; goto error;
return ret; return ret;
error: error:
dbg("%s: failed=%d", __func__, ret); dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
return ret; return ret;
} }
@ -285,9 +286,10 @@ static int tda10071_diseqc_send_master_cmd(struct dvb_frontend *fe,
goto error; goto error;
} }
dbg("%s: msg_len=%d", __func__, diseqc_cmd->msg_len); dev_dbg(&priv->i2c->dev, "%s: msg_len=%d\n", __func__,
diseqc_cmd->msg_len);
if (diseqc_cmd->msg_len < 3 || diseqc_cmd->msg_len > 16) { if (diseqc_cmd->msg_len < 3 || diseqc_cmd->msg_len > 6) {
ret = -EINVAL; ret = -EINVAL;
goto error; goto error;
} }
@ -301,7 +303,7 @@ static int tda10071_diseqc_send_master_cmd(struct dvb_frontend *fe,
usleep_range(10000, 20000); usleep_range(10000, 20000);
} }
dbg("%s: loop=%d", __func__, i); dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i);
if (i == 0) { if (i == 0) {
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
@ -312,22 +314,22 @@ static int tda10071_diseqc_send_master_cmd(struct dvb_frontend *fe,
if (ret) if (ret)
goto error; goto error;
cmd.args[0x00] = CMD_LNB_SEND_DISEQC; cmd.args[0] = CMD_LNB_SEND_DISEQC;
cmd.args[0x01] = 0; cmd.args[1] = 0;
cmd.args[0x02] = 0; cmd.args[2] = 0;
cmd.args[0x03] = 0; cmd.args[3] = 0;
cmd.args[0x04] = 2; cmd.args[4] = 2;
cmd.args[0x05] = 0; cmd.args[5] = 0;
cmd.args[0x06] = diseqc_cmd->msg_len; cmd.args[6] = diseqc_cmd->msg_len;
memcpy(&cmd.args[0x07], diseqc_cmd->msg, diseqc_cmd->msg_len); memcpy(&cmd.args[7], diseqc_cmd->msg, diseqc_cmd->msg_len);
cmd.len = 0x07 + diseqc_cmd->msg_len; cmd.len = 7 + diseqc_cmd->msg_len;
ret = tda10071_cmd_execute(priv, &cmd); ret = tda10071_cmd_execute(priv, &cmd);
if (ret) if (ret)
goto error; goto error;
return ret; return ret;
error: error:
dbg("%s: failed=%d", __func__, ret); dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
return ret; return ret;
} }
@ -344,7 +346,7 @@ static int tda10071_diseqc_recv_slave_reply(struct dvb_frontend *fe,
goto error; goto error;
} }
dbg("%s:", __func__); dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
/* wait LNB RX */ /* wait LNB RX */
for (i = 500, tmp = 0; i && !tmp; i--) { for (i = 500, tmp = 0; i && !tmp; i--) {
@ -355,7 +357,7 @@ static int tda10071_diseqc_recv_slave_reply(struct dvb_frontend *fe,
usleep_range(10000, 20000); usleep_range(10000, 20000);
} }
dbg("%s: loop=%d", __func__, i); dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i);
if (i == 0) { if (i == 0) {
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
@ -372,9 +374,9 @@ static int tda10071_diseqc_recv_slave_reply(struct dvb_frontend *fe,
reply->msg_len = sizeof(reply->msg); /* truncate API max */ reply->msg_len = sizeof(reply->msg); /* truncate API max */
/* read reply */ /* read reply */
cmd.args[0x00] = CMD_LNB_UPDATE_REPLY; cmd.args[0] = CMD_LNB_UPDATE_REPLY;
cmd.args[0x01] = 0; cmd.args[1] = 0;
cmd.len = 0x02; cmd.len = 2;
ret = tda10071_cmd_execute(priv, &cmd); ret = tda10071_cmd_execute(priv, &cmd);
if (ret) if (ret)
goto error; goto error;
@ -385,7 +387,7 @@ static int tda10071_diseqc_recv_slave_reply(struct dvb_frontend *fe,
return ret; return ret;
error: error:
dbg("%s: failed=%d", __func__, ret); dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
return ret; return ret;
} }
@ -402,7 +404,8 @@ static int tda10071_diseqc_send_burst(struct dvb_frontend *fe,
goto error; goto error;
} }
dbg("%s: fe_sec_mini_cmd=%d", __func__, fe_sec_mini_cmd); dev_dbg(&priv->i2c->dev, "%s: fe_sec_mini_cmd=%d\n", __func__,
fe_sec_mini_cmd);
switch (fe_sec_mini_cmd) { switch (fe_sec_mini_cmd) {
case SEC_MINI_A: case SEC_MINI_A:
@ -412,7 +415,8 @@ static int tda10071_diseqc_send_burst(struct dvb_frontend *fe,
burst = 1; burst = 1;
break; break;
default: default:
dbg("%s: invalid fe_sec_mini_cmd", __func__); dev_dbg(&priv->i2c->dev, "%s: invalid fe_sec_mini_cmd\n",
__func__);
ret = -EINVAL; ret = -EINVAL;
goto error; goto error;
} }
@ -426,7 +430,7 @@ static int tda10071_diseqc_send_burst(struct dvb_frontend *fe,
usleep_range(10000, 20000); usleep_range(10000, 20000);
} }
dbg("%s: loop=%d", __func__, i); dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i);
if (i == 0) { if (i == 0) {
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
@ -437,17 +441,17 @@ static int tda10071_diseqc_send_burst(struct dvb_frontend *fe,
if (ret) if (ret)
goto error; goto error;
cmd.args[0x00] = CMD_LNB_SEND_TONEBURST; cmd.args[0] = CMD_LNB_SEND_TONEBURST;
cmd.args[0x01] = 0; cmd.args[1] = 0;
cmd.args[0x02] = burst; cmd.args[2] = burst;
cmd.len = 0x03; cmd.len = 3;
ret = tda10071_cmd_execute(priv, &cmd); ret = tda10071_cmd_execute(priv, &cmd);
if (ret) if (ret)
goto error; goto error;
return ret; return ret;
error: error:
dbg("%s: failed=%d", __func__, ret); dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
return ret; return ret;
} }
@ -481,7 +485,7 @@ static int tda10071_read_status(struct dvb_frontend *fe, fe_status_t *status)
return ret; return ret;
error: error:
dbg("%s: failed=%d", __func__, ret); dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
return ret; return ret;
} }
@ -506,7 +510,7 @@ static int tda10071_read_snr(struct dvb_frontend *fe, u16 *snr)
return ret; return ret;
error: error:
dbg("%s: failed=%d", __func__, ret); dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
return ret; return ret;
} }
@ -523,9 +527,9 @@ static int tda10071_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
goto error; goto error;
} }
cmd.args[0x00] = CMD_GET_AGCACC; cmd.args[0] = CMD_GET_AGCACC;
cmd.args[0x01] = 0; cmd.args[1] = 0;
cmd.len = 0x02; cmd.len = 2;
ret = tda10071_cmd_execute(priv, &cmd); ret = tda10071_cmd_execute(priv, &cmd);
if (ret) if (ret)
goto error; goto error;
@ -545,7 +549,7 @@ static int tda10071_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
return ret; return ret;
error: error:
dbg("%s: failed=%d", __func__, ret); dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
return ret; return ret;
} }
@ -583,17 +587,18 @@ static int tda10071_read_ber(struct dvb_frontend *fe, u32 *ber)
goto error; goto error;
if (priv->meas_count[i] == tmp) { if (priv->meas_count[i] == tmp) {
dbg("%s: meas not ready=%02x", __func__, tmp); dev_dbg(&priv->i2c->dev, "%s: meas not ready=%02x\n", __func__,
tmp);
*ber = priv->ber; *ber = priv->ber;
return 0; return 0;
} else { } else {
priv->meas_count[i] = tmp; priv->meas_count[i] = tmp;
} }
cmd.args[0x00] = CMD_BER_UPDATE_COUNTERS; cmd.args[0] = CMD_BER_UPDATE_COUNTERS;
cmd.args[0x01] = 0; cmd.args[1] = 0;
cmd.args[0x02] = i; cmd.args[2] = i;
cmd.len = 0x03; cmd.len = 3;
ret = tda10071_cmd_execute(priv, &cmd); ret = tda10071_cmd_execute(priv, &cmd);
if (ret) if (ret)
goto error; goto error;
@ -612,7 +617,7 @@ static int tda10071_read_ber(struct dvb_frontend *fe, u32 *ber)
return ret; return ret;
error: error:
dbg("%s: failed=%d", __func__, ret); dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
return ret; return ret;
} }
@ -632,7 +637,7 @@ static int tda10071_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
return ret; return ret;
error: error:
dbg("%s: failed=%d", __func__, ret); dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
return ret; return ret;
} }
@ -644,10 +649,11 @@ static int tda10071_set_frontend(struct dvb_frontend *fe)
int ret, i; int ret, i;
u8 mode, rolloff, pilot, inversion, div; u8 mode, rolloff, pilot, inversion, div;
dbg("%s: delivery_system=%d modulation=%d frequency=%d " \ dev_dbg(&priv->i2c->dev, "%s: delivery_system=%d modulation=%d " \
"symbol_rate=%d inversion=%d pilot=%d rolloff=%d", __func__, "frequency=%d symbol_rate=%d inversion=%d pilot=%d " \
c->delivery_system, c->modulation, c->frequency, "rolloff=%d\n", __func__, c->delivery_system, c->modulation,
c->symbol_rate, c->inversion, c->pilot, c->rolloff); c->frequency, c->symbol_rate, c->inversion, c->pilot,
c->rolloff);
priv->delivery_system = SYS_UNDEFINED; priv->delivery_system = SYS_UNDEFINED;
@ -669,7 +675,7 @@ static int tda10071_set_frontend(struct dvb_frontend *fe)
inversion = 3; inversion = 3;
break; break;
default: default:
dbg("%s: invalid inversion", __func__); dev_dbg(&priv->i2c->dev, "%s: invalid inversion\n", __func__);
ret = -EINVAL; ret = -EINVAL;
goto error; goto error;
} }
@ -692,7 +698,8 @@ static int tda10071_set_frontend(struct dvb_frontend *fe)
break; break;
case ROLLOFF_AUTO: case ROLLOFF_AUTO:
default: default:
dbg("%s: invalid rolloff", __func__); dev_dbg(&priv->i2c->dev, "%s: invalid rolloff\n",
__func__);
ret = -EINVAL; ret = -EINVAL;
goto error; goto error;
} }
@ -708,13 +715,15 @@ static int tda10071_set_frontend(struct dvb_frontend *fe)
pilot = 2; pilot = 2;
break; break;
default: default:
dbg("%s: invalid pilot", __func__); dev_dbg(&priv->i2c->dev, "%s: invalid pilot\n",
__func__);
ret = -EINVAL; ret = -EINVAL;
goto error; goto error;
} }
break; break;
default: default:
dbg("%s: invalid delivery_system", __func__); dev_dbg(&priv->i2c->dev, "%s: invalid delivery_system\n",
__func__);
ret = -EINVAL; ret = -EINVAL;
goto error; goto error;
} }
@ -724,13 +733,15 @@ static int tda10071_set_frontend(struct dvb_frontend *fe)
c->modulation == TDA10071_MODCOD[i].modulation && c->modulation == TDA10071_MODCOD[i].modulation &&
c->fec_inner == TDA10071_MODCOD[i].fec) { c->fec_inner == TDA10071_MODCOD[i].fec) {
mode = TDA10071_MODCOD[i].val; mode = TDA10071_MODCOD[i].val;
dbg("%s: mode found=%02x", __func__, mode); dev_dbg(&priv->i2c->dev, "%s: mode found=%02x\n",
__func__, mode);
break; break;
} }
} }
if (mode == 0xff) { if (mode == 0xff) {
dbg("%s: invalid parameter combination", __func__); dev_dbg(&priv->i2c->dev, "%s: invalid parameter combination\n",
__func__);
ret = -EINVAL; ret = -EINVAL;
goto error; goto error;
} }
@ -748,22 +759,22 @@ static int tda10071_set_frontend(struct dvb_frontend *fe)
if (ret) if (ret)
goto error; goto error;
cmd.args[0x00] = CMD_CHANGE_CHANNEL; cmd.args[0] = CMD_CHANGE_CHANNEL;
cmd.args[0x01] = 0; cmd.args[1] = 0;
cmd.args[0x02] = mode; cmd.args[2] = mode;
cmd.args[0x03] = (c->frequency >> 16) & 0xff; cmd.args[3] = (c->frequency >> 16) & 0xff;
cmd.args[0x04] = (c->frequency >> 8) & 0xff; cmd.args[4] = (c->frequency >> 8) & 0xff;
cmd.args[0x05] = (c->frequency >> 0) & 0xff; cmd.args[5] = (c->frequency >> 0) & 0xff;
cmd.args[0x06] = ((c->symbol_rate / 1000) >> 8) & 0xff; cmd.args[6] = ((c->symbol_rate / 1000) >> 8) & 0xff;
cmd.args[0x07] = ((c->symbol_rate / 1000) >> 0) & 0xff; cmd.args[7] = ((c->symbol_rate / 1000) >> 0) & 0xff;
cmd.args[0x08] = (tda10071_ops.info.frequency_tolerance >> 8) & 0xff; cmd.args[8] = (tda10071_ops.info.frequency_tolerance >> 8) & 0xff;
cmd.args[0x09] = (tda10071_ops.info.frequency_tolerance >> 0) & 0xff; cmd.args[9] = (tda10071_ops.info.frequency_tolerance >> 0) & 0xff;
cmd.args[0x0a] = rolloff; cmd.args[10] = rolloff;
cmd.args[0x0b] = inversion; cmd.args[11] = inversion;
cmd.args[0x0c] = pilot; cmd.args[12] = pilot;
cmd.args[0x0d] = 0x00; cmd.args[13] = 0x00;
cmd.args[0x0e] = 0x00; cmd.args[14] = 0x00;
cmd.len = 0x0f; cmd.len = 15;
ret = tda10071_cmd_execute(priv, &cmd); ret = tda10071_cmd_execute(priv, &cmd);
if (ret) if (ret)
goto error; goto error;
@ -772,7 +783,7 @@ static int tda10071_set_frontend(struct dvb_frontend *fe)
return ret; return ret;
error: error:
dbg("%s: failed=%d", __func__, ret); dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
return ret; return ret;
} }
@ -829,7 +840,7 @@ static int tda10071_get_frontend(struct dvb_frontend *fe)
return ret; return ret;
error: error:
dbg("%s: failed=%d", __func__, ret); dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
return ret; return ret;
} }
@ -915,10 +926,10 @@ static int tda10071_init(struct dvb_frontend *fe)
goto error; goto error;
} }
cmd.args[0x00] = CMD_SET_SLEEP_MODE; cmd.args[0] = CMD_SET_SLEEP_MODE;
cmd.args[0x01] = 0; cmd.args[1] = 0;
cmd.args[0x02] = 0; cmd.args[2] = 0;
cmd.len = 0x03; cmd.len = 3;
ret = tda10071_cmd_execute(priv, &cmd); ret = tda10071_cmd_execute(priv, &cmd);
if (ret) if (ret)
goto error; goto error;
@ -929,10 +940,11 @@ static int tda10071_init(struct dvb_frontend *fe)
/* request the firmware, this will block and timeout */ /* request the firmware, this will block and timeout */
ret = request_firmware(&fw, fw_file, priv->i2c->dev.parent); ret = request_firmware(&fw, fw_file, priv->i2c->dev.parent);
if (ret) { if (ret) {
err("did not find the firmware file. (%s) " dev_err(&priv->i2c->dev, "%s: did not find the " \
"Please see linux/Documentation/dvb/ for more" \ "firmware file. (%s) Please see " \
" details on firmware-problems. (%d)", "linux/Documentation/dvb/ for more " \
fw_file, ret); "details on firmware-problems. (%d)\n",
KBUILD_MODNAME, fw_file, ret);
goto error; goto error;
} }
@ -961,10 +973,11 @@ static int tda10071_init(struct dvb_frontend *fe)
if (ret) if (ret)
goto error_release_firmware; goto error_release_firmware;
info("found a '%s' in cold state, will try to load a firmware", dev_info(&priv->i2c->dev, "%s: found a '%s' in cold state, " \
tda10071_ops.info.name); "will try to load a firmware\n", KBUILD_MODNAME,
tda10071_ops.info.name);
info("downloading firmware from file '%s'", fw_file); dev_info(&priv->i2c->dev, "%s: downloading firmware from " \
"file '%s'\n", KBUILD_MODNAME, fw_file);
/* do not download last byte */ /* do not download last byte */
fw_size = fw->size - 1; fw_size = fw->size - 1;
@ -978,7 +991,9 @@ static int tda10071_init(struct dvb_frontend *fe)
ret = tda10071_wr_regs(priv, 0xfa, ret = tda10071_wr_regs(priv, 0xfa,
(u8 *) &fw->data[fw_size - remaining], len); (u8 *) &fw->data[fw_size - remaining], len);
if (ret) { if (ret) {
err("firmware download failed=%d", ret); dev_err(&priv->i2c->dev, "%s: firmware " \
"download failed=%d\n",
KBUILD_MODNAME, ret);
if (ret) if (ret)
goto error_release_firmware; goto error_release_firmware;
} }
@ -1002,15 +1017,16 @@ static int tda10071_init(struct dvb_frontend *fe)
goto error; goto error;
if (tmp) { if (tmp) {
info("firmware did not run"); dev_info(&priv->i2c->dev, "%s: firmware did not run\n",
KBUILD_MODNAME);
ret = -EFAULT; ret = -EFAULT;
goto error; goto error;
} else { } else {
priv->warm = 1; priv->warm = 1;
} }
cmd.args[0x00] = CMD_GET_FW_VERSION; cmd.args[0] = CMD_GET_FW_VERSION;
cmd.len = 0x01; cmd.len = 1;
ret = tda10071_cmd_execute(priv, &cmd); ret = tda10071_cmd_execute(priv, &cmd);
if (ret) if (ret)
goto error; goto error;
@ -1019,54 +1035,55 @@ static int tda10071_init(struct dvb_frontend *fe)
if (ret) if (ret)
goto error; goto error;
info("firmware version %d.%d.%d.%d", dev_info(&priv->i2c->dev, "%s: firmware version %d.%d.%d.%d\n",
buf[0], buf[1], buf[2], buf[3]); KBUILD_MODNAME, buf[0], buf[1], buf[2], buf[3]);
info("found a '%s' in warm state.", tda10071_ops.info.name); dev_info(&priv->i2c->dev, "%s: found a '%s' in warm state\n",
KBUILD_MODNAME, tda10071_ops.info.name);
ret = tda10071_rd_regs(priv, 0x81, buf, 2); ret = tda10071_rd_regs(priv, 0x81, buf, 2);
if (ret) if (ret)
goto error; goto error;
cmd.args[0x00] = CMD_DEMOD_INIT; cmd.args[0] = CMD_DEMOD_INIT;
cmd.args[0x01] = ((priv->cfg.xtal / 1000) >> 8) & 0xff; cmd.args[1] = ((priv->cfg.xtal / 1000) >> 8) & 0xff;
cmd.args[0x02] = ((priv->cfg.xtal / 1000) >> 0) & 0xff; cmd.args[2] = ((priv->cfg.xtal / 1000) >> 0) & 0xff;
cmd.args[0x03] = buf[0]; cmd.args[3] = buf[0];
cmd.args[0x04] = buf[1]; cmd.args[4] = buf[1];
cmd.args[0x05] = priv->cfg.pll_multiplier; cmd.args[5] = priv->cfg.pll_multiplier;
cmd.args[0x06] = priv->cfg.spec_inv; cmd.args[6] = priv->cfg.spec_inv;
cmd.args[0x07] = 0x00; cmd.args[7] = 0x00;
cmd.len = 0x08; cmd.len = 8;
ret = tda10071_cmd_execute(priv, &cmd); ret = tda10071_cmd_execute(priv, &cmd);
if (ret) if (ret)
goto error; goto error;
cmd.args[0x00] = CMD_TUNER_INIT; cmd.args[0] = CMD_TUNER_INIT;
cmd.args[0x01] = 0x00; cmd.args[1] = 0x00;
cmd.args[0x02] = 0x00; cmd.args[2] = 0x00;
cmd.args[0x03] = 0x00; cmd.args[3] = 0x00;
cmd.args[0x04] = 0x00; cmd.args[4] = 0x00;
cmd.args[0x05] = 0x14; cmd.args[5] = 0x14;
cmd.args[0x06] = 0x00; cmd.args[6] = 0x00;
cmd.args[0x07] = 0x03; cmd.args[7] = 0x03;
cmd.args[0x08] = 0x02; cmd.args[8] = 0x02;
cmd.args[0x09] = 0x02; cmd.args[9] = 0x02;
cmd.args[0x0a] = 0x00; cmd.args[10] = 0x00;
cmd.args[0x0b] = 0x00; cmd.args[11] = 0x00;
cmd.args[0x0c] = 0x00; cmd.args[12] = 0x00;
cmd.args[0x0d] = 0x00; cmd.args[13] = 0x00;
cmd.args[0x0e] = 0x00; cmd.args[14] = 0x00;
cmd.len = 0x0f; cmd.len = 15;
ret = tda10071_cmd_execute(priv, &cmd); ret = tda10071_cmd_execute(priv, &cmd);
if (ret) if (ret)
goto error; goto error;
cmd.args[0x00] = CMD_MPEG_CONFIG; cmd.args[0] = CMD_MPEG_CONFIG;
cmd.args[0x01] = 0; cmd.args[1] = 0;
cmd.args[0x02] = priv->cfg.ts_mode; cmd.args[2] = priv->cfg.ts_mode;
cmd.args[0x03] = 0x00; cmd.args[3] = 0x00;
cmd.args[0x04] = 0x04; cmd.args[4] = 0x04;
cmd.args[0x05] = 0x00; cmd.args[5] = 0x00;
cmd.len = 0x06; cmd.len = 6;
ret = tda10071_cmd_execute(priv, &cmd); ret = tda10071_cmd_execute(priv, &cmd);
if (ret) if (ret)
goto error; goto error;
@ -1075,27 +1092,27 @@ static int tda10071_init(struct dvb_frontend *fe)
if (ret) if (ret)
goto error; goto error;
cmd.args[0x00] = CMD_LNB_CONFIG; cmd.args[0] = CMD_LNB_CONFIG;
cmd.args[0x01] = 0; cmd.args[1] = 0;
cmd.args[0x02] = 150; cmd.args[2] = 150;
cmd.args[0x03] = 3; cmd.args[3] = 3;
cmd.args[0x04] = 22; cmd.args[4] = 22;
cmd.args[0x05] = 1; cmd.args[5] = 1;
cmd.args[0x06] = 1; cmd.args[6] = 1;
cmd.args[0x07] = 30; cmd.args[7] = 30;
cmd.args[0x08] = 30; cmd.args[8] = 30;
cmd.args[0x09] = 30; cmd.args[9] = 30;
cmd.args[0x0a] = 30; cmd.args[10] = 30;
cmd.len = 0x0b; cmd.len = 11;
ret = tda10071_cmd_execute(priv, &cmd); ret = tda10071_cmd_execute(priv, &cmd);
if (ret) if (ret)
goto error; goto error;
cmd.args[0x00] = CMD_BER_CONTROL; cmd.args[0] = CMD_BER_CONTROL;
cmd.args[0x01] = 0; cmd.args[1] = 0;
cmd.args[0x02] = 14; cmd.args[2] = 14;
cmd.args[0x03] = 14; cmd.args[3] = 14;
cmd.len = 0x04; cmd.len = 4;
ret = tda10071_cmd_execute(priv, &cmd); ret = tda10071_cmd_execute(priv, &cmd);
if (ret) if (ret)
goto error; goto error;
@ -1105,7 +1122,7 @@ static int tda10071_init(struct dvb_frontend *fe)
error_release_firmware: error_release_firmware:
release_firmware(fw); release_firmware(fw);
error: error:
dbg("%s: failed=%d", __func__, ret); dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
return ret; return ret;
} }
@ -1132,10 +1149,10 @@ static int tda10071_sleep(struct dvb_frontend *fe)
goto error; goto error;
} }
cmd.args[0x00] = CMD_SET_SLEEP_MODE; cmd.args[0] = CMD_SET_SLEEP_MODE;
cmd.args[0x01] = 0; cmd.args[1] = 0;
cmd.args[0x02] = 1; cmd.args[2] = 1;
cmd.len = 0x03; cmd.len = 3;
ret = tda10071_cmd_execute(priv, &cmd); ret = tda10071_cmd_execute(priv, &cmd);
if (ret) if (ret)
goto error; goto error;
@ -1149,7 +1166,7 @@ static int tda10071_sleep(struct dvb_frontend *fe)
return ret; return ret;
error: error:
dbg("%s: failed=%d", __func__, ret); dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
return ret; return ret;
} }
@ -1208,7 +1225,7 @@ struct dvb_frontend *tda10071_attach(const struct tda10071_config *config,
return &priv->fe; return &priv->fe;
error: error:
dbg("%s: failed=%d", __func__, ret); dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret);
kfree(priv); kfree(priv);
return NULL; return NULL;
} }

View File

@ -25,19 +25,6 @@
#include "tda10071.h" #include "tda10071.h"
#include <linux/firmware.h> #include <linux/firmware.h>
#define LOG_PREFIX "tda10071"
#undef dbg
#define dbg(f, arg...) \
if (tda10071_debug) \
printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg)
#undef err
#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg)
#undef info
#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg)
#undef warn
#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
struct tda10071_priv { struct tda10071_priv {
struct i2c_adapter *i2c; struct i2c_adapter *i2c;
struct dvb_frontend fe; struct dvb_frontend fe;
@ -112,7 +99,7 @@ struct tda10071_reg_val_mask {
#define CMD_BER_UPDATE_COUNTERS 0x3f #define CMD_BER_UPDATE_COUNTERS 0x3f
/* firmare command struct */ /* firmare command struct */
#define TDA10071_ARGLEN 0x1e #define TDA10071_ARGLEN 30
struct tda10071_cmd { struct tda10071_cmd {
u8 args[TDA10071_ARGLEN]; u8 args[TDA10071_ARGLEN];
u8 len; u8 len;

View File

@ -217,6 +217,7 @@ static int demod_attach_drxk(struct ngene_channel *chan,
memset(&config, 0, sizeof(config)); memset(&config, 0, sizeof(config));
config.microcode_name = "drxk_a3.mc"; config.microcode_name = "drxk_a3.mc";
config.qam_demod_parameter_count = 4;
config.adr = 0x29 + (chan->number ^ 2); config.adr = 0x29 + (chan->number ^ 2);
chan->fe = dvb_attach(drxk_attach, &config, i2c); chan->fe = dvb_attach(drxk_attach, &config, i2c);

View File

@ -5,6 +5,7 @@
menuconfig RADIO_ADAPTERS menuconfig RADIO_ADAPTERS
bool "Radio Adapters" bool "Radio Adapters"
depends on VIDEO_V4L2 depends on VIDEO_V4L2
depends on MEDIA_RADIO_SUPPORT
default y default y
---help--- ---help---
Say Y here to enable selecting AM/FM radio adapters. Say Y here to enable selecting AM/FM radio adapters.

View 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 */

View File

@ -37,6 +37,7 @@
#include <media/v4l2-ioctl.h> #include <media/v4l2-ioctl.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include "radio-isa.h" #include "radio-isa.h"
#include "lm7000.h"
MODULE_AUTHOR("M. Kirkwood"); MODULE_AUTHOR("M. Kirkwood");
MODULE_DESCRIPTION("A driver for the RadioTrack/RadioReveal radio card."); MODULE_DESCRIPTION("A driver for the RadioTrack/RadioReveal radio card.");
@ -72,55 +73,38 @@ static struct radio_isa_card *rtrack_alloc(void)
return rt ? &rt->isa : NULL; return rt ? &rt->isa : NULL;
} }
/* The 128+64 on these outb's is to keep the volume stable while tuning. #define AIMS_BIT_TUN_CE (1 << 0)
* Without them, the volume _will_ creep up with each frequency change #define AIMS_BIT_TUN_CLK (1 << 1)
* and bit 4 (+16) is to keep the signal strength meter enabled. #define AIMS_BIT_TUN_DATA (1 << 2)
*/ #define AIMS_BIT_VOL_CE (1 << 3)
#define AIMS_BIT_TUN_STRQ (1 << 4)
/* bit 5 is not connected */
#define AIMS_BIT_VOL_UP (1 << 6) /* active low */
#define AIMS_BIT_VOL_DN (1 << 7) /* active low */
static void send_0_byte(struct radio_isa_card *isa, int on) void rtrack_set_pins(void *handle, u8 pins)
{ {
outb_p(128+64+16+on+1, isa->io); /* wr-enable + data low */ struct radio_isa_card *isa = handle;
outb_p(128+64+16+on+2+1, isa->io); /* clock */ struct rtrack *rt = container_of(isa, struct rtrack, isa);
msleep(1); u8 bits = AIMS_BIT_VOL_DN | AIMS_BIT_VOL_UP | AIMS_BIT_TUN_STRQ;
}
static void send_1_byte(struct radio_isa_card *isa, int on) if (!v4l2_ctrl_g_ctrl(rt->isa.mute))
{ bits |= AIMS_BIT_VOL_CE;
outb_p(128+64+16+on+4+1, isa->io); /* wr-enable+data high */
outb_p(128+64+16+on+4+2+1, isa->io); /* clock */ if (pins & LM7000_DATA)
msleep(1); bits |= AIMS_BIT_TUN_DATA;
if (pins & LM7000_CLK)
bits |= AIMS_BIT_TUN_CLK;
if (pins & LM7000_CE)
bits |= AIMS_BIT_TUN_CE;
outb_p(bits, rt->isa.io);
} }
static int rtrack_s_frequency(struct radio_isa_card *isa, u32 freq) static int rtrack_s_frequency(struct radio_isa_card *isa, u32 freq)
{ {
int on = v4l2_ctrl_g_ctrl(isa->mute) ? 0 : 8; lm7000_set_freq(freq, isa, rtrack_set_pins);
int i;
freq += 171200; /* Add 10.7 MHz IF */
freq /= 800; /* Convert to 50 kHz units */
send_0_byte(isa, on); /* 0: LSB of frequency */
for (i = 0; i < 13; i++) /* : frequency bits (1-13) */
if (freq & (1 << i))
send_1_byte(isa, on);
else
send_0_byte(isa, on);
send_0_byte(isa, on); /* 14: test bit - always 0 */
send_0_byte(isa, on); /* 15: test bit - always 0 */
send_0_byte(isa, on); /* 16: band data 0 - always 0 */
send_0_byte(isa, on); /* 17: band data 1 - always 0 */
send_0_byte(isa, on); /* 18: band data 2 - always 0 */
send_0_byte(isa, on); /* 19: time base - always 0 */
send_0_byte(isa, on); /* 20: spacing (0 = 25 kHz) */
send_1_byte(isa, on); /* 21: spacing (1 = 25 kHz) */
send_0_byte(isa, on); /* 22: spacing (0 = 25 kHz) */
send_1_byte(isa, on); /* 23: AM/FM (FM = 1, always) */
outb(0xd0 + on, isa->io); /* volume steady + sigstr */
return 0; return 0;
} }

View File

@ -295,7 +295,8 @@ static int vidioc_g_tuner(struct file *file, void *priv,
v->type = V4L2_TUNER_RADIO; v->type = V4L2_TUNER_RADIO;
v->rangelow = FREQ_MIN * FREQ_MUL; v->rangelow = FREQ_MIN * FREQ_MUL;
v->rangehigh = FREQ_MAX * FREQ_MUL; v->rangehigh = FREQ_MAX * FREQ_MUL;
v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO; v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
V4L2_TUNER_CAP_HWSEEK_WRAP;
v->rxsubchans = is_stereo ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO; v->rxsubchans = is_stereo ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO;
v->audmode = radio->stereo ? v->audmode = radio->stereo ?
V4L2_TUNER_MODE_STEREO : V4L2_TUNER_MODE_MONO; V4L2_TUNER_MODE_STEREO : V4L2_TUNER_MODE_MONO;
@ -372,7 +373,7 @@ static int vidioc_s_hw_freq_seek(struct file *file, void *priv,
timeout = jiffies + msecs_to_jiffies(30000); timeout = jiffies + msecs_to_jiffies(30000);
for (;;) { for (;;) {
if (time_after(jiffies, timeout)) { if (time_after(jiffies, timeout)) {
retval = -EAGAIN; retval = -ENODATA;
break; break;
} }
if (schedule_timeout_interruptible(msecs_to_jiffies(10))) { if (schedule_timeout_interruptible(msecs_to_jiffies(10))) {

View File

@ -27,6 +27,7 @@
#include <linux/io.h> /* outb, outb_p */ #include <linux/io.h> /* outb, outb_p */
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h> #include <media/v4l2-ioctl.h>
#include "lm7000.h"
MODULE_AUTHOR("Petr Vandrovec, vandrove@vc.cvut.cz and M. Kirkwood"); MODULE_AUTHOR("Petr Vandrovec, vandrove@vc.cvut.cz and M. Kirkwood");
MODULE_DESCRIPTION("A driver for the SF16-FMI, SF16-FMP and SF16-FMD radio."); MODULE_DESCRIPTION("A driver for the SF16-FMI, SF16-FMP and SF16-FMD radio.");
@ -54,31 +55,33 @@ static struct fmi fmi_card;
static struct pnp_dev *dev; static struct pnp_dev *dev;
bool pnp_attached; bool pnp_attached;
/* freq is in 1/16 kHz to internal number, hw precision is 50 kHz */
/* It is only useful to give freq in interval of 800 (=0.05Mhz),
* other bits will be truncated, e.g 92.7400016 -> 92.7, but
* 92.7400017 -> 92.75
*/
#define RSF16_ENCODE(x) ((x) / 800 + 214)
#define RSF16_MINFREQ (87 * 16000) #define RSF16_MINFREQ (87 * 16000)
#define RSF16_MAXFREQ (108 * 16000) #define RSF16_MAXFREQ (108 * 16000)
static void outbits(int bits, unsigned int data, int io) #define FMI_BIT_TUN_CE (1 << 0)
#define FMI_BIT_TUN_CLK (1 << 1)
#define FMI_BIT_TUN_DATA (1 << 2)
#define FMI_BIT_VOL_SW (1 << 3)
#define FMI_BIT_TUN_STRQ (1 << 4)
void fmi_set_pins(void *handle, u8 pins)
{ {
while (bits--) { struct fmi *fmi = handle;
if (data & 1) { u8 bits = FMI_BIT_TUN_STRQ;
outb(5, io);
udelay(6); if (!fmi->mute)
outb(7, io); bits |= FMI_BIT_VOL_SW;
udelay(6);
} else { if (pins & LM7000_DATA)
outb(1, io); bits |= FMI_BIT_TUN_DATA;
udelay(6); if (pins & LM7000_CLK)
outb(3, io); bits |= FMI_BIT_TUN_CLK;
udelay(6); if (pins & LM7000_CE)
} bits |= FMI_BIT_TUN_CE;
data >>= 1;
} mutex_lock(&fmi->lock);
outb_p(bits, fmi->io);
mutex_unlock(&fmi->lock);
} }
static inline void fmi_mute(struct fmi *fmi) static inline void fmi_mute(struct fmi *fmi)
@ -95,20 +98,6 @@ static inline void fmi_unmute(struct fmi *fmi)
mutex_unlock(&fmi->lock); mutex_unlock(&fmi->lock);
} }
static inline int fmi_setfreq(struct fmi *fmi, unsigned long freq)
{
mutex_lock(&fmi->lock);
fmi->curfreq = freq;
outbits(16, RSF16_ENCODE(freq), fmi->io);
outbits(8, 0xC0, fmi->io);
msleep(143); /* was schedule_timeout(HZ/7) */
mutex_unlock(&fmi->lock);
if (!fmi->mute)
fmi_unmute(fmi);
return 0;
}
static inline int fmi_getsigstr(struct fmi *fmi) static inline int fmi_getsigstr(struct fmi *fmi)
{ {
int val; int val;
@ -173,7 +162,7 @@ static int vidioc_s_frequency(struct file *file, void *priv,
return -EINVAL; return -EINVAL;
/* rounding in steps of 800 to match the freq /* rounding in steps of 800 to match the freq
that will be used */ that will be used */
fmi_setfreq(fmi, (f->frequency / 800) * 800); lm7000_set_freq((f->frequency / 800) * 800, fmi, fmi_set_pins);
return 0; return 0;
} }

View File

@ -1514,7 +1514,8 @@ static int wl1273_fm_vidioc_g_tuner(struct file *file, void *priv,
tuner->rangehigh = WL1273_FREQ(WL1273_BAND_OTHER_HIGH); tuner->rangehigh = WL1273_FREQ(WL1273_BAND_OTHER_HIGH);
tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_RDS | tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_RDS |
V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS_BLOCK_IO; V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS_BLOCK_IO |
V4L2_TUNER_CAP_HWSEEK_BOUNDED | V4L2_TUNER_CAP_HWSEEK_WRAP;
if (radio->stereo) if (radio->stereo)
tuner->audmode = V4L2_TUNER_MODE_STEREO; tuner->audmode = V4L2_TUNER_MODE_STEREO;

View File

@ -363,7 +363,7 @@ stop:
/* try again, if timed out */ /* try again, if timed out */
if (retval == 0 && timed_out) if (retval == 0 && timed_out)
return -EAGAIN; return -ENODATA;
return retval; return retval;
} }
@ -596,7 +596,9 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
strcpy(tuner->name, "FM"); strcpy(tuner->name, "FM");
tuner->type = V4L2_TUNER_RADIO; tuner->type = V4L2_TUNER_RADIO;
tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO | tuner->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO; V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO |
V4L2_TUNER_CAP_HWSEEK_BOUNDED |
V4L2_TUNER_CAP_HWSEEK_WRAP;
/* range limits */ /* range limits */
switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) { switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) {

View File

@ -251,7 +251,7 @@ again:
if (!timeleft) { if (!timeleft) {
fmerr("Timeout(%d sec),didn't get tune ended int\n", fmerr("Timeout(%d sec),didn't get tune ended int\n",
jiffies_to_msecs(FM_DRV_RX_SEEK_TIMEOUT) / 1000); jiffies_to_msecs(FM_DRV_RX_SEEK_TIMEOUT) / 1000);
return -ETIMEDOUT; return -ENODATA;
} }
int_reason = fmdev->irq_info.flag & (FM_TUNE_COMPLETE | FM_BAND_LIMIT); int_reason = fmdev->irq_info.flag & (FM_TUNE_COMPLETE | FM_BAND_LIMIT);

View File

@ -285,7 +285,9 @@ static int fm_v4l2_vidioc_g_tuner(struct file *file, void *priv,
tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO | tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO |
((fmdev->rx.rds.flag == FM_RDS_ENABLE) ? V4L2_TUNER_SUB_RDS : 0); ((fmdev->rx.rds.flag == FM_RDS_ENABLE) ? V4L2_TUNER_SUB_RDS : 0);
tuner->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS | tuner->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS |
V4L2_TUNER_CAP_LOW; V4L2_TUNER_CAP_LOW |
V4L2_TUNER_CAP_HWSEEK_BOUNDED |
V4L2_TUNER_CAP_HWSEEK_WRAP;
tuner->audmode = (stereo_mono_mode ? tuner->audmode = (stereo_mono_mode ?
V4L2_TUNER_MODE_MONO : V4L2_TUNER_MODE_STEREO); V4L2_TUNER_MODE_MONO : V4L2_TUNER_MODE_STEREO);

View File

@ -1,22 +1,21 @@
menuconfig RC_CORE config RC_CORE
tristate "Remote Controller adapters"
depends on INPUT
default INPUT
---help---
Enable support for Remote Controllers on Linux. This is
needed in order to support several video capture adapters,
standalone IR receivers/transmitters, and RF receivers.
Enable this option if you have a video capture board even
if you don't need IR, as otherwise, you may not be able to
compile the driver for your adapter.
if RC_CORE
config LIRC
tristate tristate
depends on MEDIA_RC_SUPPORT
depends on INPUT
default y default y
source "drivers/media/rc/keymaps/Kconfig"
menuconfig RC_DECODERS
bool "Remote controller decoders"
depends on RC_CORE
default y
if RC_DECODERS
config LIRC
tristate "LIRC interface driver"
depends on RC_CORE
---help--- ---help---
Enable this option to build the Linux Infrared Remote Enable this option to build the Linux Infrared Remote
Control (LIRC) core device interface driver. The LIRC Control (LIRC) core device interface driver. The LIRC
@ -24,7 +23,16 @@ config LIRC
LIRC daemon handles protocol decoding for IR reception and LIRC daemon handles protocol decoding for IR reception and
encoding for IR transmitting (aka "blasting"). encoding for IR transmitting (aka "blasting").
source "drivers/media/rc/keymaps/Kconfig" config IR_LIRC_CODEC
tristate "Enable IR to LIRC bridge"
depends on RC_CORE
depends on LIRC
default y
---help---
Enable this option to pass raw IR to and from userspace via
the LIRC interface.
config IR_NEC_DECODER config IR_NEC_DECODER
tristate "Enable IR raw decoder for the NEC protocol" tristate "Enable IR raw decoder for the NEC protocol"
@ -108,16 +116,13 @@ config IR_MCE_KBD_DECODER
Enable this option if you have a Microsoft Remote Keyboard for Enable this option if you have a Microsoft Remote Keyboard for
Windows Media Center Edition, which you would like to use with Windows Media Center Edition, which you would like to use with
a raw IR receiver in your system. a raw IR receiver in your system.
endif #RC_DECODERS
config IR_LIRC_CODEC menuconfig RC_DEVICES
tristate "Enable IR to LIRC bridge" bool "Remote Controller devices"
depends on RC_CORE depends on RC_CORE
depends on LIRC
default y
---help--- if RC_DEVICES
Enable this option to pass raw IR to and from userspace via
the LIRC interface.
config RC_ATI_REMOTE config RC_ATI_REMOTE
tristate "ATI / X10 based USB RF remote controls" tristate "ATI / X10 based USB RF remote controls"
@ -276,4 +281,4 @@ config IR_GPIO_CIR
To compile this driver as a module, choose M here: the module will To compile this driver as a module, choose M here: the module will
be called gpio-ir-recv. be called gpio-ir-recv.
endif #RC_CORE endif #RC_DEVICES

View File

@ -1018,6 +1018,8 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
spin_lock_init(&dev->hw_lock); spin_lock_init(&dev->hw_lock);
dev->hw_io = pnp_port_start(pnp_dev, 0);
pnp_set_drvdata(pnp_dev, dev); pnp_set_drvdata(pnp_dev, dev);
dev->pnp_dev = pnp_dev; dev->pnp_dev = pnp_dev;
@ -1072,7 +1074,6 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
/* claim the resources */ /* claim the resources */
error = -EBUSY; error = -EBUSY;
dev->hw_io = pnp_port_start(pnp_dev, 0);
if (!request_region(dev->hw_io, ENE_IO_SIZE, ENE_DRIVER_NAME)) { if (!request_region(dev->hw_io, ENE_IO_SIZE, ENE_DRIVER_NAME)) {
dev->hw_io = -1; dev->hw_io = -1;
dev->irq = -1; dev->irq = -1;

View File

@ -23,6 +23,8 @@
* USA * USA
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pnp.h> #include <linux/pnp.h>
@ -110,30 +112,32 @@ static u8 fintek_cir_reg_read(struct fintek_dev *fintek, u8 offset)
return val; return val;
} }
#define pr_reg(text, ...) \
printk(KERN_INFO KBUILD_MODNAME ": " text, ## __VA_ARGS__)
/* dump current cir register contents */ /* dump current cir register contents */
static void cir_dump_regs(struct fintek_dev *fintek) static void cir_dump_regs(struct fintek_dev *fintek)
{ {
fintek_config_mode_enable(fintek); fintek_config_mode_enable(fintek);
fintek_select_logical_dev(fintek, fintek->logical_dev_cir); fintek_select_logical_dev(fintek, fintek->logical_dev_cir);
pr_reg("%s: Dump CIR logical device registers:\n", FINTEK_DRIVER_NAME); pr_info("%s: Dump CIR logical device registers:\n", FINTEK_DRIVER_NAME);
pr_reg(" * CR CIR BASE ADDR: 0x%x\n", pr_info(" * CR CIR BASE ADDR: 0x%x\n",
(fintek_cr_read(fintek, CIR_CR_BASE_ADDR_HI) << 8) | (fintek_cr_read(fintek, CIR_CR_BASE_ADDR_HI) << 8) |
fintek_cr_read(fintek, CIR_CR_BASE_ADDR_LO)); fintek_cr_read(fintek, CIR_CR_BASE_ADDR_LO));
pr_reg(" * CR CIR IRQ NUM: 0x%x\n", pr_info(" * CR CIR IRQ NUM: 0x%x\n",
fintek_cr_read(fintek, CIR_CR_IRQ_SEL)); fintek_cr_read(fintek, CIR_CR_IRQ_SEL));
fintek_config_mode_disable(fintek); fintek_config_mode_disable(fintek);
pr_reg("%s: Dump CIR registers:\n", FINTEK_DRIVER_NAME); pr_info("%s: Dump CIR registers:\n", FINTEK_DRIVER_NAME);
pr_reg(" * STATUS: 0x%x\n", fintek_cir_reg_read(fintek, CIR_STATUS)); pr_info(" * STATUS: 0x%x\n",
pr_reg(" * CONTROL: 0x%x\n", fintek_cir_reg_read(fintek, CIR_CONTROL)); fintek_cir_reg_read(fintek, CIR_STATUS));
pr_reg(" * RX_DATA: 0x%x\n", fintek_cir_reg_read(fintek, CIR_RX_DATA)); pr_info(" * CONTROL: 0x%x\n",
pr_reg(" * TX_CONTROL: 0x%x\n", fintek_cir_reg_read(fintek, CIR_TX_CONTROL)); fintek_cir_reg_read(fintek, CIR_CONTROL));
pr_reg(" * TX_DATA: 0x%x\n", fintek_cir_reg_read(fintek, CIR_TX_DATA)); pr_info(" * RX_DATA: 0x%x\n",
fintek_cir_reg_read(fintek, CIR_RX_DATA));
pr_info(" * TX_CONTROL: 0x%x\n",
fintek_cir_reg_read(fintek, CIR_TX_CONTROL));
pr_info(" * TX_DATA: 0x%x\n",
fintek_cir_reg_read(fintek, CIR_TX_DATA));
} }
/* detect hardware features */ /* detect hardware features */

View File

@ -82,12 +82,21 @@ static int __devinit gpio_ir_recv_probe(struct platform_device *pdev)
goto err_allocate_device; goto err_allocate_device;
} }
rcdev->priv = gpio_dev;
rcdev->driver_type = RC_DRIVER_IR_RAW; rcdev->driver_type = RC_DRIVER_IR_RAW;
rcdev->allowed_protos = RC_TYPE_ALL;
rcdev->input_name = GPIO_IR_DEVICE_NAME; rcdev->input_name = GPIO_IR_DEVICE_NAME;
rcdev->input_phys = GPIO_IR_DEVICE_NAME "/input0";
rcdev->input_id.bustype = BUS_HOST; rcdev->input_id.bustype = BUS_HOST;
rcdev->input_id.vendor = 0x0001;
rcdev->input_id.product = 0x0001;
rcdev->input_id.version = 0x0100;
rcdev->dev.parent = &pdev->dev;
rcdev->driver_name = GPIO_IR_DRIVER_NAME; rcdev->driver_name = GPIO_IR_DRIVER_NAME;
rcdev->map_name = RC_MAP_EMPTY; if (pdata->allowed_protos)
rcdev->allowed_protos = pdata->allowed_protos;
else
rcdev->allowed_protos = RC_TYPE_ALL;
rcdev->map_name = pdata->map_name ?: RC_MAP_EMPTY;
gpio_dev->rcdev = rcdev; gpio_dev->rcdev = rcdev;
gpio_dev->gpio_nr = pdata->gpio_nr; gpio_dev->gpio_nr = pdata->gpio_nr;
@ -188,18 +197,7 @@ static struct platform_driver gpio_ir_recv_driver = {
#endif #endif
}, },
}; };
module_platform_driver(gpio_ir_recv_driver);
static int __init gpio_ir_recv_init(void)
{
return platform_driver_register(&gpio_ir_recv_driver);
}
module_init(gpio_ir_recv_init);
static void __exit gpio_ir_recv_exit(void)
{
platform_driver_unregister(&gpio_ir_recv_driver);
}
module_exit(gpio_ir_recv_exit);
MODULE_DESCRIPTION("GPIO IR Receiver driver"); MODULE_DESCRIPTION("GPIO IR Receiver driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");

View File

@ -25,6 +25,8 @@
* USA * USA
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pnp.h> #include <linux/pnp.h>
@ -123,43 +125,40 @@ static u8 nvt_cir_wake_reg_read(struct nvt_dev *nvt, u8 offset)
return val; return val;
} }
#define pr_reg(text, ...) \
printk(KERN_INFO KBUILD_MODNAME ": " text, ## __VA_ARGS__)
/* dump current cir register contents */ /* dump current cir register contents */
static void cir_dump_regs(struct nvt_dev *nvt) static void cir_dump_regs(struct nvt_dev *nvt)
{ {
nvt_efm_enable(nvt); nvt_efm_enable(nvt);
nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
pr_reg("%s: Dump CIR logical device registers:\n", NVT_DRIVER_NAME); pr_info("%s: Dump CIR logical device registers:\n", NVT_DRIVER_NAME);
pr_reg(" * CR CIR ACTIVE : 0x%x\n", pr_info(" * CR CIR ACTIVE : 0x%x\n",
nvt_cr_read(nvt, CR_LOGICAL_DEV_EN)); nvt_cr_read(nvt, CR_LOGICAL_DEV_EN));
pr_reg(" * CR CIR BASE ADDR: 0x%x\n", pr_info(" * CR CIR BASE ADDR: 0x%x\n",
(nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8) | (nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8) |
nvt_cr_read(nvt, CR_CIR_BASE_ADDR_LO)); nvt_cr_read(nvt, CR_CIR_BASE_ADDR_LO));
pr_reg(" * CR CIR IRQ NUM: 0x%x\n", pr_info(" * CR CIR IRQ NUM: 0x%x\n",
nvt_cr_read(nvt, CR_CIR_IRQ_RSRC)); nvt_cr_read(nvt, CR_CIR_IRQ_RSRC));
nvt_efm_disable(nvt); nvt_efm_disable(nvt);
pr_reg("%s: Dump CIR registers:\n", NVT_DRIVER_NAME); pr_info("%s: Dump CIR registers:\n", NVT_DRIVER_NAME);
pr_reg(" * IRCON: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRCON)); pr_info(" * IRCON: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRCON));
pr_reg(" * IRSTS: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRSTS)); pr_info(" * IRSTS: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRSTS));
pr_reg(" * IREN: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IREN)); pr_info(" * IREN: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IREN));
pr_reg(" * RXFCONT: 0x%x\n", nvt_cir_reg_read(nvt, CIR_RXFCONT)); pr_info(" * RXFCONT: 0x%x\n", nvt_cir_reg_read(nvt, CIR_RXFCONT));
pr_reg(" * CP: 0x%x\n", nvt_cir_reg_read(nvt, CIR_CP)); pr_info(" * CP: 0x%x\n", nvt_cir_reg_read(nvt, CIR_CP));
pr_reg(" * CC: 0x%x\n", nvt_cir_reg_read(nvt, CIR_CC)); pr_info(" * CC: 0x%x\n", nvt_cir_reg_read(nvt, CIR_CC));
pr_reg(" * SLCH: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SLCH)); pr_info(" * SLCH: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SLCH));
pr_reg(" * SLCL: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SLCL)); pr_info(" * SLCL: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SLCL));
pr_reg(" * FIFOCON: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FIFOCON)); pr_info(" * FIFOCON: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FIFOCON));
pr_reg(" * IRFIFOSTS: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRFIFOSTS)); pr_info(" * IRFIFOSTS: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRFIFOSTS));
pr_reg(" * SRXFIFO: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SRXFIFO)); pr_info(" * SRXFIFO: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SRXFIFO));
pr_reg(" * TXFCONT: 0x%x\n", nvt_cir_reg_read(nvt, CIR_TXFCONT)); pr_info(" * TXFCONT: 0x%x\n", nvt_cir_reg_read(nvt, CIR_TXFCONT));
pr_reg(" * STXFIFO: 0x%x\n", nvt_cir_reg_read(nvt, CIR_STXFIFO)); pr_info(" * STXFIFO: 0x%x\n", nvt_cir_reg_read(nvt, CIR_STXFIFO));
pr_reg(" * FCCH: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FCCH)); pr_info(" * FCCH: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FCCH));
pr_reg(" * FCCL: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FCCL)); pr_info(" * FCCL: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FCCL));
pr_reg(" * IRFSM: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRFSM)); pr_info(" * IRFSM: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRFSM));
} }
/* dump current cir wake register contents */ /* dump current cir wake register contents */
@ -170,59 +169,59 @@ static void cir_wake_dump_regs(struct nvt_dev *nvt)
nvt_efm_enable(nvt); nvt_efm_enable(nvt);
nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE); nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE);
pr_reg("%s: Dump CIR WAKE logical device registers:\n", pr_info("%s: Dump CIR WAKE logical device registers:\n",
NVT_DRIVER_NAME); NVT_DRIVER_NAME);
pr_reg(" * CR CIR WAKE ACTIVE : 0x%x\n", pr_info(" * CR CIR WAKE ACTIVE : 0x%x\n",
nvt_cr_read(nvt, CR_LOGICAL_DEV_EN)); nvt_cr_read(nvt, CR_LOGICAL_DEV_EN));
pr_reg(" * CR CIR WAKE BASE ADDR: 0x%x\n", pr_info(" * CR CIR WAKE BASE ADDR: 0x%x\n",
(nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8) | (nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8) |
nvt_cr_read(nvt, CR_CIR_BASE_ADDR_LO)); nvt_cr_read(nvt, CR_CIR_BASE_ADDR_LO));
pr_reg(" * CR CIR WAKE IRQ NUM: 0x%x\n", pr_info(" * CR CIR WAKE IRQ NUM: 0x%x\n",
nvt_cr_read(nvt, CR_CIR_IRQ_RSRC)); nvt_cr_read(nvt, CR_CIR_IRQ_RSRC));
nvt_efm_disable(nvt); nvt_efm_disable(nvt);
pr_reg("%s: Dump CIR WAKE registers\n", NVT_DRIVER_NAME); pr_info("%s: Dump CIR WAKE registers\n", NVT_DRIVER_NAME);
pr_reg(" * IRCON: 0x%x\n", pr_info(" * IRCON: 0x%x\n",
nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRCON)); nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRCON));
pr_reg(" * IRSTS: 0x%x\n", pr_info(" * IRSTS: 0x%x\n",
nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS)); nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS));
pr_reg(" * IREN: 0x%x\n", pr_info(" * IREN: 0x%x\n",
nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN)); nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN));
pr_reg(" * FIFO CMP DEEP: 0x%x\n", pr_info(" * FIFO CMP DEEP: 0x%x\n",
nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_CMP_DEEP)); nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_CMP_DEEP));
pr_reg(" * FIFO CMP TOL: 0x%x\n", pr_info(" * FIFO CMP TOL: 0x%x\n",
nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_CMP_TOL)); nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_CMP_TOL));
pr_reg(" * FIFO COUNT: 0x%x\n", pr_info(" * FIFO COUNT: 0x%x\n",
nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT)); nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT));
pr_reg(" * SLCH: 0x%x\n", pr_info(" * SLCH: 0x%x\n",
nvt_cir_wake_reg_read(nvt, CIR_WAKE_SLCH)); nvt_cir_wake_reg_read(nvt, CIR_WAKE_SLCH));
pr_reg(" * SLCL: 0x%x\n", pr_info(" * SLCL: 0x%x\n",
nvt_cir_wake_reg_read(nvt, CIR_WAKE_SLCL)); nvt_cir_wake_reg_read(nvt, CIR_WAKE_SLCL));
pr_reg(" * FIFOCON: 0x%x\n", pr_info(" * FIFOCON: 0x%x\n",
nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFOCON)); nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFOCON));
pr_reg(" * SRXFSTS: 0x%x\n", pr_info(" * SRXFSTS: 0x%x\n",
nvt_cir_wake_reg_read(nvt, CIR_WAKE_SRXFSTS)); nvt_cir_wake_reg_read(nvt, CIR_WAKE_SRXFSTS));
pr_reg(" * SAMPLE RX FIFO: 0x%x\n", pr_info(" * SAMPLE RX FIFO: 0x%x\n",
nvt_cir_wake_reg_read(nvt, CIR_WAKE_SAMPLE_RX_FIFO)); nvt_cir_wake_reg_read(nvt, CIR_WAKE_SAMPLE_RX_FIFO));
pr_reg(" * WR FIFO DATA: 0x%x\n", pr_info(" * WR FIFO DATA: 0x%x\n",
nvt_cir_wake_reg_read(nvt, CIR_WAKE_WR_FIFO_DATA)); nvt_cir_wake_reg_read(nvt, CIR_WAKE_WR_FIFO_DATA));
pr_reg(" * RD FIFO ONLY: 0x%x\n", pr_info(" * RD FIFO ONLY: 0x%x\n",
nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY)); nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY));
pr_reg(" * RD FIFO ONLY IDX: 0x%x\n", pr_info(" * RD FIFO ONLY IDX: 0x%x\n",
nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY_IDX)); nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY_IDX));
pr_reg(" * FIFO IGNORE: 0x%x\n", pr_info(" * FIFO IGNORE: 0x%x\n",
nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_IGNORE)); nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_IGNORE));
pr_reg(" * IRFSM: 0x%x\n", pr_info(" * IRFSM: 0x%x\n",
nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRFSM)); nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRFSM));
fifo_len = nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT); fifo_len = nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT);
pr_reg("%s: Dump CIR WAKE FIFO (len %d)\n", NVT_DRIVER_NAME, fifo_len); pr_info("%s: Dump CIR WAKE FIFO (len %d)\n", NVT_DRIVER_NAME, fifo_len);
pr_reg("* Contents = "); pr_info("* Contents =");
for (i = 0; i < fifo_len; i++) for (i = 0; i < fifo_len; i++)
printk(KERN_CONT "%02x ", pr_cont(" %02x",
nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY)); nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY));
printk(KERN_CONT "\n"); pr_cont("\n");
} }
/* detect hardware features */ /* detect hardware features */

View File

@ -5,7 +5,7 @@
config VIDEO_V4L2 config VIDEO_V4L2
tristate tristate
depends on VIDEO_DEV && VIDEO_V4L2_COMMON depends on VIDEO_DEV && VIDEO_V4L2_COMMON
default VIDEO_DEV && VIDEO_V4L2_COMMON default y
config VIDEOBUF_GEN config VIDEOBUF_GEN
tristate tristate
@ -73,6 +73,7 @@ config VIDEOBUF2_DMA_SG
menuconfig VIDEO_CAPTURE_DRIVERS menuconfig VIDEO_CAPTURE_DRIVERS
bool "Video capture adapters" bool "Video capture adapters"
depends on VIDEO_V4L2 depends on VIDEO_V4L2
depends on MEDIA_CAMERA_SUPPORT || MEDIA_ANALOG_TV_SUPPORT
default y default y
---help--- ---help---
Say Y here to enable selecting the video adapters for Say Y here to enable selecting the video adapters for
@ -461,6 +462,15 @@ config VIDEO_ADV7343
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called adv7343. module will be called adv7343.
config VIDEO_ADV7393
tristate "ADV7393 video encoder"
depends on I2C
help
Support for Analog Devices I2C bus based ADV7393 encoder.
To compile this driver as a module, choose M here: the
module will be called adv7393.
config VIDEO_AK881X config VIDEO_AK881X
tristate "AK8813/AK8814 video encoders" tristate "AK8813/AK8814 video encoders"
depends on I2C depends on I2C
@ -478,6 +488,7 @@ config VIDEO_SMIAPP_PLL
config VIDEO_OV7670 config VIDEO_OV7670
tristate "OmniVision OV7670 sensor support" tristate "OmniVision OV7670 sensor support"
depends on I2C && VIDEO_V4L2 depends on I2C && VIDEO_V4L2
depends on MEDIA_CAMERA_SUPPORT
---help--- ---help---
This is a Video4Linux2 sensor-level driver for the OmniVision This is a Video4Linux2 sensor-level driver for the OmniVision
OV7670 VGA camera. It currently only works with the M88ALP01 OV7670 VGA camera. It currently only works with the M88ALP01
@ -486,6 +497,7 @@ config VIDEO_OV7670
config VIDEO_VS6624 config VIDEO_VS6624
tristate "ST VS6624 sensor support" tristate "ST VS6624 sensor support"
depends on VIDEO_V4L2 && I2C depends on VIDEO_V4L2 && I2C
depends on MEDIA_CAMERA_SUPPORT
---help--- ---help---
This is a Video4Linux2 sensor-level driver for the ST VS6624 This is a Video4Linux2 sensor-level driver for the ST VS6624
camera. camera.
@ -496,6 +508,7 @@ config VIDEO_VS6624
config VIDEO_MT9M032 config VIDEO_MT9M032
tristate "MT9M032 camera sensor support" tristate "MT9M032 camera sensor support"
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
depends on MEDIA_CAMERA_SUPPORT
select VIDEO_APTINA_PLL select VIDEO_APTINA_PLL
---help--- ---help---
This driver supports MT9M032 camera sensors from Aptina, monochrome This driver supports MT9M032 camera sensors from Aptina, monochrome
@ -504,6 +517,7 @@ config VIDEO_MT9M032
config VIDEO_MT9P031 config VIDEO_MT9P031
tristate "Aptina MT9P031 support" tristate "Aptina MT9P031 support"
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
depends on MEDIA_CAMERA_SUPPORT
select VIDEO_APTINA_PLL select VIDEO_APTINA_PLL
---help--- ---help---
This is a Video4Linux2 sensor-level driver for the Aptina This is a Video4Linux2 sensor-level driver for the Aptina
@ -512,6 +526,7 @@ config VIDEO_MT9P031
config VIDEO_MT9T001 config VIDEO_MT9T001
tristate "Aptina MT9T001 support" tristate "Aptina MT9T001 support"
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
depends on MEDIA_CAMERA_SUPPORT
---help--- ---help---
This is a Video4Linux2 sensor-level driver for the Aptina This is a Video4Linux2 sensor-level driver for the Aptina
(Micron) mt0t001 3 Mpixel camera. (Micron) mt0t001 3 Mpixel camera.
@ -519,6 +534,7 @@ config VIDEO_MT9T001
config VIDEO_MT9V011 config VIDEO_MT9V011
tristate "Micron mt9v011 sensor support" tristate "Micron mt9v011 sensor support"
depends on I2C && VIDEO_V4L2 depends on I2C && VIDEO_V4L2
depends on MEDIA_CAMERA_SUPPORT
---help--- ---help---
This is a Video4Linux2 sensor-level driver for the Micron This is a Video4Linux2 sensor-level driver for the Micron
mt0v011 1.3 Mpixel camera. It currently only works with the mt0v011 1.3 Mpixel camera. It currently only works with the
@ -527,6 +543,7 @@ config VIDEO_MT9V011
config VIDEO_MT9V032 config VIDEO_MT9V032
tristate "Micron MT9V032 sensor support" tristate "Micron MT9V032 sensor support"
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
depends on MEDIA_CAMERA_SUPPORT
---help--- ---help---
This is a Video4Linux2 sensor-level driver for the Micron This is a Video4Linux2 sensor-level driver for the Micron
MT9V032 752x480 CMOS sensor. MT9V032 752x480 CMOS sensor.
@ -534,6 +551,7 @@ config VIDEO_MT9V032
config VIDEO_TCM825X config VIDEO_TCM825X
tristate "TCM825x camera sensor support" tristate "TCM825x camera sensor support"
depends on I2C && VIDEO_V4L2 depends on I2C && VIDEO_V4L2
depends on MEDIA_CAMERA_SUPPORT
---help--- ---help---
This is a driver for the Toshiba TCM825x VGA camera sensor. This is a driver for the Toshiba TCM825x VGA camera sensor.
It is used for example in Nokia N800. It is used for example in Nokia N800.
@ -541,12 +559,14 @@ config VIDEO_TCM825X
config VIDEO_SR030PC30 config VIDEO_SR030PC30
tristate "Siliconfile SR030PC30 sensor support" tristate "Siliconfile SR030PC30 sensor support"
depends on I2C && VIDEO_V4L2 depends on I2C && VIDEO_V4L2
depends on MEDIA_CAMERA_SUPPORT
---help--- ---help---
This driver supports SR030PC30 VGA camera from Siliconfile This driver supports SR030PC30 VGA camera from Siliconfile
config VIDEO_NOON010PC30 config VIDEO_NOON010PC30
tristate "Siliconfile NOON010PC30 sensor support" tristate "Siliconfile NOON010PC30 sensor support"
depends on I2C && VIDEO_V4L2 && EXPERIMENTAL && VIDEO_V4L2_SUBDEV_API depends on I2C && VIDEO_V4L2 && EXPERIMENTAL && VIDEO_V4L2_SUBDEV_API
depends on MEDIA_CAMERA_SUPPORT
---help--- ---help---
This driver supports NOON010PC30 CIF camera from Siliconfile This driver supports NOON010PC30 CIF camera from Siliconfile
@ -554,6 +574,7 @@ source "drivers/media/video/m5mols/Kconfig"
config VIDEO_S5K6AA config VIDEO_S5K6AA
tristate "Samsung S5K6AAFX sensor support" tristate "Samsung S5K6AAFX sensor support"
depends on MEDIA_CAMERA_SUPPORT
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
---help--- ---help---
This is a V4L2 sensor-level driver for Samsung S5K6AA(FX) 1.3M This is a V4L2 sensor-level driver for Samsung S5K6AA(FX) 1.3M
@ -566,6 +587,7 @@ comment "Flash devices"
config VIDEO_ADP1653 config VIDEO_ADP1653
tristate "ADP1653 flash support" tristate "ADP1653 flash support"
depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
depends on MEDIA_CAMERA_SUPPORT
---help--- ---help---
This is a driver for the ADP1653 flash controller. It is used for This is a driver for the ADP1653 flash controller. It is used for
example in Nokia N900. example in Nokia N900.
@ -573,6 +595,7 @@ config VIDEO_ADP1653
config VIDEO_AS3645A config VIDEO_AS3645A
tristate "AS3645A flash driver support" tristate "AS3645A flash driver support"
depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
depends on MEDIA_CAMERA_SUPPORT
---help--- ---help---
This is a driver for the AS3645A and LM3555 flash controllers. It has This is a driver for the AS3645A and LM3555 flash controllers. It has
build in control for flash, torch and indicator LEDs. build in control for flash, torch and indicator LEDs.
@ -647,30 +670,14 @@ menuconfig V4L_USB_DRIVERS
depends on USB depends on USB
default y default y
if V4L_USB_DRIVERS if V4L_USB_DRIVERS && MEDIA_CAMERA_SUPPORT
source "drivers/media/video/au0828/Kconfig" comment "Webcam devices"
source "drivers/media/video/uvc/Kconfig" source "drivers/media/video/uvc/Kconfig"
source "drivers/media/video/gspca/Kconfig" source "drivers/media/video/gspca/Kconfig"
source "drivers/media/video/pvrusb2/Kconfig"
source "drivers/media/video/hdpvr/Kconfig"
source "drivers/media/video/em28xx/Kconfig"
source "drivers/media/video/tlg2300/Kconfig"
source "drivers/media/video/cx231xx/Kconfig"
source "drivers/media/video/tm6000/Kconfig"
source "drivers/media/video/usbvision/Kconfig"
source "drivers/media/video/sn9c102/Kconfig"
source "drivers/media/video/pwc/Kconfig" source "drivers/media/video/pwc/Kconfig"
source "drivers/media/video/cpia2/Kconfig" source "drivers/media/video/cpia2/Kconfig"
@ -711,15 +718,46 @@ config USB_S2255
Say Y here if you want support for the Sensoray 2255 USB device. Say Y here if you want support for the Sensoray 2255 USB device.
This driver can be compiled as a module, called s2255drv. This driver can be compiled as a module, called s2255drv.
source "drivers/media/video/sn9c102/Kconfig"
endif # V4L_USB_DRIVERS && MEDIA_CAMERA_SUPPORT
if V4L_USB_DRIVERS
comment "Webcam and/or TV USB devices"
source "drivers/media/video/em28xx/Kconfig"
endif
if V4L_USB_DRIVERS && MEDIA_ANALOG_TV_SUPPORT
comment "TV USB devices"
source "drivers/media/video/au0828/Kconfig"
source "drivers/media/video/pvrusb2/Kconfig"
source "drivers/media/video/hdpvr/Kconfig"
source "drivers/media/video/tlg2300/Kconfig"
source "drivers/media/video/cx231xx/Kconfig"
source "drivers/media/video/tm6000/Kconfig"
source "drivers/media/video/usbvision/Kconfig"
endif # V4L_USB_DRIVERS endif # V4L_USB_DRIVERS
# #
# PCI drivers configuration # PCI drivers configuration - No devices here are for webcams
# #
menuconfig V4L_PCI_DRIVERS menuconfig V4L_PCI_DRIVERS
bool "V4L PCI(e) devices" bool "V4L PCI(e) devices"
depends on PCI depends on PCI
depends on MEDIA_ANALOG_TV_SUPPORT
default y default y
---help--- ---help---
Say Y here to enable support for these PCI(e) drivers. Say Y here to enable support for these PCI(e) drivers.
@ -814,11 +852,13 @@ endif # V4L_PCI_DRIVERS
# #
# ISA & parallel port drivers configuration # ISA & parallel port drivers configuration
# All devices here are webcam or grabber devices
# #
menuconfig V4L_ISA_PARPORT_DRIVERS menuconfig V4L_ISA_PARPORT_DRIVERS
bool "V4L ISA and parallel port devices" bool "V4L ISA and parallel port devices"
depends on ISA || PARPORT depends on ISA || PARPORT
depends on MEDIA_CAMERA_SUPPORT
default n default n
---help--- ---help---
Say Y here to enable support for these ISA and parallel port drivers. Say Y here to enable support for these ISA and parallel port drivers.
@ -871,8 +911,13 @@ config VIDEO_W9966
endif # V4L_ISA_PARPORT_DRIVERS endif # V4L_ISA_PARPORT_DRIVERS
#
# Platform drivers
# All drivers here are currently for webcam support
menuconfig V4L_PLATFORM_DRIVERS menuconfig V4L_PLATFORM_DRIVERS
bool "V4L platform devices" bool "V4L platform devices"
depends on MEDIA_CAMERA_SUPPORT
default n default n
---help--- ---help---
Say Y here to enable support for platform-specific V4L drivers. Say Y here to enable support for platform-specific V4L drivers.

View File

@ -45,6 +45,7 @@ obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o
obj-$(CONFIG_VIDEO_ADV7180) += adv7180.o obj-$(CONFIG_VIDEO_ADV7180) += adv7180.o
obj-$(CONFIG_VIDEO_ADV7183) += adv7183.o obj-$(CONFIG_VIDEO_ADV7183) += adv7183.o
obj-$(CONFIG_VIDEO_ADV7343) += adv7343.o obj-$(CONFIG_VIDEO_ADV7343) += adv7343.o
obj-$(CONFIG_VIDEO_ADV7393) += adv7393.o
obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o
obj-$(CONFIG_VIDEO_VS6624) += vs6624.o obj-$(CONFIG_VIDEO_VS6624) += vs6624.o
obj-$(CONFIG_VIDEO_BT819) += bt819.o obj-$(CONFIG_VIDEO_BT819) += bt819.o

View 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);

View 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

View File

@ -676,6 +676,7 @@ struct tvcard bttv_tvcards[] = {
.tuner_type = UNSET, .tuner_type = UNSET,
.tuner_addr = ADDR_UNSET, .tuner_addr = ADDR_UNSET,
.has_remote = 1, .has_remote = 1,
.has_radio = 1, /* not every card has radio */
}, },
[BTTV_BOARD_VOBIS_BOOSTAR] = { [BTTV_BOARD_VOBIS_BOOSTAR] = {
.name = "Terratec TerraTV+ Version 1.0 (Bt848)/ Terra TValue Version 1.0/ Vobis TV-Boostar", .name = "Terratec TerraTV+ Version 1.0 (Bt848)/ Terra TValue Version 1.0/ Vobis TV-Boostar",

View File

@ -557,12 +557,6 @@ static const struct bttv_format formats[] = {
.btformat = BT848_COLOR_FMT_YUY2, .btformat = BT848_COLOR_FMT_YUY2,
.depth = 16, .depth = 16,
.flags = FORMAT_FLAGS_PACKED, .flags = FORMAT_FLAGS_PACKED,
},{
.name = "4:2:2, packed, YUYV",
.fourcc = V4L2_PIX_FMT_YUYV,
.btformat = BT848_COLOR_FMT_YUY2,
.depth = 16,
.flags = FORMAT_FLAGS_PACKED,
},{ },{
.name = "4:2:2, packed, UYVY", .name = "4:2:2, packed, UYVY",
.fourcc = V4L2_PIX_FMT_UYVY, .fourcc = V4L2_PIX_FMT_UYVY,

View File

@ -932,7 +932,7 @@ static int cpia2_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
buf->sequence = cam->buffers[buf->index].seq; buf->sequence = cam->buffers[buf->index].seq;
buf->m.offset = cam->buffers[buf->index].data - cam->frame_buffer; buf->m.offset = cam->buffers[buf->index].data - cam->frame_buffer;
buf->length = cam->frame_size; buf->length = cam->frame_size;
buf->input = 0; buf->reserved2 = 0;
buf->reserved = 0; buf->reserved = 0;
memset(&buf->timecode, 0, sizeof(buf->timecode)); memset(&buf->timecode, 0, sizeof(buf->timecode));

View File

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

View File

@ -1142,24 +1142,6 @@ static long cx18_default(struct file *file, void *fh, bool valid_prio,
return 0; return 0;
} }
long cx18_v4l2_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
{
struct video_device *vfd = video_devdata(filp);
struct cx18_open_id *id = file2id(filp);
struct cx18 *cx = id->cx;
long res;
mutex_lock(&cx->serialize_lock);
if (cx18_debug & CX18_DBGFLG_IOCTL)
vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
res = video_ioctl2(filp, cmd, arg);
vfd->debug = 0;
mutex_unlock(&cx->serialize_lock);
return res;
}
static const struct v4l2_ioctl_ops cx18_ioctl_ops = { static const struct v4l2_ioctl_ops cx18_ioctl_ops = {
.vidioc_querycap = cx18_querycap, .vidioc_querycap = cx18_querycap,
.vidioc_s_audio = cx18_s_audio, .vidioc_s_audio = cx18_s_audio,

View File

@ -29,5 +29,3 @@ void cx18_set_funcs(struct video_device *vdev);
int cx18_s_std(struct file *file, void *fh, v4l2_std_id *std); int cx18_s_std(struct file *file, void *fh, v4l2_std_id *std);
int cx18_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf); int cx18_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf);
int cx18_s_input(struct file *file, void *fh, unsigned int inp); int cx18_s_input(struct file *file, void *fh, unsigned int inp);
long cx18_v4l2_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg);

View File

@ -40,8 +40,7 @@ static struct v4l2_file_operations cx18_v4l2_enc_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.read = cx18_v4l2_read, .read = cx18_v4l2_read,
.open = cx18_v4l2_open, .open = cx18_v4l2_open,
/* FIXME change to video_ioctl2 if serialization lock can be removed */ .unlocked_ioctl = video_ioctl2,
.unlocked_ioctl = cx18_v4l2_ioctl,
.release = cx18_v4l2_close, .release = cx18_v4l2_close,
.poll = cx18_v4l2_enc_poll, .poll = cx18_v4l2_enc_poll,
.mmap = cx18_v4l2_mmap, .mmap = cx18_v4l2_mmap,
@ -376,6 +375,7 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
s->video_dev->fops = &cx18_v4l2_enc_fops; s->video_dev->fops = &cx18_v4l2_enc_fops;
s->video_dev->release = video_device_release; s->video_dev->release = video_device_release;
s->video_dev->tvnorms = V4L2_STD_ALL; s->video_dev->tvnorms = V4L2_STD_ALL;
s->video_dev->lock = &cx->serialize_lock;
set_bit(V4L2_FL_USE_FH_PRIO, &s->video_dev->flags); set_bit(V4L2_FL_USE_FH_PRIO, &s->video_dev->flags);
cx18_set_funcs(s->video_dev); cx18_set_funcs(s->video_dev);
return 0; return 0;

View File

@ -89,7 +89,7 @@ void initGPIO(struct cx231xx *dev)
verve_read_byte(dev, 0x07, &val); verve_read_byte(dev, 0x07, &val);
cx231xx_info(" verve_read_byte address0x07=0x%x\n", val); cx231xx_info(" verve_read_byte address0x07=0x%x\n", val);
cx231xx_capture_start(dev, 1, 2); cx231xx_capture_start(dev, 1, Vbi);
cx231xx_mode_register(dev, EP_MODE_SET, 0x0500FE00); cx231xx_mode_register(dev, EP_MODE_SET, 0x0500FE00);
cx231xx_mode_register(dev, GBULK_BIT_EN, 0xFFFDFFFF); cx231xx_mode_register(dev, GBULK_BIT_EN, 0xFFFDFFFF);
@ -99,7 +99,7 @@ void uninitGPIO(struct cx231xx *dev)
{ {
u8 value[4] = { 0, 0, 0, 0 }; u8 value[4] = { 0, 0, 0, 0 };
cx231xx_capture_start(dev, 0, 2); cx231xx_capture_start(dev, 0, Vbi);
verve_write_byte(dev, 0x07, 0x14); verve_write_byte(dev, 0x07, 0x14);
cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
0x68, value, 4); 0x68, value, 4);
@ -2516,29 +2516,29 @@ int cx231xx_initialize_stream_xfer(struct cx231xx *dev, u32 media_type)
if (dev->udev->speed == USB_SPEED_HIGH) { if (dev->udev->speed == USB_SPEED_HIGH) {
switch (media_type) { switch (media_type) {
case 81: /* audio */ case Audio:
cx231xx_info("%s: Audio enter HANC\n", __func__); cx231xx_info("%s: Audio enter HANC\n", __func__);
status = status =
cx231xx_mode_register(dev, TS_MODE_REG, 0x9300); cx231xx_mode_register(dev, TS_MODE_REG, 0x9300);
break; break;
case 2: /* vbi */ case Vbi:
cx231xx_info("%s: set vanc registers\n", __func__); cx231xx_info("%s: set vanc registers\n", __func__);
status = cx231xx_mode_register(dev, TS_MODE_REG, 0x300); status = cx231xx_mode_register(dev, TS_MODE_REG, 0x300);
break; break;
case 3: /* sliced cc */ case Sliced_cc:
cx231xx_info("%s: set hanc registers\n", __func__); cx231xx_info("%s: set hanc registers\n", __func__);
status = status =
cx231xx_mode_register(dev, TS_MODE_REG, 0x1300); cx231xx_mode_register(dev, TS_MODE_REG, 0x1300);
break; break;
case 0: /* video */ case Raw_Video:
cx231xx_info("%s: set video registers\n", __func__); cx231xx_info("%s: set video registers\n", __func__);
status = cx231xx_mode_register(dev, TS_MODE_REG, 0x100); status = cx231xx_mode_register(dev, TS_MODE_REG, 0x100);
break; break;
case 4: /* ts1 */ case TS1_serial_mode:
cx231xx_info("%s: set ts1 registers", __func__); cx231xx_info("%s: set ts1 registers", __func__);
if (dev->board.has_417) { if (dev->board.has_417) {
@ -2569,7 +2569,7 @@ int cx231xx_initialize_stream_xfer(struct cx231xx *dev, u32 media_type)
} }
break; break;
case 6: /* ts1 parallel mode */ case TS1_parallel_mode:
cx231xx_info("%s: set ts1 parallel mode registers\n", cx231xx_info("%s: set ts1 parallel mode registers\n",
__func__); __func__);
status = cx231xx_mode_register(dev, TS_MODE_REG, 0x100); status = cx231xx_mode_register(dev, TS_MODE_REG, 0x100);
@ -2592,52 +2592,28 @@ int cx231xx_capture_start(struct cx231xx *dev, int start, u8 media_type)
/* get EP for media type */ /* get EP for media type */
pcb_config = (struct pcb_config *)&dev->current_pcb_config; pcb_config = (struct pcb_config *)&dev->current_pcb_config;
if (pcb_config->config_num == 1) { if (pcb_config->config_num) {
switch (media_type) { switch (media_type) {
case 0: /* Video */ case Raw_Video:
ep_mask = ENABLE_EP4; /* ep4 [00:1000] */ ep_mask = ENABLE_EP4; /* ep4 [00:1000] */
break; break;
case 1: /* Audio */ case Audio:
ep_mask = ENABLE_EP3; /* ep3 [00:0100] */ ep_mask = ENABLE_EP3; /* ep3 [00:0100] */
break; break;
case 2: /* Vbi */ case Vbi:
ep_mask = ENABLE_EP5; /* ep5 [01:0000] */ ep_mask = ENABLE_EP5; /* ep5 [01:0000] */
break; break;
case 3: /* Sliced_cc */ case Sliced_cc:
ep_mask = ENABLE_EP6; /* ep6 [10:0000] */ ep_mask = ENABLE_EP6; /* ep6 [10:0000] */
break; break;
case 4: /* ts1 */ case TS1_serial_mode:
case 6: /* ts1 parallel mode */ case TS1_parallel_mode:
ep_mask = ENABLE_EP1; /* ep1 [00:0001] */ ep_mask = ENABLE_EP1; /* ep1 [00:0001] */
break; break;
case 5: /* ts2 */ case TS2:
ep_mask = ENABLE_EP2; /* ep2 [00:0010] */ ep_mask = ENABLE_EP2; /* ep2 [00:0010] */
break; break;
} }
} else if (pcb_config->config_num > 1) {
switch (media_type) {
case 0: /* Video */
ep_mask = ENABLE_EP4; /* ep4 [00:1000] */
break;
case 1: /* Audio */
ep_mask = ENABLE_EP3; /* ep3 [00:0100] */
break;
case 2: /* Vbi */
ep_mask = ENABLE_EP5; /* ep5 [01:0000] */
break;
case 3: /* Sliced_cc */
ep_mask = ENABLE_EP6; /* ep6 [10:0000] */
break;
case 4: /* ts1 */
case 6: /* ts1 parallel mode */
ep_mask = ENABLE_EP1; /* ep1 [00:0001] */
break;
case 5: /* ts2 */
ep_mask = ENABLE_EP2; /* ep2 [00:0010] */
break;
}
} }
if (start) { if (start) {

View File

@ -1023,7 +1023,6 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
int nr = 0, ifnum; int nr = 0, ifnum;
int i, isoc_pipe = 0; int i, isoc_pipe = 0;
char *speed; char *speed;
char descr[255] = "";
struct usb_interface_assoc_descriptor *assoc_desc; struct usb_interface_assoc_descriptor *assoc_desc;
udev = usb_get_dev(interface_to_usbdev(interface)); udev = usb_get_dev(interface_to_usbdev(interface));
@ -1098,20 +1097,10 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
speed = "unknown"; speed = "unknown";
} }
if (udev->manufacturer) cx231xx_info("New device %s %s @ %s Mbps "
strlcpy(descr, udev->manufacturer, sizeof(descr));
if (udev->product) {
if (*descr)
strlcat(descr, " ", sizeof(descr));
strlcat(descr, udev->product, sizeof(descr));
}
if (*descr)
strlcat(descr, " ", sizeof(descr));
cx231xx_info("New device %s@ %s Mbps "
"(%04x:%04x) with %d interfaces\n", "(%04x:%04x) with %d interfaces\n",
descr, udev->manufacturer ? udev->manufacturer : "",
udev->product ? udev->product : "",
speed, speed,
le16_to_cpu(udev->descriptor.idVendor), le16_to_cpu(udev->descriptor.idVendor),
le16_to_cpu(udev->descriptor.idProduct), le16_to_cpu(udev->descriptor.idProduct),

View File

@ -585,13 +585,10 @@ static void snd_cx88_wm8775_volume_put(struct snd_kcontrol *kcontrol,
{ {
snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
struct cx88_core *core = chip->core; struct cx88_core *core = chip->core;
struct v4l2_control client_ctl;
int left = value->value.integer.value[0]; int left = value->value.integer.value[0];
int right = value->value.integer.value[1]; int right = value->value.integer.value[1];
int v, b; int v, b;
memset(&client_ctl, 0, sizeof(client_ctl));
/* Pass volume & balance onto any WM8775 */ /* Pass volume & balance onto any WM8775 */
if (left >= right) { if (left >= right) {
v = left << 10; v = left << 10;
@ -600,13 +597,8 @@ static void snd_cx88_wm8775_volume_put(struct snd_kcontrol *kcontrol,
v = right << 10; v = right << 10;
b = right ? 0xffff - (0x8000 * left) / right : 0x8000; b = right ? 0xffff - (0x8000 * left) / right : 0x8000;
} }
client_ctl.value = v; wm8775_s_ctrl(core, V4L2_CID_AUDIO_VOLUME, v);
client_ctl.id = V4L2_CID_AUDIO_VOLUME; wm8775_s_ctrl(core, V4L2_CID_AUDIO_BALANCE, b);
call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
client_ctl.value = b;
client_ctl.id = V4L2_CID_AUDIO_BALANCE;
call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
} }
/* OK - TODO: test it */ /* OK - TODO: test it */
@ -687,14 +679,8 @@ static int snd_cx88_switch_put(struct snd_kcontrol *kcontrol,
cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, vol); cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, vol);
/* Pass mute onto any WM8775 */ /* Pass mute onto any WM8775 */
if ((core->board.audio_chip == V4L2_IDENT_WM8775) && if ((core->board.audio_chip == V4L2_IDENT_WM8775) &&
((1<<6) == bit)) { ((1<<6) == bit))
struct v4l2_control client_ctl; wm8775_s_ctrl(core, V4L2_CID_AUDIO_MUTE, 0 != (vol & bit));
memset(&client_ctl, 0, sizeof(client_ctl));
client_ctl.value = 0 != (vol & bit);
client_ctl.id = V4L2_CID_AUDIO_MUTE;
call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
}
ret = 1; ret = 1;
} }
spin_unlock_irq(&chip->reg_lock); spin_unlock_irq(&chip->reg_lock);
@ -724,13 +710,10 @@ static int snd_cx88_alc_get(struct snd_kcontrol *kcontrol,
{ {
snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
struct cx88_core *core = chip->core; struct cx88_core *core = chip->core;
struct v4l2_control client_ctl; s32 val;
memset(&client_ctl, 0, sizeof(client_ctl));
client_ctl.id = V4L2_CID_AUDIO_LOUDNESS;
call_hw(core, WM8775_GID, core, g_ctrl, &client_ctl);
value->value.integer.value[0] = client_ctl.value ? 1 : 0;
val = wm8775_g_ctrl(core, V4L2_CID_AUDIO_LOUDNESS);
value->value.integer.value[0] = val ? 1 : 0;
return 0; return 0;
} }

View File

@ -35,6 +35,7 @@
#include <linux/firmware.h> #include <linux/firmware.h>
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h> #include <media/v4l2-ioctl.h>
#include <media/v4l2-event.h>
#include <media/cx2341x.h> #include <media/cx2341x.h>
#include "cx88.h" #include "cx88.h"
@ -523,11 +524,10 @@ static void blackbird_codec_settings(struct cx8802_dev *dev)
blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0, blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
dev->height, dev->width); dev->height, dev->width);
dev->params.width = dev->width; dev->cxhdl.width = dev->width;
dev->params.height = dev->height; dev->cxhdl.height = dev->height;
dev->params.is_50hz = (dev->core->tvnorm & V4L2_STD_625_50) != 0; cx2341x_handler_set_50hz(&dev->cxhdl, dev->core->tvnorm & V4L2_STD_625_50);
cx2341x_handler_setup(&dev->cxhdl);
cx2341x_update(dev, blackbird_mbox_func, NULL, &dev->params);
} }
static int blackbird_initialize_codec(struct cx8802_dev *dev) static int blackbird_initialize_codec(struct cx8802_dev *dev)
@ -618,6 +618,8 @@ static int blackbird_start_codec(struct file *file, void *priv)
/* initialize the video input */ /* initialize the video input */
blackbird_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0); blackbird_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0);
cx2341x_handler_set_busy(&dev->cxhdl, 1);
/* start capturing to the host interface */ /* start capturing to the host interface */
blackbird_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0, blackbird_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0,
BLACKBIRD_MPEG_CAPTURE, BLACKBIRD_MPEG_CAPTURE,
@ -636,6 +638,8 @@ static int blackbird_stop_codec(struct cx8802_dev *dev)
BLACKBIRD_RAW_BITS_NONE BLACKBIRD_RAW_BITS_NONE
); );
cx2341x_handler_set_busy(&dev->cxhdl, 0);
dev->mpeg_active = 0; dev->mpeg_active = 0;
return 0; return 0;
} }
@ -685,58 +689,15 @@ static struct videobuf_queue_ops blackbird_qops = {
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
static const u32 *ctrl_classes[] = { static int vidioc_querycap(struct file *file, void *priv,
cx88_user_ctrls,
cx2341x_mpeg_ctrls,
NULL
};
static int blackbird_queryctrl(struct cx8802_dev *dev, struct v4l2_queryctrl *qctrl)
{
qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
if (qctrl->id == 0)
return -EINVAL;
/* Standard V4L2 controls */
if (cx8800_ctrl_query(dev->core, qctrl) == 0)
return 0;
/* MPEG V4L2 controls */
if (cx2341x_ctrl_query(&dev->params, qctrl))
qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
return 0;
}
/* ------------------------------------------------------------------ */
/* IOCTL Handlers */
static int vidioc_querymenu (struct file *file, void *priv,
struct v4l2_querymenu *qmenu)
{
struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
struct v4l2_queryctrl qctrl;
qctrl.id = qmenu->id;
blackbird_queryctrl(dev, &qctrl);
return v4l2_ctrl_query_menu(qmenu, &qctrl,
cx2341x_ctrl_get_menu(&dev->params, qmenu->id));
}
static int vidioc_querycap (struct file *file, void *priv,
struct v4l2_capability *cap) struct v4l2_capability *cap)
{ {
struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev; struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
struct cx88_core *core = dev->core; struct cx88_core *core = dev->core;
strcpy(cap->driver, "cx88_blackbird"); strcpy(cap->driver, "cx88_blackbird");
strlcpy(cap->card, core->board.name, sizeof(cap->card)); sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci)); cx88_querycap(file, core, cap);
cap->capabilities =
V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING;
if (UNSET != core->board.tuner_type)
cap->capabilities |= V4L2_CAP_TUNER;
return 0; return 0;
} }
@ -748,6 +709,7 @@ static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv,
strlcpy(f->description, "MPEG", sizeof(f->description)); strlcpy(f->description, "MPEG", sizeof(f->description));
f->pixelformat = V4L2_PIX_FMT_MPEG; f->pixelformat = V4L2_PIX_FMT_MPEG;
f->flags = V4L2_FMT_FLAG_COMPRESSED;
return 0; return 0;
} }
@ -759,12 +721,12 @@ static int vidioc_g_fmt_vid_cap (struct file *file, void *priv,
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.bytesperline = 0; f->fmt.pix.bytesperline = 0;
f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */ f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */;
f->fmt.pix.colorspace = 0; f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
f->fmt.pix.width = dev->width; f->fmt.pix.width = dev->width;
f->fmt.pix.height = dev->height; f->fmt.pix.height = dev->height;
f->fmt.pix.field = fh->mpegq.field; f->fmt.pix.field = fh->mpegq.field;
dprintk(0,"VIDIOC_G_FMT: w: %d, h: %d, f: %d\n", dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
dev->width, dev->height, fh->mpegq.field ); dev->width, dev->height, fh->mpegq.field );
return 0; return 0;
} }
@ -777,9 +739,9 @@ static int vidioc_try_fmt_vid_cap (struct file *file, void *priv,
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.bytesperline = 0; f->fmt.pix.bytesperline = 0;
f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */; f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */;
f->fmt.pix.colorspace = 0; f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
dprintk(0,"VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n", dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
dev->width, dev->height, fh->mpegq.field ); dev->width, dev->height, fh->mpegq.field );
return 0; return 0;
} }
@ -793,15 +755,15 @@ static int vidioc_s_fmt_vid_cap (struct file *file, void *priv,
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.bytesperline = 0; f->fmt.pix.bytesperline = 0;
f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; /* 188 * 4 * 1024; */; f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */;
f->fmt.pix.colorspace = 0; f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
dev->width = f->fmt.pix.width; dev->width = f->fmt.pix.width;
dev->height = f->fmt.pix.height; dev->height = f->fmt.pix.height;
fh->mpegq.field = f->fmt.pix.field; fh->mpegq.field = f->fmt.pix.field;
cx88_set_scale(core, f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field); cx88_set_scale(core, f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0, blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
f->fmt.pix.height, f->fmt.pix.width); f->fmt.pix.height, f->fmt.pix.width);
dprintk(0,"VIDIOC_S_FMT: w: %d, h: %d, f: %d\n", dprintk(1, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field ); f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field );
return 0; return 0;
} }
@ -834,60 +796,21 @@ static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p)
static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
{ {
struct cx8802_fh *fh = priv; struct cx8802_fh *fh = priv;
struct cx8802_dev *dev = fh->dev;
if (!dev->mpeg_active)
blackbird_start_codec(file, fh);
return videobuf_streamon(&fh->mpegq); return videobuf_streamon(&fh->mpegq);
} }
static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
{ {
struct cx8802_fh *fh = priv; struct cx8802_fh *fh = priv;
return videobuf_streamoff(&fh->mpegq); struct cx8802_dev *dev = fh->dev;
}
static int vidioc_g_ext_ctrls (struct file *file, void *priv,
struct v4l2_ext_controls *f)
{
struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
return -EINVAL;
return cx2341x_ext_ctrls(&dev->params, 0, f, VIDIOC_G_EXT_CTRLS);
}
static int vidioc_s_ext_ctrls (struct file *file, void *priv,
struct v4l2_ext_controls *f)
{
struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
struct cx2341x_mpeg_params p;
int err;
if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
return -EINVAL;
if (dev->mpeg_active) if (dev->mpeg_active)
blackbird_stop_codec(dev); blackbird_stop_codec(dev);
return videobuf_streamoff(&fh->mpegq);
p = dev->params;
err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_S_EXT_CTRLS);
if (!err) {
err = cx2341x_update(dev, blackbird_mbox_func, &dev->params, &p);
dev->params = p;
}
return err;
}
static int vidioc_try_ext_ctrls (struct file *file, void *priv,
struct v4l2_ext_controls *f)
{
struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
struct cx2341x_mpeg_params p;
int err;
if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
return -EINVAL;
p = dev->params;
err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_TRY_EXT_CTRLS);
return err;
} }
static int vidioc_s_frequency (struct file *file, void *priv, static int vidioc_s_frequency (struct file *file, void *priv,
@ -897,6 +820,10 @@ static int vidioc_s_frequency (struct file *file, void *priv,
struct cx8802_dev *dev = fh->dev; struct cx8802_dev *dev = fh->dev;
struct cx88_core *core = dev->core; struct cx88_core *core = dev->core;
if (unlikely(UNSET == core->board.tuner_type))
return -EINVAL;
if (unlikely(f->tuner != 0))
return -EINVAL;
if (dev->mpeg_active) if (dev->mpeg_active)
blackbird_stop_codec(dev); blackbird_stop_codec(dev);
@ -914,29 +841,11 @@ static int vidioc_log_status (struct file *file, void *priv)
char name[32 + 2]; char name[32 + 2];
snprintf(name, sizeof(name), "%s/2", core->name); snprintf(name, sizeof(name), "%s/2", core->name);
printk("%s/2: ============ START LOG STATUS ============\n",
core->name);
call_all(core, core, log_status); call_all(core, core, log_status);
cx2341x_log_status(&dev->params, name); v4l2_ctrl_handler_log_status(&dev->cxhdl.hdl, name);
printk("%s/2: ============= END LOG STATUS =============\n",
core->name);
return 0; return 0;
} }
static int vidioc_queryctrl (struct file *file, void *priv,
struct v4l2_queryctrl *qctrl)
{
struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
if (blackbird_queryctrl(dev, qctrl) == 0)
return 0;
qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
if (unlikely(qctrl->id == 0))
return -EINVAL;
return cx8800_ctrl_query(dev->core, qctrl);
}
static int vidioc_enum_input (struct file *file, void *priv, static int vidioc_enum_input (struct file *file, void *priv,
struct v4l2_input *i) struct v4l2_input *i)
{ {
@ -944,22 +853,6 @@ static int vidioc_enum_input (struct file *file, void *priv,
return cx88_enum_input (core,i); return cx88_enum_input (core,i);
} }
static int vidioc_g_ctrl (struct file *file, void *priv,
struct v4l2_control *ctl)
{
struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
return
cx88_get_control(core,ctl);
}
static int vidioc_s_ctrl (struct file *file, void *priv,
struct v4l2_control *ctl)
{
struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
return
cx88_set_control(core,ctl);
}
static int vidioc_g_frequency (struct file *file, void *priv, static int vidioc_g_frequency (struct file *file, void *priv,
struct v4l2_frequency *f) struct v4l2_frequency *f)
{ {
@ -968,8 +861,9 @@ static int vidioc_g_frequency (struct file *file, void *priv,
if (unlikely(UNSET == core->board.tuner_type)) if (unlikely(UNSET == core->board.tuner_type))
return -EINVAL; return -EINVAL;
if (unlikely(f->tuner != 0))
return -EINVAL;
f->type = V4L2_TUNER_ANALOG_TV;
f->frequency = core->freq; f->frequency = core->freq;
call_all(core, tuner, g_frequency, f); call_all(core, tuner, g_frequency, f);
@ -990,6 +884,8 @@ static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
if (i >= 4) if (i >= 4)
return -EINVAL; return -EINVAL;
if (0 == INPUT(i).type)
return -EINVAL;
mutex_lock(&core->lock); mutex_lock(&core->lock);
cx88_newstation(core); cx88_newstation(core);
@ -1010,9 +906,9 @@ static int vidioc_g_tuner (struct file *file, void *priv,
return -EINVAL; return -EINVAL;
strcpy(t->name, "Television"); strcpy(t->name, "Television");
t->type = V4L2_TUNER_ANALOG_TV;
t->capability = V4L2_TUNER_CAP_NORM; t->capability = V4L2_TUNER_CAP_NORM;
t->rangehigh = 0xffffffffUL; t->rangehigh = 0xffffffffUL;
call_all(core, tuner, g_tuner, t);
cx88_get_stereo(core ,t); cx88_get_stereo(core ,t);
reg = cx_read(MO_DEVICE_STATUS); reg = cx_read(MO_DEVICE_STATUS);
@ -1034,6 +930,14 @@ static int vidioc_s_tuner (struct file *file, void *priv,
return 0; return 0;
} }
static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm)
{
struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
*tvnorm = core->tvnorm;
return 0;
}
static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id) static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id)
{ {
struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
@ -1087,6 +991,7 @@ static int mpeg_open(struct file *file)
mutex_unlock(&dev->core->lock); mutex_unlock(&dev->core->lock);
return -ENOMEM; return -ENOMEM;
} }
v4l2_fh_init(&fh->fh, vdev);
file->private_data = fh; file->private_data = fh;
fh->dev = dev; fh->dev = dev;
@ -1103,6 +1008,7 @@ static int mpeg_open(struct file *file)
dev->core->mpeg_users++; dev->core->mpeg_users++;
mutex_unlock(&dev->core->lock); mutex_unlock(&dev->core->lock);
v4l2_fh_add(&fh->fh);
return 0; return 0;
} }
@ -1123,6 +1029,8 @@ static int mpeg_release(struct file *file)
videobuf_mmap_free(&fh->mpegq); videobuf_mmap_free(&fh->mpegq);
v4l2_fh_del(&fh->fh);
v4l2_fh_exit(&fh->fh);
file->private_data = NULL; file->private_data = NULL;
kfree(fh); kfree(fh);
@ -1155,13 +1063,14 @@ mpeg_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
static unsigned int static unsigned int
mpeg_poll(struct file *file, struct poll_table_struct *wait) mpeg_poll(struct file *file, struct poll_table_struct *wait)
{ {
unsigned long req_events = poll_requested_events(wait);
struct cx8802_fh *fh = file->private_data; struct cx8802_fh *fh = file->private_data;
struct cx8802_dev *dev = fh->dev; struct cx8802_dev *dev = fh->dev;
if (!dev->mpeg_active) if (!dev->mpeg_active && (req_events & (POLLIN | POLLRDNORM)))
blackbird_start_codec(file, fh); blackbird_start_codec(file, fh);
return videobuf_poll_stream(file, &fh->mpegq, wait); return v4l2_ctrl_poll(file, wait) | videobuf_poll_stream(file, &fh->mpegq, wait);
} }
static int static int
@ -1180,11 +1089,10 @@ static const struct v4l2_file_operations mpeg_fops =
.read = mpeg_read, .read = mpeg_read,
.poll = mpeg_poll, .poll = mpeg_poll,
.mmap = mpeg_mmap, .mmap = mpeg_mmap,
.ioctl = video_ioctl2, .unlocked_ioctl = video_ioctl2,
}; };
static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
.vidioc_querymenu = vidioc_querymenu,
.vidioc_querycap = vidioc_querycap, .vidioc_querycap = vidioc_querycap,
.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
.vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
@ -1196,21 +1104,18 @@ static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
.vidioc_dqbuf = vidioc_dqbuf, .vidioc_dqbuf = vidioc_dqbuf,
.vidioc_streamon = vidioc_streamon, .vidioc_streamon = vidioc_streamon,
.vidioc_streamoff = vidioc_streamoff, .vidioc_streamoff = vidioc_streamoff,
.vidioc_g_ext_ctrls = vidioc_g_ext_ctrls,
.vidioc_s_ext_ctrls = vidioc_s_ext_ctrls,
.vidioc_try_ext_ctrls = vidioc_try_ext_ctrls,
.vidioc_s_frequency = vidioc_s_frequency, .vidioc_s_frequency = vidioc_s_frequency,
.vidioc_log_status = vidioc_log_status, .vidioc_log_status = vidioc_log_status,
.vidioc_queryctrl = vidioc_queryctrl,
.vidioc_enum_input = vidioc_enum_input, .vidioc_enum_input = vidioc_enum_input,
.vidioc_g_ctrl = vidioc_g_ctrl,
.vidioc_s_ctrl = vidioc_s_ctrl,
.vidioc_g_frequency = vidioc_g_frequency, .vidioc_g_frequency = vidioc_g_frequency,
.vidioc_g_input = vidioc_g_input, .vidioc_g_input = vidioc_g_input,
.vidioc_s_input = vidioc_s_input, .vidioc_s_input = vidioc_s_input,
.vidioc_g_tuner = vidioc_g_tuner, .vidioc_g_tuner = vidioc_g_tuner,
.vidioc_s_tuner = vidioc_s_tuner, .vidioc_s_tuner = vidioc_s_tuner,
.vidioc_g_std = vidioc_g_std,
.vidioc_s_std = vidioc_s_std, .vidioc_s_std = vidioc_s_std,
.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
}; };
static struct video_device cx8802_mpeg_template = { static struct video_device cx8802_mpeg_template = {
@ -1218,7 +1123,6 @@ static struct video_device cx8802_mpeg_template = {
.fops = &mpeg_fops, .fops = &mpeg_fops,
.ioctl_ops = &mpeg_ioctl_ops, .ioctl_ops = &mpeg_ioctl_ops,
.tvnorms = CX88_NORMS, .tvnorms = CX88_NORMS,
.current_norm = V4L2_STD_NTSC_M,
}; };
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
@ -1286,6 +1190,7 @@ static int blackbird_register_video(struct cx8802_dev *dev)
dev->mpeg_dev = cx88_vdev_init(dev->core,dev->pci, dev->mpeg_dev = cx88_vdev_init(dev->core,dev->pci,
&cx8802_mpeg_template,"mpeg"); &cx8802_mpeg_template,"mpeg");
dev->mpeg_dev->ctrl_handler = &dev->cxhdl.hdl;
video_set_drvdata(dev->mpeg_dev, dev); video_set_drvdata(dev->mpeg_dev, dev);
err = video_register_device(dev->mpeg_dev,VFL_TYPE_GRABBER, -1); err = video_register_device(dev->mpeg_dev,VFL_TYPE_GRABBER, -1);
if (err < 0) { if (err < 0) {
@ -1318,17 +1223,20 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv)
goto fail_core; goto fail_core;
dev->width = 720; dev->width = 720;
dev->height = 576;
cx2341x_fill_defaults(&dev->params);
dev->params.port = CX2341X_PORT_STREAMING;
cx8802_mpeg_template.current_norm = core->tvnorm;
if (core->tvnorm & V4L2_STD_525_60) { if (core->tvnorm & V4L2_STD_525_60) {
dev->height = 480; dev->height = 480;
} else { } else {
dev->height = 576; dev->height = 576;
} }
dev->cxhdl.port = CX2341X_PORT_STREAMING;
dev->cxhdl.width = dev->width;
dev->cxhdl.height = dev->height;
dev->cxhdl.func = blackbird_mbox_func;
dev->cxhdl.priv = dev;
err = cx2341x_handler_init(&dev->cxhdl, 36);
if (err)
goto fail_core;
v4l2_ctrl_add_handler(&dev->cxhdl.hdl, &core->video_hdl);
/* blackbird stuff */ /* blackbird stuff */
printk("%s/2: cx23416 based mpeg encoder (blackbird reference design)\n", printk("%s/2: cx23416 based mpeg encoder (blackbird reference design)\n",
@ -1336,12 +1244,14 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv)
host_setup(dev->core); host_setup(dev->core);
blackbird_initialize_codec(dev); blackbird_initialize_codec(dev);
blackbird_register_video(dev);
/* initial device configuration: needed ? */ /* initial device configuration: needed ? */
// init_controls(core); // init_controls(core);
cx88_set_tvnorm(core,core->tvnorm); cx88_set_tvnorm(core,core->tvnorm);
cx88_video_mux(core,0); cx88_video_mux(core,0);
cx2341x_handler_set_50hz(&dev->cxhdl, dev->height == 576);
cx2341x_handler_setup(&dev->cxhdl);
blackbird_register_video(dev);
return 0; return 0;
@ -1351,8 +1261,12 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv)
static int cx8802_blackbird_remove(struct cx8802_driver *drv) static int cx8802_blackbird_remove(struct cx8802_driver *drv)
{ {
struct cx88_core *core = drv->core;
struct cx8802_dev *dev = core->dvbdev;
/* blackbird */ /* blackbird */
blackbird_unregister_video(drv->core->dvbdev); blackbird_unregister_video(drv->core->dvbdev);
v4l2_ctrl_handler_free(&dev->cxhdl.hdl);
return 0; return 0;
} }

View File

@ -3693,7 +3693,22 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
return NULL; return NULL;
} }
if (v4l2_ctrl_handler_init(&core->video_hdl, 13)) {
v4l2_device_unregister(&core->v4l2_dev);
kfree(core);
return NULL;
}
if (v4l2_ctrl_handler_init(&core->audio_hdl, 13)) {
v4l2_ctrl_handler_free(&core->video_hdl);
v4l2_device_unregister(&core->v4l2_dev);
kfree(core);
return NULL;
}
if (0 != cx88_get_resources(core, pci)) { if (0 != cx88_get_resources(core, pci)) {
v4l2_ctrl_handler_free(&core->video_hdl);
v4l2_ctrl_handler_free(&core->audio_hdl);
v4l2_device_unregister(&core->v4l2_dev); v4l2_device_unregister(&core->v4l2_dev);
kfree(core); kfree(core);
return NULL; return NULL;
@ -3706,6 +3721,11 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
core->bmmio = (u8 __iomem *)core->lmmio; core->bmmio = (u8 __iomem *)core->lmmio;
if (core->lmmio == NULL) { if (core->lmmio == NULL) {
release_mem_region(pci_resource_start(pci, 0),
pci_resource_len(pci, 0));
v4l2_ctrl_handler_free(&core->video_hdl);
v4l2_ctrl_handler_free(&core->audio_hdl);
v4l2_device_unregister(&core->v4l2_dev);
kfree(core); kfree(core);
return NULL; return NULL;
} }

View File

@ -1012,6 +1012,9 @@ int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm)
// tell i2c chips // tell i2c chips
call_all(core, core, s_std, norm); call_all(core, core, s_std, norm);
/* The chroma_agc control should be inaccessible if the video format is SECAM */
v4l2_ctrl_grab(core->chroma_agc, cxiformat == VideoFormatSECAM);
// done // done
return 0; return 0;
} }
@ -1030,10 +1033,10 @@ struct video_device *cx88_vdev_init(struct cx88_core *core,
return NULL; return NULL;
*vfd = *template_; *vfd = *template_;
vfd->v4l2_dev = &core->v4l2_dev; vfd->v4l2_dev = &core->v4l2_dev;
vfd->parent = &pci->dev;
vfd->release = video_device_release; vfd->release = video_device_release;
snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
core->name, type, core->board.name); core->name, type, core->board.name);
set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
return vfd; return vfd;
} }
@ -1086,6 +1089,8 @@ void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
iounmap(core->lmmio); iounmap(core->lmmio);
cx88_devcount--; cx88_devcount--;
mutex_unlock(&devlist); mutex_unlock(&devlist);
v4l2_ctrl_handler_free(&core->video_hdl);
v4l2_ctrl_handler_free(&core->audio_hdl);
v4l2_device_unregister(&core->v4l2_dev); v4l2_device_unregister(&core->v4l2_dev);
kfree(core); kfree(core);
} }

File diff suppressed because it is too large Load Diff

View File

@ -26,6 +26,7 @@
#include <linux/kdev_t.h> #include <linux/kdev_t.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-fh.h>
#include <media/tuner.h> #include <media/tuner.h>
#include <media/tveeprom.h> #include <media/tveeprom.h>
#include <media/videobuf-dma-sg.h> #include <media/videobuf-dma-sg.h>
@ -115,15 +116,6 @@ struct cx8800_fmt {
u32 cxformat; u32 cxformat;
}; };
struct cx88_ctrl {
struct v4l2_queryctrl v;
u32 off;
u32 reg;
u32 sreg;
u32 mask;
u32 shift;
};
/* ----------------------------------------------------------- */ /* ----------------------------------------------------------- */
/* SRAM memory management data (see cx88-core.c) */ /* SRAM memory management data (see cx88-core.c) */
@ -359,6 +351,10 @@ struct cx88_core {
/* config info -- analog */ /* config info -- analog */
struct v4l2_device v4l2_dev; struct v4l2_device v4l2_dev;
struct v4l2_ctrl_handler video_hdl;
struct v4l2_ctrl *chroma_agc;
struct v4l2_ctrl_handler audio_hdl;
struct v4l2_subdev *sd_wm8775;
struct i2c_client *i2c_rtc; struct i2c_client *i2c_rtc;
unsigned int boardnr; unsigned int boardnr;
struct cx88_board board; struct cx88_board board;
@ -409,8 +405,6 @@ static inline struct cx88_core *to_core(struct v4l2_device *v4l2_dev)
return container_of(v4l2_dev, struct cx88_core, v4l2_dev); return container_of(v4l2_dev, struct cx88_core, v4l2_dev);
} }
#define WM8775_GID (1 << 0)
#define call_hw(core, grpid, o, f, args...) \ #define call_hw(core, grpid, o, f, args...) \
do { \ do { \
if (!core->i2c_rc) { \ if (!core->i2c_rc) { \
@ -424,6 +418,36 @@ static inline struct cx88_core *to_core(struct v4l2_device *v4l2_dev)
#define call_all(core, o, f, args...) call_hw(core, 0, o, f, ##args) #define call_all(core, o, f, args...) call_hw(core, 0, o, f, ##args)
#define WM8775_GID (1 << 0)
#define wm8775_s_ctrl(core, id, val) \
do { \
struct v4l2_ctrl *ctrl_ = \
v4l2_ctrl_find(core->sd_wm8775->ctrl_handler, id); \
if (ctrl_ && !core->i2c_rc) { \
if (core->gate_ctrl) \
core->gate_ctrl(core, 1); \
v4l2_ctrl_s_ctrl(ctrl_, val); \
if (core->gate_ctrl) \
core->gate_ctrl(core, 0); \
} \
} while (0)
#define wm8775_g_ctrl(core, id) \
({ \
struct v4l2_ctrl *ctrl_ = \
v4l2_ctrl_find(core->sd_wm8775->ctrl_handler, id); \
s32 val = 0; \
if (ctrl_ && !core->i2c_rc) { \
if (core->gate_ctrl) \
core->gate_ctrl(core, 1); \
val = v4l2_ctrl_g_ctrl(ctrl_); \
if (core->gate_ctrl) \
core->gate_ctrl(core, 0); \
} \
val; \
})
struct cx8800_dev; struct cx8800_dev;
struct cx8802_dev; struct cx8802_dev;
@ -431,19 +455,11 @@ struct cx8802_dev;
/* function 0: video stuff */ /* function 0: video stuff */
struct cx8800_fh { struct cx8800_fh {
struct v4l2_fh fh;
struct cx8800_dev *dev; struct cx8800_dev *dev;
enum v4l2_buf_type type;
int radio;
unsigned int resources; unsigned int resources;
/* video overlay */
struct v4l2_window win;
struct v4l2_clip *clips;
unsigned int nclips;
/* video capture */ /* video capture */
const struct cx8800_fmt *fmt;
unsigned int width,height;
struct videobuf_queue vidq; struct videobuf_queue vidq;
/* vbi capture */ /* vbi capture */
@ -468,6 +484,8 @@ struct cx8800_dev {
struct pci_dev *pci; struct pci_dev *pci;
unsigned char pci_rev,pci_lat; unsigned char pci_rev,pci_lat;
const struct cx8800_fmt *fmt;
unsigned int width, height;
/* capture queues */ /* capture queues */
struct cx88_dmaqueue vidq; struct cx88_dmaqueue vidq;
@ -488,6 +506,7 @@ struct cx8800_dev {
/* function 2: mpeg stuff */ /* function 2: mpeg stuff */
struct cx8802_fh { struct cx8802_fh {
struct v4l2_fh fh;
struct cx8802_dev *dev; struct cx8802_dev *dev;
struct videobuf_queue mpegq; struct videobuf_queue mpegq;
}; };
@ -552,7 +571,7 @@ struct cx8802_dev {
unsigned char mpeg_active; /* nonzero if mpeg encoder is active */ unsigned char mpeg_active; /* nonzero if mpeg encoder is active */
/* mpeg params */ /* mpeg params */
struct cx2341x_mpeg_params params; struct cx2341x_handler cxhdl;
#endif #endif
#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE) #if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)
@ -722,11 +741,8 @@ void cx8802_cancel_buffers(struct cx8802_dev *dev);
/* ----------------------------------------------------------- */ /* ----------------------------------------------------------- */
/* cx88-video.c*/ /* cx88-video.c*/
extern const u32 cx88_user_ctrls[];
extern int cx8800_ctrl_query(struct cx88_core *core,
struct v4l2_queryctrl *qctrl);
int cx88_enum_input (struct cx88_core *core,struct v4l2_input *i); int cx88_enum_input (struct cx88_core *core,struct v4l2_input *i);
int cx88_set_freq (struct cx88_core *core,struct v4l2_frequency *f); int cx88_set_freq (struct cx88_core *core,struct v4l2_frequency *f);
int cx88_get_control(struct cx88_core *core, struct v4l2_control *ctl);
int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl);
int cx88_video_mux(struct cx88_core *core, unsigned int input); int cx88_video_mux(struct cx88_core *core, unsigned int input);
void cx88_querycap(struct file *file, struct cx88_core *core,
struct v4l2_capability *cap);

View File

@ -42,6 +42,7 @@
#include <sound/initval.h> #include <sound/initval.h>
#include <sound/control.h> #include <sound/control.h>
#include <sound/tlv.h> #include <sound/tlv.h>
#include <sound/ac97_codec.h>
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include "em28xx.h" #include "em28xx.h"
@ -679,19 +680,19 @@ static int em28xx_audio_init(struct em28xx *dev)
INIT_WORK(&dev->wq_trigger, audio_trigger); INIT_WORK(&dev->wq_trigger, audio_trigger);
if (dev->audio_mode.ac97 != EM28XX_NO_AC97) { if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
em28xx_cvol_new(card, dev, "Video", AC97_VIDEO_VOL); em28xx_cvol_new(card, dev, "Video", AC97_VIDEO);
em28xx_cvol_new(card, dev, "Line In", AC97_LINEIN_VOL); em28xx_cvol_new(card, dev, "Line In", AC97_LINE);
em28xx_cvol_new(card, dev, "Phone", AC97_PHONE_VOL); em28xx_cvol_new(card, dev, "Phone", AC97_PHONE);
em28xx_cvol_new(card, dev, "Microphone", AC97_PHONE_VOL); em28xx_cvol_new(card, dev, "Microphone", AC97_MIC);
em28xx_cvol_new(card, dev, "CD", AC97_CD_VOL); em28xx_cvol_new(card, dev, "CD", AC97_CD);
em28xx_cvol_new(card, dev, "AUX", AC97_AUX_VOL); em28xx_cvol_new(card, dev, "AUX", AC97_AUX);
em28xx_cvol_new(card, dev, "PCM", AC97_PCM_OUT_VOL); em28xx_cvol_new(card, dev, "PCM", AC97_PCM);
em28xx_cvol_new(card, dev, "Master", AC97_MASTER_VOL); em28xx_cvol_new(card, dev, "Master", AC97_MASTER);
em28xx_cvol_new(card, dev, "Line", AC97_LINE_LEVEL_VOL); em28xx_cvol_new(card, dev, "Line", AC97_HEADPHONE);
em28xx_cvol_new(card, dev, "Mono", AC97_MASTER_MONO_VOL); em28xx_cvol_new(card, dev, "Mono", AC97_MASTER_MONO);
em28xx_cvol_new(card, dev, "LFE", AC97_LFE_MASTER_VOL); em28xx_cvol_new(card, dev, "LFE", AC97_CENTER_LFE_MASTER);
em28xx_cvol_new(card, dev, "Surround", AC97_SURR_MASTER_VOL); em28xx_cvol_new(card, dev, "Surround", AC97_SURROUND_MASTER);
} }
err = snd_card_register(card); err = snd_card_register(card);

View File

@ -975,12 +975,7 @@ struct em28xx_board em28xx_boards[] = {
.name = "Terratec Cinergy HTC Stick", .name = "Terratec Cinergy HTC Stick",
.has_dvb = 1, .has_dvb = 1,
.ir_codes = RC_MAP_NEC_TERRATEC_CINERGY_XS, .ir_codes = RC_MAP_NEC_TERRATEC_CINERGY_XS,
#if 0 .tuner_type = TUNER_ABSENT,
.tuner_type = TUNER_PHILIPS_TDA8290,
.tuner_addr = 0x41,
.dvb_gpio = terratec_h5_digital, /* FIXME: probably wrong */
.tuner_gpio = terratec_h5_gpio,
#endif
.i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT |
EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_CLK_WAIT_ENABLE |
EM28XX_I2C_FREQ_400_KHZ, EM28XX_I2C_FREQ_400_KHZ,

View File

@ -27,6 +27,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <sound/ac97_codec.h>
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include "em28xx.h" #include "em28xx.h"
@ -326,13 +327,13 @@ struct em28xx_vol_itable {
}; };
static struct em28xx_vol_itable inputs[] = { static struct em28xx_vol_itable inputs[] = {
{ EM28XX_AMUX_VIDEO, AC97_VIDEO_VOL }, { EM28XX_AMUX_VIDEO, AC97_VIDEO },
{ EM28XX_AMUX_LINE_IN, AC97_LINEIN_VOL }, { EM28XX_AMUX_LINE_IN, AC97_LINE },
{ EM28XX_AMUX_PHONE, AC97_PHONE_VOL }, { EM28XX_AMUX_PHONE, AC97_PHONE },
{ EM28XX_AMUX_MIC, AC97_MIC_VOL }, { EM28XX_AMUX_MIC, AC97_MIC },
{ EM28XX_AMUX_CD, AC97_CD_VOL }, { EM28XX_AMUX_CD, AC97_CD },
{ EM28XX_AMUX_AUX, AC97_AUX_VOL }, { EM28XX_AMUX_AUX, AC97_AUX },
{ EM28XX_AMUX_PCM_OUT, AC97_PCM_OUT_VOL }, { EM28XX_AMUX_PCM_OUT, AC97_PCM },
}; };
static int set_ac97_input(struct em28xx *dev) static int set_ac97_input(struct em28xx *dev)
@ -415,11 +416,11 @@ struct em28xx_vol_otable {
}; };
static const struct em28xx_vol_otable outputs[] = { static const struct em28xx_vol_otable outputs[] = {
{ EM28XX_AOUT_MASTER, AC97_MASTER_VOL }, { EM28XX_AOUT_MASTER, AC97_MASTER },
{ EM28XX_AOUT_LINE, AC97_LINE_LEVEL_VOL }, { EM28XX_AOUT_LINE, AC97_HEADPHONE },
{ EM28XX_AOUT_MONO, AC97_MASTER_MONO_VOL }, { EM28XX_AOUT_MONO, AC97_MASTER_MONO },
{ EM28XX_AOUT_LFE, AC97_LFE_MASTER_VOL }, { EM28XX_AOUT_LFE, AC97_CENTER_LFE_MASTER },
{ EM28XX_AOUT_SURR, AC97_SURR_MASTER_VOL }, { EM28XX_AOUT_SURR, AC97_SURROUND_MASTER },
}; };
int em28xx_audio_analog_set(struct em28xx *dev) int em28xx_audio_analog_set(struct em28xx *dev)
@ -459,9 +460,9 @@ int em28xx_audio_analog_set(struct em28xx *dev)
if (dev->audio_mode.ac97 != EM28XX_NO_AC97) { if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
int vol; int vol;
em28xx_write_ac97(dev, AC97_POWER_DOWN_CTRL, 0x4200); em28xx_write_ac97(dev, AC97_POWERDOWN, 0x4200);
em28xx_write_ac97(dev, AC97_EXT_AUD_CTRL, 0x0031); em28xx_write_ac97(dev, AC97_EXTENDED_STATUS, 0x0031);
em28xx_write_ac97(dev, AC97_PCM_IN_SRATE, 0xbb80); em28xx_write_ac97(dev, AC97_PCM_LR_ADC_RATE, 0xbb80);
/* LSB: left channel - both channels with the same level */ /* LSB: left channel - both channels with the same level */
vol = (0x1f - dev->volume) | ((0x1f - dev->volume) << 8); vol = (0x1f - dev->volume) | ((0x1f - dev->volume) << 8);
@ -487,7 +488,7 @@ int em28xx_audio_analog_set(struct em28xx *dev)
channels */ channels */
sel |= (sel << 8); sel |= (sel << 8);
em28xx_write_ac97(dev, AC97_RECORD_SELECT, sel); em28xx_write_ac97(dev, AC97_REC_SEL, sel);
} }
} }

View File

@ -310,31 +310,47 @@ static struct drxd_config em28xx_drxd = {
.disable_i2c_gate_ctrl = 1, .disable_i2c_gate_ctrl = 1,
}; };
struct drxk_config terratec_h5_drxk = { static struct drxk_config terratec_h5_drxk = {
.adr = 0x29, .adr = 0x29,
.single_master = 1, .single_master = 1,
.no_i2c_bridge = 1, .no_i2c_bridge = 1,
.microcode_name = "dvb-usb-terratec-h5-drxk.fw", .microcode_name = "dvb-usb-terratec-h5-drxk.fw",
.qam_demod_parameter_count = 2,
}; };
struct drxk_config hauppauge_930c_drxk = { static struct drxk_config hauppauge_930c_drxk = {
.adr = 0x29, .adr = 0x29,
.single_master = 1, .single_master = 1,
.no_i2c_bridge = 1, .no_i2c_bridge = 1,
.microcode_name = "dvb-usb-hauppauge-hvr930c-drxk.fw", .microcode_name = "dvb-usb-hauppauge-hvr930c-drxk.fw",
.chunk_size = 56, .chunk_size = 56,
.qam_demod_parameter_count = 2,
}; };
struct drxk_config maxmedia_ub425_tc_drxk = { struct drxk_config terratec_htc_stick_drxk = {
.adr = 0x29,
.single_master = 1,
.no_i2c_bridge = 1,
.microcode_name = "dvb-usb-terratec-htc-stick-drxk.fw",
.chunk_size = 54,
.qam_demod_parameter_count = 2,
/* Required for the antenna_gpio to disable LNA. */
.antenna_dvbt = true,
/* The windows driver uses the same. This will disable LNA. */
.antenna_gpio = 0x6,
};
static struct drxk_config maxmedia_ub425_tc_drxk = {
.adr = 0x29, .adr = 0x29,
.single_master = 1, .single_master = 1,
.no_i2c_bridge = 1, .no_i2c_bridge = 1,
}; };
struct drxk_config pctv_520e_drxk = { static struct drxk_config pctv_520e_drxk = {
.adr = 0x29, .adr = 0x29,
.single_master = 1, .single_master = 1,
.microcode_name = "dvb-demod-drxk-pctv.fw", .microcode_name = "dvb-demod-drxk-pctv.fw",
.qam_demod_parameter_count = 2,
.chunk_size = 58, .chunk_size = 58,
.antenna_dvbt = true, /* disable LNA */ .antenna_dvbt = true, /* disable LNA */
.antenna_gpio = (1 << 2), /* disable LNA */ .antenna_gpio = (1 << 2), /* disable LNA */
@ -473,6 +489,57 @@ static void terratec_h5_init(struct em28xx *dev)
em28xx_gpio_set(dev, terratec_h5_end); em28xx_gpio_set(dev, terratec_h5_end);
}; };
static void terratec_htc_stick_init(struct em28xx *dev)
{
int i;
/*
* GPIO configuration:
* 0xff: unknown (does not affect DVB-T).
* 0xf6: DRX-K (demodulator).
* 0xe6: unknown (does not affect DVB-T).
* 0xb6: unknown (does not affect DVB-T).
*/
struct em28xx_reg_seq terratec_htc_stick_init[] = {
{EM28XX_R08_GPIO, 0xff, 0xff, 10},
{EM2874_R80_GPIO, 0xf6, 0xff, 100},
{EM2874_R80_GPIO, 0xe6, 0xff, 50},
{EM2874_R80_GPIO, 0xf6, 0xff, 100},
{ -1, -1, -1, -1},
};
struct em28xx_reg_seq terratec_htc_stick_end[] = {
{EM2874_R80_GPIO, 0xb6, 0xff, 100},
{EM2874_R80_GPIO, 0xf6, 0xff, 50},
{ -1, -1, -1, -1},
};
/* Init the analog decoder? */
struct {
unsigned char r[4];
int len;
} regs[] = {
{{ 0x06, 0x02, 0x00, 0x31 }, 4},
{{ 0x01, 0x02 }, 2},
{{ 0x01, 0x02, 0x00, 0xc6 }, 4},
{{ 0x01, 0x00 }, 2},
{{ 0x01, 0x00, 0xff, 0xaf }, 4},
};
em28xx_gpio_set(dev, terratec_htc_stick_init);
em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40);
msleep(10);
em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44);
msleep(10);
dev->i2c_client.addr = 0x82 >> 1;
for (i = 0; i < ARRAY_SIZE(regs); i++)
i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len);
em28xx_gpio_set(dev, terratec_htc_stick_end);
};
static void pctv_520e_init(struct em28xx *dev) static void pctv_520e_init(struct em28xx *dev)
{ {
/* /*
@ -944,7 +1011,6 @@ static int em28xx_dvb_init(struct em28xx *dev)
break; break;
} }
case EM2884_BOARD_TERRATEC_H5: case EM2884_BOARD_TERRATEC_H5:
case EM2884_BOARD_CINERGY_HTC_STICK:
terratec_h5_init(dev); terratec_h5_init(dev);
dvb->fe[0] = dvb_attach(drxk_attach, &terratec_h5_drxk, &dev->i2c_adap); dvb->fe[0] = dvb_attach(drxk_attach, &terratec_h5_drxk, &dev->i2c_adap);
@ -1021,6 +1087,25 @@ static int em28xx_dvb_init(struct em28xx *dev)
} }
} }
break; break;
case EM2884_BOARD_CINERGY_HTC_STICK:
terratec_htc_stick_init(dev);
/* attach demodulator */
dvb->fe[0] = dvb_attach(drxk_attach, &terratec_htc_stick_drxk,
&dev->i2c_adap);
if (!dvb->fe[0]) {
result = -EINVAL;
goto out_free;
}
/* Attach the demodulator. */
if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
&dev->i2c_adap,
&em28xx_cxd2820r_tda18271_config)) {
result = -EINVAL;
goto out_free;
}
break;
default: default:
em28xx_errdev("/2: The frontend of your DVB/ATSC card" em28xx_errdev("/2: The frontend of your DVB/ATSC card"
" isn't supported yet\n"); " isn't supported yet\n");

View File

@ -475,6 +475,7 @@ static struct i2c_client em28xx_client_template = {
*/ */
static char *i2c_devs[128] = { static char *i2c_devs[128] = {
[0x4a >> 1] = "saa7113h", [0x4a >> 1] = "saa7113h",
[0x52 >> 1] = "drxk",
[0x60 >> 1] = "remote IR sensor", [0x60 >> 1] = "remote IR sensor",
[0x8e >> 1] = "remote IR sensor", [0x8e >> 1] = "remote IR sensor",
[0x86 >> 1] = "tda9887", [0x86 >> 1] = "tda9887",

View File

@ -345,7 +345,7 @@ static void em28xx_ir_stop(struct rc_dev *rc)
cancel_delayed_work_sync(&ir->work); cancel_delayed_work_sync(&ir->work);
} }
int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 rc_type) static int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 rc_type)
{ {
int rc = 0; int rc = 0;
struct em28xx_IR *ir = rc_dev->priv; struct em28xx_IR *ir = rc_dev->priv;

View File

@ -211,58 +211,9 @@ enum em28xx_chip_id {
}; };
/* /*
* Registers used by em202 and other AC97 chips * Registers used by em202
*/ */
/* Standard AC97 registers */
#define AC97_RESET 0x00
/* Output volumes */
#define AC97_MASTER_VOL 0x02
#define AC97_LINE_LEVEL_VOL 0x04 /* Some devices use for headphones */
#define AC97_MASTER_MONO_VOL 0x06
/* Input volumes */
#define AC97_PC_BEEP_VOL 0x0a
#define AC97_PHONE_VOL 0x0c
#define AC97_MIC_VOL 0x0e
#define AC97_LINEIN_VOL 0x10
#define AC97_CD_VOL 0x12
#define AC97_VIDEO_VOL 0x14
#define AC97_AUX_VOL 0x16
#define AC97_PCM_OUT_VOL 0x18
/* capture registers */
#define AC97_RECORD_SELECT 0x1a
#define AC97_RECORD_GAIN 0x1c
/* control registers */
#define AC97_GENERAL_PURPOSE 0x20
#define AC97_3D_CTRL 0x22
#define AC97_AUD_INT_AND_PAG 0x24
#define AC97_POWER_DOWN_CTRL 0x26
#define AC97_EXT_AUD_ID 0x28
#define AC97_EXT_AUD_CTRL 0x2a
/* Supported rate varies for each AC97 device
if write an unsupported value, it will return the closest one
*/
#define AC97_PCM_OUT_FRONT_SRATE 0x2c
#define AC97_PCM_OUT_SURR_SRATE 0x2e
#define AC97_PCM_OUT_LFE_SRATE 0x30
#define AC97_PCM_IN_SRATE 0x32
/* For devices with more than 2 channels, extra output volumes */
#define AC97_LFE_MASTER_VOL 0x36
#define AC97_SURR_MASTER_VOL 0x38
/* Digital SPDIF output control */
#define AC97_SPDIF_OUT_CTRL 0x3a
/* Vendor ID identifier */
#define AC97_VENDOR_ID1 0x7c
#define AC97_VENDOR_ID2 0x7e
/* EMP202 vendor registers */ /* EMP202 vendor registers */
#define EM202_EXT_MODEM_CTRL 0x3e #define EM202_EXT_MODEM_CTRL 0x3e
#define EM202_GPIO_CONF 0x4c #define EM202_GPIO_CONF 0x4c

View File

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

View File

@ -1830,18 +1830,6 @@ static long ivtv_default(struct file *file, void *fh, bool valid_prio,
return 0; return 0;
} }
long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct video_device *vfd = video_devdata(filp);
long ret;
if (ivtv_debug & IVTV_DBGFLG_IOCTL)
vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
ret = video_ioctl2(filp, cmd, arg);
vfd->debug = 0;
return ret;
}
static const struct v4l2_ioctl_ops ivtv_ioctl_ops = { static const struct v4l2_ioctl_ops ivtv_ioctl_ops = {
.vidioc_querycap = ivtv_querycap, .vidioc_querycap = ivtv_querycap,
.vidioc_s_audio = ivtv_s_audio, .vidioc_s_audio = ivtv_s_audio,

View File

@ -31,6 +31,5 @@ void ivtv_s_std_enc(struct ivtv *itv, v4l2_std_id *std);
void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std); void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std);
int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf); int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf);
int ivtv_s_input(struct file *file, void *fh, unsigned int inp); int ivtv_s_input(struct file *file, void *fh, unsigned int inp);
long ivtv_v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
#endif #endif

View File

@ -50,7 +50,7 @@ static const struct v4l2_file_operations ivtv_v4l2_enc_fops = {
.read = ivtv_v4l2_read, .read = ivtv_v4l2_read,
.write = ivtv_v4l2_write, .write = ivtv_v4l2_write,
.open = ivtv_v4l2_open, .open = ivtv_v4l2_open,
.unlocked_ioctl = ivtv_v4l2_ioctl, .unlocked_ioctl = video_ioctl2,
.release = ivtv_v4l2_close, .release = ivtv_v4l2_close,
.poll = ivtv_v4l2_enc_poll, .poll = ivtv_v4l2_enc_poll,
}; };
@ -60,7 +60,7 @@ static const struct v4l2_file_operations ivtv_v4l2_dec_fops = {
.read = ivtv_v4l2_read, .read = ivtv_v4l2_read,
.write = ivtv_v4l2_write, .write = ivtv_v4l2_write,
.open = ivtv_v4l2_open, .open = ivtv_v4l2_open,
.unlocked_ioctl = ivtv_v4l2_ioctl, .unlocked_ioctl = video_ioctl2,
.release = ivtv_v4l2_close, .release = ivtv_v4l2_close,
.poll = ivtv_v4l2_dec_poll, .poll = ivtv_v4l2_dec_poll,
}; };

View File

@ -1,5 +1,6 @@
config VIDEO_M5MOLS config VIDEO_M5MOLS
tristate "Fujitsu M-5MOLS 8MP sensor support" tristate "Fujitsu M-5MOLS 8MP sensor support"
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
depends on MEDIA_CAMERA_SUPPORT
---help--- ---help---
This driver supports Fujitsu M-5MOLS camera sensor with ISP This driver supports Fujitsu M-5MOLS camera sensor with ISP

View File

@ -60,6 +60,10 @@ MODULE_VERSION("0.1.1");
#define MEM2MEM_COLOR_STEP (0xff >> 4) #define MEM2MEM_COLOR_STEP (0xff >> 4)
#define MEM2MEM_NUM_TILES 8 #define MEM2MEM_NUM_TILES 8
/* Flags that indicate processing mode */
#define MEM2MEM_HFLIP (1 << 0)
#define MEM2MEM_VFLIP (1 << 1)
#define dprintk(dev, fmt, arg...) \ #define dprintk(dev, fmt, arg...) \
v4l2_dbg(1, 1, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg) v4l2_dbg(1, 1, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
@ -115,6 +119,24 @@ enum {
static struct v4l2_queryctrl m2mtest_ctrls[] = { static struct v4l2_queryctrl m2mtest_ctrls[] = {
{ {
.id = V4L2_CID_HFLIP,
.type = V4L2_CTRL_TYPE_BOOLEAN,
.name = "Mirror",
.minimum = 0,
.maximum = 1,
.step = 1,
.default_value = 0,
.flags = 0,
}, {
.id = V4L2_CID_VFLIP,
.type = V4L2_CTRL_TYPE_BOOLEAN,
.name = "Vertical Mirror",
.minimum = 0,
.maximum = 1,
.step = 1,
.default_value = 0,
.flags = 0,
}, {
.id = V4L2_CID_TRANS_TIME_MSEC, .id = V4L2_CID_TRANS_TIME_MSEC,
.type = V4L2_CTRL_TYPE_INTEGER, .type = V4L2_CTRL_TYPE_INTEGER,
.name = "Transaction time (msec)", .name = "Transaction time (msec)",
@ -181,6 +203,9 @@ struct m2mtest_ctx {
/* Abort requested by m2m */ /* Abort requested by m2m */
int aborting; int aborting;
/* Processing mode */
int mode;
struct v4l2_m2m_ctx *m2m_ctx; struct v4l2_m2m_ctx *m2m_ctx;
/* Source and destination queue data */ /* Source and destination queue data */
@ -249,19 +274,84 @@ static int device_process(struct m2mtest_ctx *ctx,
bytes_left = bytesperline - tile_w * MEM2MEM_NUM_TILES; bytes_left = bytesperline - tile_w * MEM2MEM_NUM_TILES;
w = 0; w = 0;
for (y = 0; y < height; ++y) { switch (ctx->mode) {
for (t = 0; t < MEM2MEM_NUM_TILES; ++t) { case MEM2MEM_HFLIP | MEM2MEM_VFLIP:
if (w & 0x1) { p_out += bytesperline * height - bytes_left;
for (x = 0; x < tile_w; ++x) for (y = 0; y < height; ++y) {
*p_out++ = *p_in++ + MEM2MEM_COLOR_STEP; for (t = 0; t < MEM2MEM_NUM_TILES; ++t) {
} else { if (w & 0x1) {
for (x = 0; x < tile_w; ++x) for (x = 0; x < tile_w; ++x)
*p_out++ = *p_in++ - MEM2MEM_COLOR_STEP; *--p_out = *p_in++ +
MEM2MEM_COLOR_STEP;
} else {
for (x = 0; x < tile_w; ++x)
*--p_out = *p_in++ -
MEM2MEM_COLOR_STEP;
}
++w;
} }
++w; p_in += bytes_left;
p_out -= bytes_left;
}
break;
case MEM2MEM_HFLIP:
for (y = 0; y < height; ++y) {
p_out += MEM2MEM_NUM_TILES * tile_w;
for (t = 0; t < MEM2MEM_NUM_TILES; ++t) {
if (w & 0x01) {
for (x = 0; x < tile_w; ++x)
*--p_out = *p_in++ +
MEM2MEM_COLOR_STEP;
} else {
for (x = 0; x < tile_w; ++x)
*--p_out = *p_in++ -
MEM2MEM_COLOR_STEP;
}
++w;
}
p_in += bytes_left;
p_out += bytesperline;
}
break;
case MEM2MEM_VFLIP:
p_out += bytesperline * (height - 1);
for (y = 0; y < height; ++y) {
for (t = 0; t < MEM2MEM_NUM_TILES; ++t) {
if (w & 0x1) {
for (x = 0; x < tile_w; ++x)
*p_out++ = *p_in++ +
MEM2MEM_COLOR_STEP;
} else {
for (x = 0; x < tile_w; ++x)
*p_out++ = *p_in++ -
MEM2MEM_COLOR_STEP;
}
++w;
}
p_in += bytes_left;
p_out += bytes_left - 2 * bytesperline;
}
break;
default:
for (y = 0; y < height; ++y) {
for (t = 0; t < MEM2MEM_NUM_TILES; ++t) {
if (w & 0x1) {
for (x = 0; x < tile_w; ++x)
*p_out++ = *p_in++ +
MEM2MEM_COLOR_STEP;
} else {
for (x = 0; x < tile_w; ++x)
*p_out++ = *p_in++ -
MEM2MEM_COLOR_STEP;
}
++w;
}
p_in += bytes_left;
p_out += bytes_left;
} }
p_in += bytes_left;
p_out += bytes_left;
} }
return 0; return 0;
@ -648,6 +738,14 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
struct m2mtest_ctx *ctx = priv; struct m2mtest_ctx *ctx = priv;
switch (ctrl->id) { switch (ctrl->id) {
case V4L2_CID_HFLIP:
ctrl->value = (ctx->mode & MEM2MEM_HFLIP) ? 1 : 0;
break;
case V4L2_CID_VFLIP:
ctrl->value = (ctx->mode & MEM2MEM_VFLIP) ? 1 : 0;
break;
case V4L2_CID_TRANS_TIME_MSEC: case V4L2_CID_TRANS_TIME_MSEC:
ctrl->value = ctx->transtime; ctrl->value = ctx->transtime;
break; break;
@ -691,6 +789,20 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
return ret; return ret;
switch (ctrl->id) { switch (ctrl->id) {
case V4L2_CID_HFLIP:
if (ctrl->value)
ctx->mode |= MEM2MEM_HFLIP;
else
ctx->mode &= ~MEM2MEM_HFLIP;
break;
case V4L2_CID_VFLIP:
if (ctrl->value)
ctx->mode |= MEM2MEM_VFLIP;
else
ctx->mode &= ~MEM2MEM_VFLIP;
break;
case V4L2_CID_TRANS_TIME_MSEC: case V4L2_CID_TRANS_TIME_MSEC:
ctx->transtime = ctrl->value; ctx->transtime = ctrl->value;
break; break;
@ -861,6 +973,7 @@ static int m2mtest_open(struct file *file)
ctx->translen = MEM2MEM_DEF_TRANSLEN; ctx->translen = MEM2MEM_DEF_TRANSLEN;
ctx->transtime = MEM2MEM_DEF_TRANSTIME; ctx->transtime = MEM2MEM_DEF_TRANSTIME;
ctx->num_processed = 0; ctx->num_processed = 0;
ctx->mode = 0;
ctx->q_data[V4L2_M2M_SRC].fmt = &formats[0]; ctx->q_data[V4L2_M2M_SRC].fmt = &formats[0];
ctx->q_data[V4L2_M2M_DST].fmt = &formats[0]; ctx->q_data[V4L2_M2M_DST].fmt = &formats[0];

View File

@ -22,7 +22,7 @@
/* /*
* mt9m001 i2c address 0x5d * mt9m001 i2c address 0x5d
* The platform has to define ctruct i2c_board_info objects and link to them * The platform has to define struct i2c_board_info objects and link to them
* from struct soc_camera_link * from struct soc_camera_link
*/ */

View File

@ -688,11 +688,17 @@ static const struct v4l2_subdev_ops mt9m032_ops = {
static int mt9m032_probe(struct i2c_client *client, static int mt9m032_probe(struct i2c_client *client,
const struct i2c_device_id *devid) const struct i2c_device_id *devid)
{ {
struct mt9m032_platform_data *pdata = client->dev.platform_data;
struct i2c_adapter *adapter = client->adapter; struct i2c_adapter *adapter = client->adapter;
struct mt9m032 *sensor; struct mt9m032 *sensor;
int chip_version; int chip_version;
int ret; int ret;
if (pdata == NULL) {
dev_err(&client->dev, "No platform data\n");
return -EINVAL;
}
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) { if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
dev_warn(&client->dev, dev_warn(&client->dev,
"I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n"); "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
@ -708,7 +714,7 @@ static int mt9m032_probe(struct i2c_client *client,
mutex_init(&sensor->lock); mutex_init(&sensor->lock);
sensor->pdata = client->dev.platform_data; sensor->pdata = pdata;
v4l2_i2c_subdev_init(&sensor->subdev, client, &mt9m032_ops); v4l2_i2c_subdev_init(&sensor->subdev, client, &mt9m032_ops);
sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
@ -738,7 +744,7 @@ static int mt9m032_probe(struct i2c_client *client,
sensor->format.field = V4L2_FIELD_NONE; sensor->format.field = V4L2_FIELD_NONE;
sensor->format.colorspace = V4L2_COLORSPACE_SRGB; sensor->format.colorspace = V4L2_COLORSPACE_SRGB;
v4l2_ctrl_handler_init(&sensor->ctrls, 4); v4l2_ctrl_handler_init(&sensor->ctrls, 5);
v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops, v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops,
V4L2_CID_GAIN, 0, 127, 1, 64); V4L2_CID_GAIN, 0, 127, 1, 64);
@ -754,6 +760,9 @@ static int mt9m032_probe(struct i2c_client *client,
V4L2_CID_EXPOSURE, MT9M032_SHUTTER_WIDTH_MIN, V4L2_CID_EXPOSURE, MT9M032_SHUTTER_WIDTH_MIN,
MT9M032_SHUTTER_WIDTH_MAX, 1, MT9M032_SHUTTER_WIDTH_MAX, 1,
MT9M032_SHUTTER_WIDTH_DEF); MT9M032_SHUTTER_WIDTH_DEF);
v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops,
V4L2_CID_PIXEL_RATE, pdata->pix_clock,
pdata->pix_clock, 1, pdata->pix_clock);
if (sensor->ctrls.error) { if (sensor->ctrls.error) {
ret = sensor->ctrls.error; ret = sensor->ctrls.error;

View File

@ -214,7 +214,6 @@ struct mt9m111 {
int power_count; int power_count;
const struct mt9m111_datafmt *fmt; const struct mt9m111_datafmt *fmt;
int lastpage; /* PageMap cache value */ int lastpage; /* PageMap cache value */
unsigned char datawidth;
}; };
/* Find a data format by a pixel code */ /* Find a data format by a pixel code */

View File

@ -950,7 +950,7 @@ static int mt9p031_probe(struct i2c_client *client,
mt9p031->model = did->driver_data; mt9p031->model = did->driver_data;
mt9p031->reset = -1; mt9p031->reset = -1;
v4l2_ctrl_handler_init(&mt9p031->ctrls, ARRAY_SIZE(mt9p031_ctrls) + 4); v4l2_ctrl_handler_init(&mt9p031->ctrls, ARRAY_SIZE(mt9p031_ctrls) + 5);
v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops, v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
V4L2_CID_EXPOSURE, MT9P031_SHUTTER_WIDTH_MIN, V4L2_CID_EXPOSURE, MT9P031_SHUTTER_WIDTH_MIN,
@ -963,6 +963,9 @@ static int mt9p031_probe(struct i2c_client *client,
V4L2_CID_HFLIP, 0, 1, 1, 0); V4L2_CID_HFLIP, 0, 1, 1, 0);
v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops, v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
V4L2_CID_VFLIP, 0, 1, 1, 0); V4L2_CID_VFLIP, 0, 1, 1, 0);
v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
V4L2_CID_PIXEL_RATE, pdata->target_freq,
pdata->target_freq, 1, pdata->target_freq);
for (i = 0; i < ARRAY_SIZE(mt9p031_ctrls); ++i) for (i = 0; i < ARRAY_SIZE(mt9p031_ctrls); ++i)
v4l2_ctrl_new_custom(&mt9p031->ctrls, &mt9p031_ctrls[i], NULL); v4l2_ctrl_new_custom(&mt9p031->ctrls, &mt9p031_ctrls[i], NULL);

View File

@ -691,7 +691,7 @@ static int mt9t001_video_probe(struct i2c_client *client)
return ret; return ret;
/* Configure the pixel clock polarity */ /* Configure the pixel clock polarity */
if (pdata && pdata->clk_pol) { if (pdata->clk_pol) {
ret = mt9t001_write(client, MT9T001_PIXEL_CLOCK, ret = mt9t001_write(client, MT9T001_PIXEL_CLOCK,
MT9T001_PIXEL_CLOCK_INVERT); MT9T001_PIXEL_CLOCK_INVERT);
if (ret < 0) if (ret < 0)
@ -715,10 +715,16 @@ static int mt9t001_video_probe(struct i2c_client *client)
static int mt9t001_probe(struct i2c_client *client, static int mt9t001_probe(struct i2c_client *client,
const struct i2c_device_id *did) const struct i2c_device_id *did)
{ {
struct mt9t001_platform_data *pdata = client->dev.platform_data;
struct mt9t001 *mt9t001; struct mt9t001 *mt9t001;
unsigned int i; unsigned int i;
int ret; int ret;
if (pdata == NULL) {
dev_err(&client->dev, "No platform data\n");
return -EINVAL;
}
if (!i2c_check_functionality(client->adapter, if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_WORD_DATA)) { I2C_FUNC_SMBUS_WORD_DATA)) {
dev_warn(&client->adapter->dev, dev_warn(&client->adapter->dev,
@ -735,7 +741,7 @@ static int mt9t001_probe(struct i2c_client *client,
return -ENOMEM; return -ENOMEM;
v4l2_ctrl_handler_init(&mt9t001->ctrls, ARRAY_SIZE(mt9t001_ctrls) + v4l2_ctrl_handler_init(&mt9t001->ctrls, ARRAY_SIZE(mt9t001_ctrls) +
ARRAY_SIZE(mt9t001_gains) + 2); ARRAY_SIZE(mt9t001_gains) + 3);
v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops, v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops,
V4L2_CID_EXPOSURE, MT9T001_SHUTTER_WIDTH_MIN, V4L2_CID_EXPOSURE, MT9T001_SHUTTER_WIDTH_MIN,
@ -743,6 +749,9 @@ static int mt9t001_probe(struct i2c_client *client,
MT9T001_SHUTTER_WIDTH_DEF); MT9T001_SHUTTER_WIDTH_DEF);
v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops, v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops,
V4L2_CID_BLACK_LEVEL, 1, 1, 1, 1); V4L2_CID_BLACK_LEVEL, 1, 1, 1, 1);
v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops,
V4L2_CID_PIXEL_RATE, pdata->ext_clk, pdata->ext_clk,
1, pdata->ext_clk);
for (i = 0; i < ARRAY_SIZE(mt9t001_ctrls); ++i) for (i = 0; i < ARRAY_SIZE(mt9t001_ctrls); ++i)
v4l2_ctrl_new_custom(&mt9t001->ctrls, &mt9t001_ctrls[i], NULL); v4l2_ctrl_new_custom(&mt9t001->ctrls, &mt9t001_ctrls[i], NULL);

View File

@ -23,7 +23,7 @@
/* /*
* mt9v022 i2c address 0x48, 0x4c, 0x58, 0x5c * mt9v022 i2c address 0x48, 0x4c, 0x58, 0x5c
* The platform has to define ctruct i2c_board_info objects and link to them * The platform has to define struct i2c_board_info objects and link to them
* from struct soc_camera_link * from struct soc_camera_link
*/ */

View File

@ -2014,7 +2014,7 @@ static int ccdc_get_selection(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
return -EINVAL; return -EINVAL;
switch (sel->target) { switch (sel->target) {
case V4L2_SUBDEV_SEL_TGT_CROP_BOUNDS: case V4L2_SEL_TGT_CROP_BOUNDS:
sel->r.left = 0; sel->r.left = 0;
sel->r.top = 0; sel->r.top = 0;
sel->r.width = INT_MAX; sel->r.width = INT_MAX;
@ -2024,7 +2024,7 @@ static int ccdc_get_selection(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
ccdc_try_crop(ccdc, format, &sel->r); ccdc_try_crop(ccdc, format, &sel->r);
break; break;
case V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL: case V4L2_SEL_TGT_CROP:
sel->r = *__ccdc_get_crop(ccdc, fh, sel->which); sel->r = *__ccdc_get_crop(ccdc, fh, sel->which);
break; break;
@ -2052,7 +2052,7 @@ static int ccdc_set_selection(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd); struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
struct v4l2_mbus_framefmt *format; struct v4l2_mbus_framefmt *format;
if (sel->target != V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL || if (sel->target != V4L2_SEL_TGT_CROP ||
sel->pad != CCDC_PAD_SOURCE_OF) sel->pad != CCDC_PAD_SOURCE_OF)
return -EINVAL; return -EINVAL;
@ -2064,7 +2064,7 @@ static int ccdc_set_selection(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
* pad. If the KEEP_CONFIG flag is set, just return the current crop * pad. If the KEEP_CONFIG flag is set, just return the current crop
* rectangle. * rectangle.
*/ */
if (sel->flags & V4L2_SUBDEV_SEL_FLAG_KEEP_CONFIG) { if (sel->flags & V4L2_SEL_FLAG_KEEP_CONFIG) {
sel->r = *__ccdc_get_crop(ccdc, fh, sel->which); sel->r = *__ccdc_get_crop(ccdc, fh, sel->which);
return 0; return 0;
} }

View File

@ -1949,7 +1949,7 @@ static int preview_get_selection(struct v4l2_subdev *sd,
return -EINVAL; return -EINVAL;
switch (sel->target) { switch (sel->target) {
case V4L2_SUBDEV_SEL_TGT_CROP_BOUNDS: case V4L2_SEL_TGT_CROP_BOUNDS:
sel->r.left = 0; sel->r.left = 0;
sel->r.top = 0; sel->r.top = 0;
sel->r.width = INT_MAX; sel->r.width = INT_MAX;
@ -1960,7 +1960,7 @@ static int preview_get_selection(struct v4l2_subdev *sd,
preview_try_crop(prev, format, &sel->r); preview_try_crop(prev, format, &sel->r);
break; break;
case V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL: case V4L2_SEL_TGT_CROP:
sel->r = *__preview_get_crop(prev, fh, sel->which); sel->r = *__preview_get_crop(prev, fh, sel->which);
break; break;
@ -1988,7 +1988,7 @@ static int preview_set_selection(struct v4l2_subdev *sd,
struct isp_prev_device *prev = v4l2_get_subdevdata(sd); struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
struct v4l2_mbus_framefmt *format; struct v4l2_mbus_framefmt *format;
if (sel->target != V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL || if (sel->target != V4L2_SEL_TGT_CROP ||
sel->pad != PREV_PAD_SINK) sel->pad != PREV_PAD_SINK)
return -EINVAL; return -EINVAL;
@ -2000,7 +2000,7 @@ static int preview_set_selection(struct v4l2_subdev *sd,
* pad. If the KEEP_CONFIG flag is set, just return the current crop * pad. If the KEEP_CONFIG flag is set, just return the current crop
* rectangle. * rectangle.
*/ */
if (sel->flags & V4L2_SUBDEV_SEL_FLAG_KEEP_CONFIG) { if (sel->flags & V4L2_SEL_FLAG_KEEP_CONFIG) {
sel->r = *__preview_get_crop(prev, fh, sel->which); sel->r = *__preview_get_crop(prev, fh, sel->which);
return 0; return 0;
} }

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