Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (348 commits) [media] pctv452e: Remove bogus code [media] adv7175: Make use of media bus pixel codes [media] media: vb2: fix incorrect return value [media] em28xx: implement VIDIOC_ENUM_FRAMESIZES [media] cx23885: Stop the risc video fifo before reconfiguring it [media] cx23885: Avoid incorrect error handling and reporting [media] cx23885: Avoid stopping the risc engine during buffer timeout [media] cx23885: Removed a spurious function cx23885_set_scale() [media] cx23885: v4l2 api compliance, set the audioset field correctly [media] cx23885: hook the audio selection functions into the main driver [media] cx23885: add generic functions for dealing with audio input selection [media] cx23885: fixes related to maximum number of inputs and range checking [media] cx23885: Initial support for the MPX-885 mini-card [media] cx25840: Ensure AUDIO6 and AUDIO7 trigger line-in baseband use [media] cx23885: Enable audio line in support from the back panel [media] cx23885: Allow the audio mux config to be specified on a per input basis [media] cx25840: Enable support for non-tuner LR1/LR2 audio inputs [media] cx23885: Name an internal i2c part and declare a bitfield by name [media] cx23885: Ensure VBI buffers timeout quickly - bugfix for vbi hangs during streaming [media] cx23885: remove channel dump diagnostics when a vbi buffer times out ... Fix up trivial conflicts in drivers/misc/altera-stapl/altera.c (header file rename vs add)
This commit is contained in:
commit
1eb6337835
@ -352,6 +352,7 @@ typedef enum fe_delivery_system {
|
||||
SYS_CMMB,
|
||||
SYS_DAB,
|
||||
SYS_DVBT2,
|
||||
SYS_TURBO,
|
||||
} fe_delivery_system_t;
|
||||
</programlisting>
|
||||
</section>
|
||||
@ -809,6 +810,8 @@ typedef enum fe_hierarchy {
|
||||
<listitem><para><link linkend="DTV-INVERSION"><constant>DTV_INVERSION</constant></link></para></listitem>
|
||||
<listitem><para><link linkend="DTV-SYMBOL-RATE"><constant>DTV_SYMBOL_RATE</constant></link></para></listitem>
|
||||
<listitem><para><link linkend="DTV-INNER-FEC"><constant>DTV_INNER_FEC</constant></link></para></listitem>
|
||||
<listitem><para><link linkend="DTV-VOLTAGE"><constant>DTV_VOLTAGE</constant></link></para></listitem>
|
||||
<listitem><para><link linkend="DTV-TONE"><constant>DTV_TONE</constant></link></para></listitem>
|
||||
</itemizedlist>
|
||||
<para>Future implementations might add those two missing parameters:</para>
|
||||
<itemizedlist mark='opencircle'>
|
||||
@ -818,25 +821,18 @@ typedef enum fe_hierarchy {
|
||||
</section>
|
||||
<section id="dvbs2-params">
|
||||
<title>DVB-S2 delivery system</title>
|
||||
<para>The following parameters are valid for DVB-S2:</para>
|
||||
<para>In addition to all parameters valid for DVB-S, DVB-S2 supports the following parameters:</para>
|
||||
<itemizedlist mark='opencircle'>
|
||||
<listitem><para><link linkend="DTV-API-VERSION"><constant>DTV_API_VERSION</constant></link></para></listitem>
|
||||
<listitem><para><link linkend="DTV-DELIVERY-SYSTEM"><constant>DTV_DELIVERY_SYSTEM</constant></link></para></listitem>
|
||||
<listitem><para><link linkend="DTV-TUNE"><constant>DTV_TUNE</constant></link></para></listitem>
|
||||
<listitem><para><link linkend="DTV-CLEAR"><constant>DTV_CLEAR</constant></link></para></listitem>
|
||||
<listitem><para><link linkend="DTV-FREQUENCY"><constant>DTV_FREQUENCY</constant></link></para></listitem>
|
||||
<listitem><para><link linkend="DTV-INVERSION"><constant>DTV_INVERSION</constant></link></para></listitem>
|
||||
<listitem><para><link linkend="DTV-SYMBOL-RATE"><constant>DTV_SYMBOL_RATE</constant></link></para></listitem>
|
||||
<listitem><para><link linkend="DTV-INNER-FEC"><constant>DTV_INNER_FEC</constant></link></para></listitem>
|
||||
<listitem><para><link linkend="DTV-VOLTAGE"><constant>DTV_VOLTAGE</constant></link></para></listitem>
|
||||
<listitem><para><link linkend="DTV-TONE"><constant>DTV_TONE</constant></link></para></listitem>
|
||||
<listitem><para><link linkend="DTV-MODULATION"><constant>DTV_MODULATION</constant></link></para></listitem>
|
||||
<listitem><para><link linkend="DTV-PILOT"><constant>DTV_PILOT</constant></link></para></listitem>
|
||||
<listitem><para><link linkend="DTV-ROLLOFF"><constant>DTV_ROLLOFF</constant></link></para></listitem>
|
||||
</itemizedlist>
|
||||
<para>Future implementations might add those two missing parameters:</para>
|
||||
</section>
|
||||
<section id="turbo-params">
|
||||
<title>Turbo code delivery system</title>
|
||||
<para>In addition to all parameters valid for DVB-S, turbo code supports the following parameters:</para>
|
||||
<itemizedlist mark='opencircle'>
|
||||
<listitem><para><link linkend="DTV-DISEQC-MASTER"><constant>DTV_DISEQC_MASTER</constant></link></para></listitem>
|
||||
<listitem><para><link linkend="DTV-DISEQC-SLAVE-REPLY"><constant>DTV_DISEQC_SLAVE_REPLY</constant></link></para></listitem>
|
||||
<listitem><para><link linkend="DTV-MODULATION"><constant>DTV_MODULATION</constant></link></para></listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
<section id="isdbs-params">
|
||||
|
@ -205,7 +205,7 @@ a partial path like:</para>
|
||||
additional include file <emphasis
|
||||
role="tt">linux/dvb/version.h</emphasis> exists, which defines the
|
||||
constant <emphasis role="tt">DVB_API_VERSION</emphasis>. This document
|
||||
describes <emphasis role="tt">DVB_API_VERSION 3</emphasis>.
|
||||
describes <emphasis role="tt">DVB_API_VERSION 5.4</emphasis>.
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
@ -2370,6 +2370,14 @@ that used it. It was originally scheduled for removal in 2.6.35.
|
||||
</listitem>
|
||||
</orderedlist>
|
||||
</section>
|
||||
<section>
|
||||
<title>V4L2 in Linux 3.2</title>
|
||||
<orderedlist>
|
||||
<listitem>
|
||||
<para>V4L2_CTRL_FLAG_VOLATILE was added to signal volatile controls to userspace.</para>
|
||||
</listitem>
|
||||
</orderedlist>
|
||||
</section>
|
||||
|
||||
<section id="other">
|
||||
<title>Relation of V4L2 to other Linux multimedia APIs</title>
|
||||
|
@ -266,7 +266,7 @@
|
||||
|
||||
<para>When satisfied with the try results, applications can set the active
|
||||
formats by setting the <structfield>which</structfield> argument to
|
||||
<constant>V4L2_SUBDEV_FORMAT_TRY</constant>. Active formats are changed
|
||||
<constant>V4L2_SUBDEV_FORMAT_ACTIVE</constant>. Active formats are changed
|
||||
exactly as try formats by drivers. To avoid modifying the hardware state
|
||||
during format negotiation, applications should negotiate try formats first
|
||||
and then modify the active settings using the try formats returned during
|
||||
|
@ -127,6 +127,13 @@ structs, ioctls) must be noted in more detail in the history chapter
|
||||
(compat.xml), along with the possible impact on existing drivers and
|
||||
applications. -->
|
||||
|
||||
<revision>
|
||||
<revnumber>3.2</revnumber>
|
||||
<date>2011-08-26</date>
|
||||
<authorinitials>hv</authorinitials>
|
||||
<revremark>Added V4L2_CTRL_FLAG_VOLATILE.</revremark>
|
||||
</revision>
|
||||
|
||||
<revision>
|
||||
<revnumber>3.1</revnumber>
|
||||
<date>2011-06-27</date>
|
||||
@ -410,7 +417,7 @@ and discussions on the V4L mailing list.</revremark>
|
||||
</partinfo>
|
||||
|
||||
<title>Video for Linux Two API Specification</title>
|
||||
<subtitle>Revision 3.1</subtitle>
|
||||
<subtitle>Revision 3.2</subtitle>
|
||||
|
||||
<chapter id="common">
|
||||
&sub-common;
|
||||
|
@ -86,6 +86,12 @@
|
||||
<entry>Event data for event V4L2_EVENT_CTRL.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
<entry>&v4l2-event-frame-sync;</entry>
|
||||
<entry><structfield>frame</structfield></entry>
|
||||
<entry>Event data for event V4L2_EVENT_FRAME_SYNC.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
<entry>__u8</entry>
|
||||
@ -135,6 +141,129 @@
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<table frame="none" pgwide="1" id="v4l2-event-vsync">
|
||||
<title>struct <structname>v4l2_event_vsync</structname></title>
|
||||
<tgroup cols="3">
|
||||
&cs-str;
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry>__u8</entry>
|
||||
<entry><structfield>field</structfield></entry>
|
||||
<entry>The upcoming field. See &v4l2-field;.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<table frame="none" pgwide="1" id="v4l2-event-ctrl">
|
||||
<title>struct <structname>v4l2_event_ctrl</structname></title>
|
||||
<tgroup cols="4">
|
||||
&cs-str;
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>changes</structfield></entry>
|
||||
<entry></entry>
|
||||
<entry>A bitmask that tells what has changed. See <xref linkend="changes-flags" />.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>type</structfield></entry>
|
||||
<entry></entry>
|
||||
<entry>The type of the control. See &v4l2-ctrl-type;.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>union (anonymous)</entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
<entry>__s32</entry>
|
||||
<entry><structfield>value</structfield></entry>
|
||||
<entry>The 32-bit value of the control for 32-bit control types.
|
||||
This is 0 for string controls since the value of a string
|
||||
cannot be passed using &VIDIOC-DQEVENT;.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
<entry>__s64</entry>
|
||||
<entry><structfield>value64</structfield></entry>
|
||||
<entry>The 64-bit value of the control for 64-bit control types.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>flags</structfield></entry>
|
||||
<entry></entry>
|
||||
<entry>The control flags. See <xref linkend="control-flags" />.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__s32</entry>
|
||||
<entry><structfield>minimum</structfield></entry>
|
||||
<entry></entry>
|
||||
<entry>The minimum value of the control. See &v4l2-queryctrl;.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__s32</entry>
|
||||
<entry><structfield>maximum</structfield></entry>
|
||||
<entry></entry>
|
||||
<entry>The maximum value of the control. See &v4l2-queryctrl;.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__s32</entry>
|
||||
<entry><structfield>step</structfield></entry>
|
||||
<entry></entry>
|
||||
<entry>The step value of the control. See &v4l2-queryctrl;.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__s32</entry>
|
||||
<entry><structfield>default_value</structfield></entry>
|
||||
<entry></entry>
|
||||
<entry>The default value value of the control. See &v4l2-queryctrl;.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<table frame="none" pgwide="1" id="v4l2-event-frame-sync">
|
||||
<title>struct <structname>v4l2_event_frame_sync</structname></title>
|
||||
<tgroup cols="3">
|
||||
&cs-str;
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>frame_sequence</structfield></entry>
|
||||
<entry>
|
||||
The sequence number of the frame being received.
|
||||
</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<table pgwide="1" frame="none" id="changes-flags">
|
||||
<title>Changes</title>
|
||||
<tgroup cols="3">
|
||||
&cs-def;
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry><constant>V4L2_EVENT_CTRL_CH_VALUE</constant></entry>
|
||||
<entry>0x0001</entry>
|
||||
<entry>This control event was triggered because the value of the control
|
||||
changed. Special case: if a button control is pressed, then this
|
||||
event is sent as well, even though there is not explicit value
|
||||
associated with a button control.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>V4L2_EVENT_CTRL_CH_FLAGS</constant></entry>
|
||||
<entry>0x0002</entry>
|
||||
<entry>This control event was triggered because the control flags
|
||||
changed.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
</refsect1>
|
||||
<refsect1>
|
||||
&return-value;
|
||||
|
@ -406,6 +406,15 @@ flag is typically present for relative controls or action controls where
|
||||
writing a value will cause the device to carry out a given action
|
||||
(⪚ motor control) but no meaningful value can be returned.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>V4L2_CTRL_FLAG_VOLATILE</constant></entry>
|
||||
<entry>0x0080</entry>
|
||||
<entry>This control is volatile, which means that the value of the control
|
||||
changes continuously. A typical example would be the current gain value if the device
|
||||
is in auto-gain mode. In such a case the hardware calculates the gain value based on
|
||||
the lighting conditions which can change over time. Note that setting a new value for
|
||||
a volatile control will have no effect. The new value will just be ignored.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
@ -138,6 +138,22 @@
|
||||
field of the oldest event.</para>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>V4L2_EVENT_FRAME_SYNC</constant></entry>
|
||||
<entry>4</entry>
|
||||
<entry>
|
||||
<para>Triggered immediately when the reception of a
|
||||
frame has begun. This event has a
|
||||
&v4l2-event-frame-sync; associated with it.</para>
|
||||
|
||||
<para>If the hardware needs to be stopped in the case of a
|
||||
buffer underrun it might not be able to generate this event.
|
||||
In such cases the <structfield>frame_sequence</structfield>
|
||||
field in &v4l2-event-frame-sync; will not be incremented. This
|
||||
causes two consecutive frame sequence numbers to have n times
|
||||
frame interval in between them.</para>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>V4L2_EVENT_PRIVATE_START</constant></entry>
|
||||
<entry>0x08000000</entry>
|
||||
@ -183,113 +199,6 @@
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<table frame="none" pgwide="1" id="v4l2-event-vsync">
|
||||
<title>struct <structname>v4l2_event_vsync</structname></title>
|
||||
<tgroup cols="3">
|
||||
&cs-str;
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry>__u8</entry>
|
||||
<entry><structfield>field</structfield></entry>
|
||||
<entry>The upcoming field. See &v4l2-field;.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<table frame="none" pgwide="1" id="v4l2-event-ctrl">
|
||||
<title>struct <structname>v4l2_event_ctrl</structname></title>
|
||||
<tgroup cols="4">
|
||||
&cs-str;
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>changes</structfield></entry>
|
||||
<entry></entry>
|
||||
<entry>A bitmask that tells what has changed. See <xref linkend="changes-flags" />.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>type</structfield></entry>
|
||||
<entry></entry>
|
||||
<entry>The type of the control. See &v4l2-ctrl-type;.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>union (anonymous)</entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
<entry>__s32</entry>
|
||||
<entry><structfield>value</structfield></entry>
|
||||
<entry>The 32-bit value of the control for 32-bit control types.
|
||||
This is 0 for string controls since the value of a string
|
||||
cannot be passed using &VIDIOC-DQEVENT;.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry></entry>
|
||||
<entry>__s64</entry>
|
||||
<entry><structfield>value64</structfield></entry>
|
||||
<entry>The 64-bit value of the control for 64-bit control types.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>flags</structfield></entry>
|
||||
<entry></entry>
|
||||
<entry>The control flags. See <xref linkend="control-flags" />.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__s32</entry>
|
||||
<entry><structfield>minimum</structfield></entry>
|
||||
<entry></entry>
|
||||
<entry>The minimum value of the control. See &v4l2-queryctrl;.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__s32</entry>
|
||||
<entry><structfield>maximum</structfield></entry>
|
||||
<entry></entry>
|
||||
<entry>The maximum value of the control. See &v4l2-queryctrl;.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__s32</entry>
|
||||
<entry><structfield>step</structfield></entry>
|
||||
<entry></entry>
|
||||
<entry>The step value of the control. See &v4l2-queryctrl;.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>__s32</entry>
|
||||
<entry><structfield>default_value</structfield></entry>
|
||||
<entry></entry>
|
||||
<entry>The default value value of the control. See &v4l2-queryctrl;.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<table pgwide="1" frame="none" id="changes-flags">
|
||||
<title>Changes</title>
|
||||
<tgroup cols="3">
|
||||
&cs-def;
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry><constant>V4L2_EVENT_CTRL_CH_VALUE</constant></entry>
|
||||
<entry>0x0001</entry>
|
||||
<entry>This control event was triggered because the value of the control
|
||||
changed. Special case: if a button control is pressed, then this
|
||||
event is sent as well, even though there is not explicit value
|
||||
associated with a button control.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>V4L2_EVENT_CTRL_CH_FLAGS</constant></entry>
|
||||
<entry>0x0002</entry>
|
||||
<entry>This control event was triggered because the control flags
|
||||
changed.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
</refsect1>
|
||||
<refsect1>
|
||||
&return-value;
|
||||
|
@ -27,7 +27,8 @@ use IO::Handle;
|
||||
"or51211", "or51132_qam", "or51132_vsb", "bluebird",
|
||||
"opera1", "cx231xx", "cx18", "cx23885", "pvrusb2", "mpc718",
|
||||
"af9015", "ngene", "az6027", "lme2510_lg", "lme2510c_s7395",
|
||||
"lme2510c_s7395_old", "drxk", "drxk_terratec_h5");
|
||||
"lme2510c_s7395_old", "drxk", "drxk_terratec_h5", "tda10071",
|
||||
"it9135" );
|
||||
|
||||
# Check args
|
||||
syntax() if (scalar(@ARGV) != 1);
|
||||
@ -575,19 +576,10 @@ sub ngene {
|
||||
}
|
||||
|
||||
sub az6027{
|
||||
my $file = "AZ6027_Linux_Driver.tar.gz";
|
||||
my $url = "http://linux.terratec.de/files/$file";
|
||||
my $firmware = "dvb-usb-az6027-03.fw";
|
||||
my $url = "http://linux.terratec.de/files/TERRATEC_S7/$firmware";
|
||||
|
||||
wgetfile($file, $url);
|
||||
|
||||
#untar
|
||||
if( system("tar xzvf $file $firmware")){
|
||||
die "failed to untar firmware";
|
||||
}
|
||||
if( system("rm $file")){
|
||||
die ("unable to remove unnecessary files");
|
||||
}
|
||||
wgetfile($firmware, $url);
|
||||
|
||||
$firmware;
|
||||
}
|
||||
@ -665,6 +657,41 @@ sub drxk_terratec_h5 {
|
||||
"$fwfile"
|
||||
}
|
||||
|
||||
sub it9135 {
|
||||
my $url = "http://kworld.server261.com/kworld/CD/ITE_TiVme/V1.00/";
|
||||
my $zipfile = "Driver_V10.323.1.0412.100412.zip";
|
||||
my $hash = "79b597dc648698ed6820845c0c9d0d37";
|
||||
my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 0);
|
||||
my $drvfile = "Driver_V10.323.1.0412.100412/Data/x86/IT9135BDA.sys";
|
||||
my $fwfile = "dvb-usb-it9137-01.fw";
|
||||
|
||||
checkstandard();
|
||||
|
||||
wgetfile($zipfile, $url . $zipfile);
|
||||
verify($zipfile, $hash);
|
||||
unzip($zipfile, $tmpdir);
|
||||
extract("$tmpdir/$drvfile", 69632, 5731, "$fwfile");
|
||||
|
||||
"$fwfile"
|
||||
}
|
||||
|
||||
sub tda10071 {
|
||||
my $sourcefile = "PCTV_460e_reference.zip";
|
||||
my $url = "ftp://ftp.pctvsystems.com/TV/driver/PCTV%2070e%2080e%20100e%20320e%20330e%20800e/";
|
||||
my $hash = "4403de903bf2593464c8d74bbc200a57";
|
||||
my $fwfile = "dvb-fe-tda10071.fw";
|
||||
my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1);
|
||||
|
||||
checkstandard();
|
||||
|
||||
wgetfile($sourcefile, $url . $sourcefile);
|
||||
verify($sourcefile, $hash);
|
||||
unzip($sourcefile, $tmpdir);
|
||||
extract("$tmpdir/PCTV\ 70e\ 80e\ 100e\ 320e\ 330e\ 800e/32\ bit/emOEM.sys", 0x67d38, 40504, $fwfile);
|
||||
|
||||
"$fwfile";
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# Utilities
|
||||
|
||||
|
9
Documentation/dvb/it9137.txt
Normal file
9
Documentation/dvb/it9137.txt
Normal file
@ -0,0 +1,9 @@
|
||||
To extract firmware for Kworld UB499-2T (id 1b80:e409) you need to copy the
|
||||
following file(s) to this directory.
|
||||
|
||||
IT9135BDA.sys Dated Mon 22 Mar 2010 02:20:08 GMT
|
||||
|
||||
extract using dd
|
||||
dd if=IT9135BDA.sys ibs=1 skip=69632 count=5731 of=dvb-usb-it9137-01.fw
|
||||
|
||||
copy to default firmware location.
|
@ -495,29 +495,6 @@ Who: Jean Delvare <khali@linux-fr.org>
|
||||
|
||||
----------------------------
|
||||
|
||||
What: Support for UVCIOC_CTRL_ADD in the uvcvideo driver
|
||||
When: 3.2
|
||||
Why: The information passed to the driver by this ioctl is now queried
|
||||
dynamically from the device.
|
||||
Who: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
|
||||
----------------------------
|
||||
|
||||
What: Support for UVCIOC_CTRL_MAP_OLD in the uvcvideo driver
|
||||
When: 3.2
|
||||
Why: Used only by applications compiled against older driver versions.
|
||||
Superseded by UVCIOC_CTRL_MAP which supports V4L2 menu controls.
|
||||
Who: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
|
||||
----------------------------
|
||||
|
||||
What: Support for UVCIOC_CTRL_GET and UVCIOC_CTRL_SET in the uvcvideo driver
|
||||
When: 3.2
|
||||
Why: Superseded by the UVCIOC_CTRL_QUERY ioctl.
|
||||
Who: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
|
||||
----------------------------
|
||||
|
||||
What: Support for driver specific ioctls in the pwc driver (everything
|
||||
defined in media/pwc-ioctl.h)
|
||||
When: 3.3
|
||||
|
@ -8,6 +8,7 @@ xxxx vend:prod
|
||||
----
|
||||
spca501 0000:0000 MystFromOri Unknown Camera
|
||||
spca508 0130:0130 Clone Digital Webcam 11043
|
||||
zc3xx 03f0:1b07 HP Premium Starter Cam
|
||||
m5602 0402:5602 ALi Video Camera Controller
|
||||
spca501 040a:0002 Kodak DVC-325
|
||||
spca500 040a:0300 Kodak EZ200
|
||||
@ -190,6 +191,7 @@ ov519 05a9:0519 OV519 Microphone
|
||||
ov519 05a9:0530 OmniVision
|
||||
ov519 05a9:2800 OmniVision SuperCAM
|
||||
ov519 05a9:4519 Webcam Classic
|
||||
ov534_9 05a9:8065 OmniVision test kit ov538+ov9712
|
||||
ov519 05a9:8519 OmniVision
|
||||
ov519 05a9:a511 D-Link USB Digital Video Camera
|
||||
ov519 05a9:a518 D-Link DSB-C310 Webcam
|
||||
@ -199,6 +201,8 @@ gl860 05e3:0503 Genesys Logic PC Camera
|
||||
gl860 05e3:f191 Genesys Logic PC Camera
|
||||
spca561 060b:a001 Maxell Compact Pc PM3
|
||||
zc3xx 0698:2003 CTX M730V built in
|
||||
topro 06a2:0003 TP6800 PC Camera, CmoX CX0342 webcam
|
||||
topro 06a2:6810 Creative Qmax
|
||||
nw80x 06a5:0000 Typhoon Webcam 100 USB
|
||||
nw80x 06a5:d001 Divio based webcams
|
||||
nw80x 06a5:d800 Divio Chicony TwinkleCam, Trust SpaceCam
|
||||
|
@ -70,10 +70,11 @@ Events
|
||||
The OMAP 3 ISP driver does support the V4L2 event interface on CCDC and
|
||||
statistics (AEWB, AF and histogram) subdevs.
|
||||
|
||||
The CCDC subdev produces V4L2_EVENT_OMAP3ISP_HS_VS type event on HS_VS
|
||||
interrupt which is used to signal frame start. The event is triggered exactly
|
||||
when the reception of the first line of the frame starts in the CCDC module.
|
||||
The event can be subscribed on the CCDC subdev.
|
||||
The CCDC subdev produces V4L2_EVENT_FRAME_SYNC type event on HS_VS
|
||||
interrupt which is used to signal frame start. Earlier version of this
|
||||
driver used V4L2_EVENT_OMAP3ISP_HS_VS for this purpose. The event is
|
||||
triggered exactly when the reception of the first line of the frame starts
|
||||
in the CCDC module. The event can be subscribed on the CCDC subdev.
|
||||
|
||||
(When using parallel interface one must pay account to correct configuration
|
||||
of the VS signal polarity. This is automatically correct when using the serial
|
||||
|
@ -285,11 +285,11 @@ implement g_volatile_ctrl like this:
|
||||
Note that you use the 'new value' union as well in g_volatile_ctrl. In general
|
||||
controls that need to implement g_volatile_ctrl are read-only controls.
|
||||
|
||||
To mark a control as volatile you have to set the is_volatile flag:
|
||||
To mark a control as volatile you have to set V4L2_CTRL_FLAG_VOLATILE:
|
||||
|
||||
ctrl = v4l2_ctrl_new_std(&sd->ctrl_handler, ...);
|
||||
if (ctrl)
|
||||
ctrl->is_volatile = 1;
|
||||
ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
|
||||
|
||||
For try/s_ctrl the new values (i.e. as passed by the user) are filled in and
|
||||
you can modify them in try_ctrl or set them in s_ctrl. The 'cur' union
|
||||
@ -367,8 +367,7 @@ Driver specific controls can be created using v4l2_ctrl_new_custom():
|
||||
The last argument is the priv pointer which can be set to driver-specific
|
||||
private data.
|
||||
|
||||
The v4l2_ctrl_config struct also has fields to set the is_private and is_volatile
|
||||
flags.
|
||||
The v4l2_ctrl_config struct also has a field to set the is_private flag.
|
||||
|
||||
If the name field is not set, then the framework will assume this is a standard
|
||||
control and will fill in the name, type and flags fields accordingly.
|
||||
@ -496,18 +495,20 @@ Handling autogain/gain-type Controls with Auto Clusters
|
||||
|
||||
A common type of control cluster is one that handles 'auto-foo/foo'-type
|
||||
controls. Typical examples are autogain/gain, autoexposure/exposure,
|
||||
autowhitebalance/red balance/blue balance. In all cases you have one controls
|
||||
autowhitebalance/red balance/blue balance. In all cases you have one control
|
||||
that determines whether another control is handled automatically by the hardware,
|
||||
or whether it is under manual control from the user.
|
||||
|
||||
If the cluster is in automatic mode, then the manual controls should be
|
||||
marked inactive. When the volatile controls are read the g_volatile_ctrl
|
||||
operation should return the value that the hardware's automatic mode set up
|
||||
automatically.
|
||||
marked inactive and volatile. When the volatile controls are read the
|
||||
g_volatile_ctrl operation should return the value that the hardware's automatic
|
||||
mode set up automatically.
|
||||
|
||||
If the cluster is put in manual mode, then the manual controls should become
|
||||
active again and the is_volatile flag should be ignored (so g_volatile_ctrl is
|
||||
no longer called while in manual mode).
|
||||
active again and the volatile flag is cleared (so g_volatile_ctrl is no longer
|
||||
called while in manual mode). In addition just before switching to manual mode
|
||||
the current values as determined by the auto mode are copied as the new manual
|
||||
values.
|
||||
|
||||
Finally the V4L2_CTRL_FLAG_UPDATE should be set for the auto control since
|
||||
changing that control affects the control flags of the manual controls.
|
||||
@ -520,7 +521,11 @@ void v4l2_ctrl_auto_cluster(unsigned ncontrols, struct v4l2_ctrl **controls,
|
||||
|
||||
The first two arguments are identical to v4l2_ctrl_cluster. The third argument
|
||||
tells the framework which value switches the cluster into manual mode. The
|
||||
last argument will optionally set the is_volatile flag for the non-auto controls.
|
||||
last argument will optionally set V4L2_CTRL_FLAG_VOLATILE for the non-auto controls.
|
||||
If it is false, then the manual controls are never volatile. You would typically
|
||||
use that if the hardware does not give you the option to read back to values as
|
||||
determined by the auto mode (e.g. if autogain is on, the hardware doesn't allow
|
||||
you to obtain the current gain value).
|
||||
|
||||
The first control of the cluster is assumed to be the 'auto' control.
|
||||
|
||||
@ -681,16 +686,6 @@ if there are no controls at all.
|
||||
count if nothing was done yet. If it is less than count then only the controls
|
||||
up to error_idx-1 were successfully applied.
|
||||
|
||||
3) When attempting to read a button control the framework will return -EACCES
|
||||
instead of -EINVAL as stated in the spec. It seems to make more sense since
|
||||
button controls are write-only controls.
|
||||
|
||||
4) Attempting to write to a read-only control will return -EACCES instead of
|
||||
-EINVAL as the spec says.
|
||||
|
||||
5) The spec does not mention what should happen when you try to set/get a
|
||||
control class controls. The framework will return -EACCES.
|
||||
|
||||
|
||||
Proposals for Extensions
|
||||
========================
|
||||
@ -703,9 +698,3 @@ decimal. Useful for e.g. video_mute_yuv.
|
||||
2) It is possible to mark in the controls array which controls have been
|
||||
successfully written and which failed by for example adding a bit to the
|
||||
control ID. Not sure if it is worth the effort, though.
|
||||
|
||||
3) Trying to set volatile inactive controls should result in -EACCESS.
|
||||
|
||||
4) Add a new flag to mark volatile controls. Any application that wants
|
||||
to store the state of the controls can then skip volatile inactive controls.
|
||||
Currently it is not possible to detect such controls.
|
||||
|
18
MAINTAINERS
18
MAINTAINERS
@ -1085,6 +1085,24 @@ F: arch/arm/plat-s5p/dev-fimc*
|
||||
F: arch/arm/plat-samsung/include/plat/*fimc*
|
||||
F: drivers/media/video/s5p-fimc/
|
||||
|
||||
ARM/SAMSUNG S5P SERIES Multi Format Codec (MFC) SUPPORT
|
||||
M: Kyungmin Park <kyungmin.park@samsung.com>
|
||||
M: Kamil Debski <k.debski@samsung.com>
|
||||
L: linux-arm-kernel@lists.infradead.org
|
||||
L: linux-media@vger.kernel.org
|
||||
S: Maintained
|
||||
F: arch/arm/plat-s5p/dev-mfc.c
|
||||
F: drivers/media/video/s5p-mfc/
|
||||
|
||||
ARM/SAMSUNG S5P SERIES TV SUBSYSTEM SUPPORT
|
||||
M: Kyungmin Park <kyungmin.park@samsung.com>
|
||||
M: Tomasz Stanislawski <t.stanislaws@samsung.com>
|
||||
L: linux-arm-kernel@lists.infradead.org
|
||||
L: linux-media@vger.kernel.org
|
||||
S: Maintained
|
||||
F: arch/arm/plat-s5p/dev-tv.c
|
||||
F: drivers/media/video/s5p-tv/
|
||||
|
||||
ARM/SHMOBILE ARM ARCHITECTURE
|
||||
M: Paul Mundt <lethal@linux-sh.org>
|
||||
M: Magnus Damm <magnus.damm@gmail.com>
|
||||
|
@ -217,22 +217,6 @@ config INPUT_ATLAS_BTNS
|
||||
To compile this driver as a module, choose M here: the module will
|
||||
be called atlas_btns.
|
||||
|
||||
config INPUT_ATI_REMOTE
|
||||
tristate "ATI / X10 USB RF remote control"
|
||||
depends on USB_ARCH_HAS_HCD
|
||||
select USB
|
||||
help
|
||||
Say Y here if you want to use an ATI or X10 "Lola" USB remote control.
|
||||
These are RF remotes with USB receivers.
|
||||
The ATI remote comes with many of ATI's All-In-Wonder video cards.
|
||||
The X10 "Lola" remote is available at:
|
||||
<http://www.x10.com/products/lola_sg1.htm>
|
||||
This driver provides mouse pointer, left and right mouse buttons,
|
||||
and maps all the other remote buttons to keypress events.
|
||||
|
||||
To compile this driver as a module, choose M here: the module will be
|
||||
called ati_remote.
|
||||
|
||||
config INPUT_ATI_REMOTE2
|
||||
tristate "ATI / Philips USB RF remote control"
|
||||
depends on USB_ARCH_HAS_HCD
|
||||
|
@ -13,7 +13,6 @@ obj-$(CONFIG_INPUT_ADXL34X) += adxl34x.o
|
||||
obj-$(CONFIG_INPUT_ADXL34X_I2C) += adxl34x-i2c.o
|
||||
obj-$(CONFIG_INPUT_ADXL34X_SPI) += adxl34x-spi.o
|
||||
obj-$(CONFIG_INPUT_APANEL) += apanel.o
|
||||
obj-$(CONFIG_INPUT_ATI_REMOTE) += ati_remote.o
|
||||
obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o
|
||||
obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o
|
||||
obj-$(CONFIG_INPUT_BFIN_ROTARY) += bfin_rotary.o
|
||||
|
@ -18,6 +18,8 @@
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <media/saa7146.h>
|
||||
|
||||
LIST_HEAD(saa7146_devices);
|
||||
@ -35,10 +37,9 @@ static void dump_registers(struct saa7146_dev* dev)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
INFO((" @ %li jiffies:\n",jiffies));
|
||||
for(i = 0; i <= 0x148; i+=4) {
|
||||
printk("0x%03x: 0x%08x\n",i,saa7146_read(dev,i));
|
||||
}
|
||||
pr_info(" @ %li jiffies:\n", jiffies);
|
||||
for (i = 0; i <= 0x148; i += 4)
|
||||
pr_info("0x%03x: 0x%08x\n", i, saa7146_read(dev, i));
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -72,9 +73,8 @@ static inline int saa7146_wait_for_debi_done_sleep(struct saa7146_dev *dev,
|
||||
if (saa7146_read(dev, MC2) & 2)
|
||||
break;
|
||||
if (err) {
|
||||
printk(KERN_ERR "%s: %s timed out while waiting for "
|
||||
"registers getting programmed\n",
|
||||
dev->name, __func__);
|
||||
pr_err("%s: %s timed out while waiting for registers getting programmed\n",
|
||||
dev->name, __func__);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
msleep(1);
|
||||
@ -88,8 +88,8 @@ static inline int saa7146_wait_for_debi_done_sleep(struct saa7146_dev *dev,
|
||||
break;
|
||||
saa7146_read(dev, MC2);
|
||||
if (err) {
|
||||
DEB_S(("%s: %s timed out while waiting for transfer "
|
||||
"completion\n", dev->name, __func__));
|
||||
DEB_S("%s: %s timed out while waiting for transfer completion\n",
|
||||
dev->name, __func__);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
msleep(1);
|
||||
@ -109,9 +109,8 @@ static inline int saa7146_wait_for_debi_done_busyloop(struct saa7146_dev *dev,
|
||||
if (saa7146_read(dev, MC2) & 2)
|
||||
break;
|
||||
if (!loops--) {
|
||||
printk(KERN_ERR "%s: %s timed out while waiting for "
|
||||
"registers getting programmed\n",
|
||||
dev->name, __func__);
|
||||
pr_err("%s: %s timed out while waiting for registers getting programmed\n",
|
||||
dev->name, __func__);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
udelay(1);
|
||||
@ -124,8 +123,8 @@ static inline int saa7146_wait_for_debi_done_busyloop(struct saa7146_dev *dev,
|
||||
break;
|
||||
saa7146_read(dev, MC2);
|
||||
if (!loops--) {
|
||||
DEB_S(("%s: %s timed out while waiting for transfer "
|
||||
"completion\n", dev->name, __func__));
|
||||
DEB_S("%s: %s timed out while waiting for transfer completion\n",
|
||||
dev->name, __func__);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
udelay(5);
|
||||
@ -264,7 +263,9 @@ int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt
|
||||
ptr = pt->cpu;
|
||||
for (i = 0; i < sglen; i++, list++) {
|
||||
/*
|
||||
printk("i:%d, adr:0x%08x, len:%d, offset:%d\n", i,sg_dma_address(list), sg_dma_len(list), list->offset);
|
||||
pr_debug("i:%d, adr:0x%08x, len:%d, offset:%d\n",
|
||||
i, sg_dma_address(list), sg_dma_len(list),
|
||||
list->offset);
|
||||
*/
|
||||
for (p = 0; p * 4096 < list->length; p++, ptr++) {
|
||||
*ptr = cpu_to_le32(sg_dma_address(list) + p * 4096);
|
||||
@ -281,9 +282,9 @@ int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt
|
||||
|
||||
/*
|
||||
ptr = pt->cpu;
|
||||
printk("offset: %d\n",pt->offset);
|
||||
pr_debug("offset: %d\n", pt->offset);
|
||||
for(i=0;i<5;i++) {
|
||||
printk("ptr1 %d: 0x%08x\n",i,ptr[i]);
|
||||
pr_debug("ptr1 %d: 0x%08x\n", i, ptr[i]);
|
||||
}
|
||||
*/
|
||||
return 0;
|
||||
@ -314,7 +315,7 @@ static irqreturn_t interrupt_hw(int irq, void *dev_id)
|
||||
}
|
||||
}
|
||||
if (0 != (isr & (MASK_27))) {
|
||||
DEB_INT(("irq: RPS0 (0x%08x).\n",isr));
|
||||
DEB_INT("irq: RPS0 (0x%08x)\n", isr);
|
||||
if (dev->vv_data && dev->vv_callback)
|
||||
dev->vv_callback(dev,isr);
|
||||
isr &= ~MASK_27;
|
||||
@ -333,14 +334,15 @@ static irqreturn_t interrupt_hw(int irq, void *dev_id)
|
||||
} else {
|
||||
u32 psr = saa7146_read(dev, PSR);
|
||||
u32 ssr = saa7146_read(dev, SSR);
|
||||
printk(KERN_WARNING "%s: unexpected i2c irq: isr %08x psr %08x ssr %08x\n",
|
||||
dev->name, isr, psr, ssr);
|
||||
pr_warn("%s: unexpected i2c irq: isr %08x psr %08x ssr %08x\n",
|
||||
dev->name, isr, psr, ssr);
|
||||
}
|
||||
isr &= ~(MASK_16|MASK_17);
|
||||
}
|
||||
if( 0 != isr ) {
|
||||
ERR(("warning: interrupt enabled, but not handled properly.(0x%08x)\n",isr));
|
||||
ERR(("disabling interrupt source(s)!\n"));
|
||||
ERR("warning: interrupt enabled, but not handled properly.(0x%08x)\n",
|
||||
isr);
|
||||
ERR("disabling interrupt source(s)!\n");
|
||||
SAA7146_IER_DISABLE(dev,isr);
|
||||
}
|
||||
saa7146_write(dev, ISR, ack_isr);
|
||||
@ -360,15 +362,15 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
|
||||
/* clear out mem for sure */
|
||||
dev = kzalloc(sizeof(struct saa7146_dev), GFP_KERNEL);
|
||||
if (!dev) {
|
||||
ERR(("out of memory.\n"));
|
||||
ERR("out of memory\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
DEB_EE(("pci:%p\n",pci));
|
||||
DEB_EE("pci:%p\n", pci);
|
||||
|
||||
err = pci_enable_device(pci);
|
||||
if (err < 0) {
|
||||
ERR(("pci_enable_device() failed.\n"));
|
||||
ERR("pci_enable_device() failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
@ -389,7 +391,7 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
|
||||
dev->mem = ioremap(pci_resource_start(pci, 0),
|
||||
pci_resource_len(pci, 0));
|
||||
if (!dev->mem) {
|
||||
ERR(("ioremap() failed.\n"));
|
||||
ERR("ioremap() failed\n");
|
||||
err = -ENODEV;
|
||||
goto err_release;
|
||||
}
|
||||
@ -414,7 +416,7 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
|
||||
err = request_irq(pci->irq, interrupt_hw, IRQF_SHARED | IRQF_DISABLED,
|
||||
dev->name, dev);
|
||||
if (err < 0) {
|
||||
ERR(("request_irq() failed.\n"));
|
||||
ERR("request_irq() failed\n");
|
||||
goto err_unmap;
|
||||
}
|
||||
|
||||
@ -444,7 +446,9 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
|
||||
/* create a nice device name */
|
||||
sprintf(dev->name, "saa7146 (%d)", saa7146_num);
|
||||
|
||||
INFO(("found saa7146 @ mem %p (revision %d, irq %d) (0x%04x,0x%04x).\n", dev->mem, dev->revision, pci->irq, pci->subsystem_vendor, pci->subsystem_device));
|
||||
pr_info("found saa7146 @ mem %p (revision %d, irq %d) (0x%04x,0x%04x)\n",
|
||||
dev->mem, dev->revision, pci->irq,
|
||||
pci->subsystem_vendor, pci->subsystem_device);
|
||||
dev->ext = ext;
|
||||
|
||||
mutex_init(&dev->v4l2_lock);
|
||||
@ -464,12 +468,12 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
|
||||
err = -ENODEV;
|
||||
|
||||
if (ext->probe && ext->probe(dev)) {
|
||||
DEB_D(("ext->probe() failed for %p. skipping device.\n",dev));
|
||||
DEB_D("ext->probe() failed for %p. skipping device.\n", dev);
|
||||
goto err_free_i2c;
|
||||
}
|
||||
|
||||
if (ext->attach(dev, pci_ext)) {
|
||||
DEB_D(("ext->attach() failed for %p. skipping device.\n",dev));
|
||||
DEB_D("ext->attach() failed for %p. skipping device.\n", dev);
|
||||
goto err_free_i2c;
|
||||
}
|
||||
/* V4L extensions will set the pci drvdata to the v4l2_device in the
|
||||
@ -521,7 +525,7 @@ static void saa7146_remove_one(struct pci_dev *pdev)
|
||||
{ NULL, 0 }
|
||||
}, *p;
|
||||
|
||||
DEB_EE(("dev:%p\n",dev));
|
||||
DEB_EE("dev:%p\n", dev);
|
||||
|
||||
dev->ext->detach(dev);
|
||||
/* Zero the PCI drvdata after use. */
|
||||
@ -552,21 +556,21 @@ static void saa7146_remove_one(struct pci_dev *pdev)
|
||||
|
||||
int saa7146_register_extension(struct saa7146_extension* ext)
|
||||
{
|
||||
DEB_EE(("ext:%p\n",ext));
|
||||
DEB_EE("ext:%p\n", ext);
|
||||
|
||||
ext->driver.name = ext->name;
|
||||
ext->driver.id_table = ext->pci_tbl;
|
||||
ext->driver.probe = saa7146_init_one;
|
||||
ext->driver.remove = saa7146_remove_one;
|
||||
|
||||
printk("saa7146: register extension '%s'.\n",ext->name);
|
||||
pr_info("register extension '%s'\n", ext->name);
|
||||
return pci_register_driver(&ext->driver);
|
||||
}
|
||||
|
||||
int saa7146_unregister_extension(struct saa7146_extension* ext)
|
||||
{
|
||||
DEB_EE(("ext:%p\n",ext));
|
||||
printk("saa7146: unregister extension '%s'.\n",ext->name);
|
||||
DEB_EE("ext:%p\n", ext);
|
||||
pr_info("unregister extension '%s'\n", ext->name);
|
||||
pci_unregister_driver(&ext->driver);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <media/saa7146_vv.h>
|
||||
|
||||
/****************************************************************************/
|
||||
@ -9,21 +11,23 @@ int saa7146_res_get(struct saa7146_fh *fh, unsigned int bit)
|
||||
struct saa7146_vv *vv = dev->vv_data;
|
||||
|
||||
if (fh->resources & bit) {
|
||||
DEB_D(("already allocated! want: 0x%02x, cur:0x%02x\n",bit,vv->resources));
|
||||
DEB_D("already allocated! want: 0x%02x, cur:0x%02x\n",
|
||||
bit, vv->resources);
|
||||
/* have it already allocated */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* is it free? */
|
||||
if (vv->resources & bit) {
|
||||
DEB_D(("locked! vv->resources:0x%02x, we want:0x%02x\n",vv->resources,bit));
|
||||
DEB_D("locked! vv->resources:0x%02x, we want:0x%02x\n",
|
||||
vv->resources, bit);
|
||||
/* no, someone else uses it */
|
||||
return 0;
|
||||
}
|
||||
/* it's free, grab it */
|
||||
fh->resources |= bit;
|
||||
fh->resources |= bit;
|
||||
vv->resources |= bit;
|
||||
DEB_D(("res: get 0x%02x, cur:0x%02x\n",bit,vv->resources));
|
||||
DEB_D("res: get 0x%02x, cur:0x%02x\n", bit, vv->resources);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -34,9 +38,9 @@ void saa7146_res_free(struct saa7146_fh *fh, unsigned int bits)
|
||||
|
||||
BUG_ON((fh->resources & bits) != bits);
|
||||
|
||||
fh->resources &= ~bits;
|
||||
fh->resources &= ~bits;
|
||||
vv->resources &= ~bits;
|
||||
DEB_D(("res: put 0x%02x, cur:0x%02x\n",bits,vv->resources));
|
||||
DEB_D("res: put 0x%02x, cur:0x%02x\n", bits, vv->resources);
|
||||
}
|
||||
|
||||
|
||||
@ -47,7 +51,7 @@ void saa7146_dma_free(struct saa7146_dev *dev,struct videobuf_queue *q,
|
||||
struct saa7146_buf *buf)
|
||||
{
|
||||
struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
|
||||
DEB_EE(("dev:%p, buf:%p\n",dev,buf));
|
||||
DEB_EE("dev:%p, buf:%p\n", dev, buf);
|
||||
|
||||
BUG_ON(in_interrupt());
|
||||
|
||||
@ -66,18 +70,19 @@ int saa7146_buffer_queue(struct saa7146_dev *dev,
|
||||
struct saa7146_buf *buf)
|
||||
{
|
||||
assert_spin_locked(&dev->slock);
|
||||
DEB_EE(("dev:%p, dmaq:%p, buf:%p\n", dev, q, buf));
|
||||
DEB_EE("dev:%p, dmaq:%p, buf:%p\n", dev, q, buf);
|
||||
|
||||
BUG_ON(!q);
|
||||
|
||||
if (NULL == q->curr) {
|
||||
q->curr = buf;
|
||||
DEB_D(("immediately activating buffer %p\n", buf));
|
||||
DEB_D("immediately activating buffer %p\n", buf);
|
||||
buf->activate(dev,buf,NULL);
|
||||
} else {
|
||||
list_add_tail(&buf->vb.queue,&q->queue);
|
||||
buf->vb.state = VIDEOBUF_QUEUED;
|
||||
DEB_D(("adding buffer %p to queue. (active buffer present)\n", buf));
|
||||
DEB_D("adding buffer %p to queue. (active buffer present)\n",
|
||||
buf);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -87,14 +92,14 @@ void saa7146_buffer_finish(struct saa7146_dev *dev,
|
||||
int state)
|
||||
{
|
||||
assert_spin_locked(&dev->slock);
|
||||
DEB_EE(("dev:%p, dmaq:%p, state:%d\n", dev, q, state));
|
||||
DEB_EE(("q->curr:%p\n",q->curr));
|
||||
DEB_EE("dev:%p, dmaq:%p, state:%d\n", dev, q, state);
|
||||
DEB_EE("q->curr:%p\n", q->curr);
|
||||
|
||||
BUG_ON(!q->curr);
|
||||
|
||||
/* finish current buffer */
|
||||
if (NULL == q->curr) {
|
||||
DEB_D(("aiii. no current buffer\n"));
|
||||
DEB_D("aiii. no current buffer\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -112,7 +117,7 @@ void saa7146_buffer_next(struct saa7146_dev *dev,
|
||||
|
||||
BUG_ON(!q);
|
||||
|
||||
DEB_INT(("dev:%p, dmaq:%p, vbi:%d\n", dev, q, vbi));
|
||||
DEB_INT("dev:%p, dmaq:%p, vbi:%d\n", dev, q, vbi);
|
||||
|
||||
assert_spin_locked(&dev->slock);
|
||||
if (!list_empty(&q->queue)) {
|
||||
@ -122,10 +127,11 @@ void saa7146_buffer_next(struct saa7146_dev *dev,
|
||||
if (!list_empty(&q->queue))
|
||||
next = list_entry(q->queue.next,struct saa7146_buf, vb.queue);
|
||||
q->curr = buf;
|
||||
DEB_INT(("next buffer: buf:%p, prev:%p, next:%p\n", buf, q->queue.prev,q->queue.next));
|
||||
DEB_INT("next buffer: buf:%p, prev:%p, next:%p\n",
|
||||
buf, q->queue.prev, q->queue.next);
|
||||
buf->activate(dev,buf,next);
|
||||
} else {
|
||||
DEB_INT(("no next buffer. stopping.\n"));
|
||||
DEB_INT("no next buffer. stopping.\n");
|
||||
if( 0 != vbi ) {
|
||||
/* turn off video-dma3 */
|
||||
saa7146_write(dev,MC1, MASK_20);
|
||||
@ -162,11 +168,11 @@ void saa7146_buffer_timeout(unsigned long data)
|
||||
struct saa7146_dev *dev = q->dev;
|
||||
unsigned long flags;
|
||||
|
||||
DEB_EE(("dev:%p, dmaq:%p\n", dev, q));
|
||||
DEB_EE("dev:%p, dmaq:%p\n", dev, q);
|
||||
|
||||
spin_lock_irqsave(&dev->slock,flags);
|
||||
if (q->curr) {
|
||||
DEB_D(("timeout on %p\n", q->curr));
|
||||
DEB_D("timeout on %p\n", q->curr);
|
||||
saa7146_buffer_finish(dev,q,VIDEOBUF_ERROR);
|
||||
}
|
||||
|
||||
@ -194,12 +200,12 @@ static int fops_open(struct file *file)
|
||||
|
||||
enum v4l2_buf_type type;
|
||||
|
||||
DEB_EE(("file:%p, dev:%s\n", file, video_device_node_name(vdev)));
|
||||
DEB_EE("file:%p, dev:%s\n", file, video_device_node_name(vdev));
|
||||
|
||||
if (mutex_lock_interruptible(&saa7146_devices_lock))
|
||||
return -ERESTARTSYS;
|
||||
|
||||
DEB_D(("using: %p\n",dev));
|
||||
DEB_D("using: %p\n", dev);
|
||||
|
||||
type = vdev->vfl_type == VFL_TYPE_GRABBER
|
||||
? V4L2_BUF_TYPE_VIDEO_CAPTURE
|
||||
@ -207,7 +213,7 @@ static int fops_open(struct file *file)
|
||||
|
||||
/* check if an extension is registered */
|
||||
if( NULL == dev->ext ) {
|
||||
DEB_S(("no extension registered for this device.\n"));
|
||||
DEB_S("no extension registered for this device\n");
|
||||
result = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
@ -215,7 +221,7 @@ static int fops_open(struct file *file)
|
||||
/* allocate per open data */
|
||||
fh = kzalloc(sizeof(*fh),GFP_KERNEL);
|
||||
if (NULL == fh) {
|
||||
DEB_S(("cannot allocate memory for per open data.\n"));
|
||||
DEB_S("cannot allocate memory for per open data\n");
|
||||
result = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
@ -225,13 +231,13 @@ static int fops_open(struct file *file)
|
||||
fh->type = type;
|
||||
|
||||
if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
|
||||
DEB_S(("initializing vbi...\n"));
|
||||
DEB_S("initializing vbi...\n");
|
||||
if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
|
||||
result = saa7146_vbi_uops.open(dev,file);
|
||||
if (dev->ext_vv_data->vbi_fops.open)
|
||||
dev->ext_vv_data->vbi_fops.open(file);
|
||||
} else {
|
||||
DEB_S(("initializing video...\n"));
|
||||
DEB_S("initializing video...\n");
|
||||
result = saa7146_video_uops.open(dev,file);
|
||||
}
|
||||
|
||||
@ -259,7 +265,7 @@ static int fops_release(struct file *file)
|
||||
struct saa7146_fh *fh = file->private_data;
|
||||
struct saa7146_dev *dev = fh->dev;
|
||||
|
||||
DEB_EE(("file:%p\n", file));
|
||||
DEB_EE("file:%p\n", file);
|
||||
|
||||
if (mutex_lock_interruptible(&saa7146_devices_lock))
|
||||
return -ERESTARTSYS;
|
||||
@ -289,12 +295,14 @@ static int fops_mmap(struct file *file, struct vm_area_struct * vma)
|
||||
|
||||
switch (fh->type) {
|
||||
case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
|
||||
DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, vma:%p\n",file, vma));
|
||||
DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, vma:%p\n",
|
||||
file, vma);
|
||||
q = &fh->video_q;
|
||||
break;
|
||||
}
|
||||
case V4L2_BUF_TYPE_VBI_CAPTURE: {
|
||||
DEB_EE(("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, vma:%p\n",file, vma));
|
||||
DEB_EE("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, vma:%p\n",
|
||||
file, vma);
|
||||
q = &fh->vbi_q;
|
||||
break;
|
||||
}
|
||||
@ -312,14 +320,14 @@ static unsigned int fops_poll(struct file *file, struct poll_table_struct *wait)
|
||||
struct videobuf_buffer *buf = NULL;
|
||||
struct videobuf_queue *q;
|
||||
|
||||
DEB_EE(("file:%p, poll:%p\n",file, wait));
|
||||
DEB_EE("file:%p, poll:%p\n", file, wait);
|
||||
|
||||
if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
|
||||
if( 0 == fh->vbi_q.streaming )
|
||||
return videobuf_poll_stream(file, &fh->vbi_q, wait);
|
||||
q = &fh->vbi_q;
|
||||
} else {
|
||||
DEB_D(("using video queue.\n"));
|
||||
DEB_D("using video queue\n");
|
||||
q = &fh->video_q;
|
||||
}
|
||||
|
||||
@ -327,17 +335,17 @@ static unsigned int fops_poll(struct file *file, struct poll_table_struct *wait)
|
||||
buf = list_entry(q->stream.next, struct videobuf_buffer, stream);
|
||||
|
||||
if (!buf) {
|
||||
DEB_D(("buf == NULL!\n"));
|
||||
DEB_D("buf == NULL!\n");
|
||||
return POLLERR;
|
||||
}
|
||||
|
||||
poll_wait(file, &buf->done, wait);
|
||||
if (buf->state == VIDEOBUF_DONE || buf->state == VIDEOBUF_ERROR) {
|
||||
DEB_D(("poll succeeded!\n"));
|
||||
DEB_D("poll succeeded!\n");
|
||||
return POLLIN|POLLRDNORM;
|
||||
}
|
||||
|
||||
DEB_D(("nothing to poll for, buf->state:%d\n",buf->state));
|
||||
DEB_D("nothing to poll for, buf->state:%d\n", buf->state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -346,18 +354,20 @@ static ssize_t fops_read(struct file *file, char __user *data, size_t count, lof
|
||||
struct saa7146_fh *fh = file->private_data;
|
||||
|
||||
switch (fh->type) {
|
||||
case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
|
||||
// DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, data:%p, count:%lun", file, data, (unsigned long)count));
|
||||
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
|
||||
/*
|
||||
DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, data:%p, count:%lun",
|
||||
file, data, (unsigned long)count);
|
||||
*/
|
||||
return saa7146_video_uops.read(file,data,count,ppos);
|
||||
}
|
||||
case V4L2_BUF_TYPE_VBI_CAPTURE: {
|
||||
// DEB_EE(("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%lu\n", file, data, (unsigned long)count));
|
||||
case V4L2_BUF_TYPE_VBI_CAPTURE:
|
||||
/*
|
||||
DEB_EE("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%lu\n",
|
||||
file, data, (unsigned long)count);
|
||||
*/
|
||||
if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
|
||||
return saa7146_vbi_uops.read(file,data,count,ppos);
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
return -EINVAL;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
@ -398,22 +408,22 @@ static void vv_callback(struct saa7146_dev *dev, unsigned long status)
|
||||
{
|
||||
u32 isr = status;
|
||||
|
||||
DEB_INT(("dev:%p, isr:0x%08x\n",dev,(u32)status));
|
||||
DEB_INT("dev:%p, isr:0x%08x\n", dev, (u32)status);
|
||||
|
||||
if (0 != (isr & (MASK_27))) {
|
||||
DEB_INT(("irq: RPS0 (0x%08x).\n",isr));
|
||||
DEB_INT("irq: RPS0 (0x%08x)\n", isr);
|
||||
saa7146_video_uops.irq_done(dev,isr);
|
||||
}
|
||||
|
||||
if (0 != (isr & (MASK_28))) {
|
||||
u32 mc2 = saa7146_read(dev, MC2);
|
||||
if( 0 != (mc2 & MASK_15)) {
|
||||
DEB_INT(("irq: RPS1 vbi workaround (0x%08x).\n",isr));
|
||||
DEB_INT("irq: RPS1 vbi workaround (0x%08x)\n", isr);
|
||||
wake_up(&dev->vv_data->vbi_wq);
|
||||
saa7146_write(dev,MC2, MASK_31);
|
||||
return;
|
||||
}
|
||||
DEB_INT(("irq: RPS1 (0x%08x).\n",isr));
|
||||
DEB_INT("irq: RPS1 (0x%08x)\n", isr);
|
||||
saa7146_vbi_uops.irq_done(dev,isr);
|
||||
}
|
||||
}
|
||||
@ -429,13 +439,13 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
|
||||
|
||||
vv = kzalloc(sizeof(struct saa7146_vv), GFP_KERNEL);
|
||||
if (vv == NULL) {
|
||||
ERR(("out of memory. aborting.\n"));
|
||||
ERR("out of memory. aborting.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
ext_vv->ops = saa7146_video_ioctl_ops;
|
||||
ext_vv->core_ops = &saa7146_video_ioctl_ops;
|
||||
|
||||
DEB_EE(("dev:%p\n",dev));
|
||||
DEB_EE("dev:%p\n", dev);
|
||||
|
||||
/* set default values for video parts of the saa7146 */
|
||||
saa7146_write(dev, BCS_CTRL, 0x80400040);
|
||||
@ -450,7 +460,7 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
|
||||
|
||||
vv->d_clipping.cpu_addr = pci_alloc_consistent(dev->pci, SAA7146_CLIPPING_MEM, &vv->d_clipping.dma_handle);
|
||||
if( NULL == vv->d_clipping.cpu_addr ) {
|
||||
ERR(("out of memory. aborting.\n"));
|
||||
ERR("out of memory. aborting.\n");
|
||||
kfree(vv);
|
||||
return -1;
|
||||
}
|
||||
@ -471,7 +481,7 @@ int saa7146_vv_release(struct saa7146_dev* dev)
|
||||
{
|
||||
struct saa7146_vv *vv = dev->vv_data;
|
||||
|
||||
DEB_EE(("dev:%p\n",dev));
|
||||
DEB_EE("dev:%p\n", dev);
|
||||
|
||||
v4l2_device_unregister(&dev->v4l2_dev);
|
||||
pci_free_consistent(dev->pci, SAA7146_CLIPPING_MEM, vv->d_clipping.cpu_addr, vv->d_clipping.dma_handle);
|
||||
@ -490,7 +500,7 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
|
||||
int err;
|
||||
int i;
|
||||
|
||||
DEB_EE(("dev:%p, name:'%s', type:%d\n",dev,name,type));
|
||||
DEB_EE("dev:%p, name:'%s', type:%d\n", dev, name, type);
|
||||
|
||||
// released by vfd->release
|
||||
vfd = video_device_alloc();
|
||||
@ -509,13 +519,13 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
|
||||
|
||||
err = video_register_device(vfd, type, -1);
|
||||
if (err < 0) {
|
||||
ERR(("cannot register v4l2 device. skipping.\n"));
|
||||
ERR("cannot register v4l2 device. skipping.\n");
|
||||
video_device_release(vfd);
|
||||
return err;
|
||||
}
|
||||
|
||||
INFO(("%s: registered device %s [v4l2]\n",
|
||||
dev->name, video_device_node_name(vfd)));
|
||||
pr_info("%s: registered device %s [v4l2]\n",
|
||||
dev->name, video_device_node_name(vfd));
|
||||
|
||||
*vid = vfd;
|
||||
return 0;
|
||||
@ -524,7 +534,7 @@ EXPORT_SYMBOL_GPL(saa7146_register_device);
|
||||
|
||||
int saa7146_unregister_device(struct video_device **vid, struct saa7146_dev* dev)
|
||||
{
|
||||
DEB_EE(("dev:%p\n",dev));
|
||||
DEB_EE("dev:%p\n", dev);
|
||||
|
||||
video_unregister_device(*vid);
|
||||
*vid = NULL;
|
||||
|
@ -1,3 +1,5 @@
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <media/saa7146_vv.h>
|
||||
|
||||
@ -711,8 +713,8 @@ static int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa71
|
||||
|
||||
int depth = sfmt->depth;
|
||||
|
||||
DEB_CAP(("[size=%dx%d,fields=%s]\n",
|
||||
width,height,v4l2_field_names[field]));
|
||||
DEB_CAP("[size=%dx%d,fields=%s]\n",
|
||||
width, height, v4l2_field_names[field]);
|
||||
|
||||
if( bytesperline != 0) {
|
||||
vdma1.pitch = bytesperline*2;
|
||||
@ -837,8 +839,8 @@ static int calculate_video_dma_grab_planar(struct saa7146_dev* dev, struct saa71
|
||||
BUG_ON(0 == buf->pt[1].dma);
|
||||
BUG_ON(0 == buf->pt[2].dma);
|
||||
|
||||
DEB_CAP(("[size=%dx%d,fields=%s]\n",
|
||||
width,height,v4l2_field_names[field]));
|
||||
DEB_CAP("[size=%dx%d,fields=%s]\n",
|
||||
width, height, v4l2_field_names[field]);
|
||||
|
||||
/* fixme: look at bytesperline! */
|
||||
|
||||
@ -998,12 +1000,12 @@ void saa7146_set_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struc
|
||||
struct saa7146_vv *vv = dev->vv_data;
|
||||
u32 vdma1_prot_addr;
|
||||
|
||||
DEB_CAP(("buf:%p, next:%p\n",buf,next));
|
||||
DEB_CAP("buf:%p, next:%p\n", buf, next);
|
||||
|
||||
vdma1_prot_addr = saa7146_read(dev, PROT_ADDR1);
|
||||
if( 0 == vdma1_prot_addr ) {
|
||||
/* clear out beginning of streaming bit (rps register 0)*/
|
||||
DEB_CAP(("forcing sync to new frame\n"));
|
||||
DEB_CAP("forcing sync to new frame\n");
|
||||
saa7146_write(dev, MC2, MASK_27 );
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,10 @@
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <media/saa7146_vv.h>
|
||||
|
||||
static u32 saa7146_i2c_func(struct i2c_adapter *adapter)
|
||||
{
|
||||
//fm DEB_I2C(("'%s'.\n", adapter->name));
|
||||
/* DEB_I2C("'%s'\n", adapter->name); */
|
||||
|
||||
return I2C_FUNC_I2C
|
||||
| I2C_FUNC_SMBUS_QUICK
|
||||
@ -14,9 +16,7 @@ static u32 saa7146_i2c_func(struct i2c_adapter *adapter)
|
||||
static inline u32 saa7146_i2c_status(struct saa7146_dev *dev)
|
||||
{
|
||||
u32 iicsta = saa7146_read(dev, I2C_STATUS);
|
||||
/*
|
||||
DEB_I2C(("status: 0x%08x\n",iicsta));
|
||||
*/
|
||||
/* DEB_I2C("status: 0x%08x\n", iicsta); */
|
||||
return iicsta;
|
||||
}
|
||||
|
||||
@ -39,10 +39,11 @@ static int saa7146_i2c_msg_prepare(const struct i2c_msg *m, int num, __le32 *op)
|
||||
plus one extra byte to address the device */
|
||||
mem = 1 + ((mem-1) / 3);
|
||||
|
||||
/* we assume that op points to a memory of at least SAA7146_I2C_MEM bytes
|
||||
size. if we exceed this limit... */
|
||||
if ( (4*mem) > SAA7146_I2C_MEM ) {
|
||||
//fm DEB_I2C(("cannot prepare i2c-message.\n"));
|
||||
/* we assume that op points to a memory of at least
|
||||
* SAA7146_I2C_MEM bytes size. if we exceed this limit...
|
||||
*/
|
||||
if ((4 * mem) > SAA7146_I2C_MEM) {
|
||||
/* DEB_I2C("cannot prepare i2c-message\n"); */
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@ -123,7 +124,7 @@ static int saa7146_i2c_reset(struct saa7146_dev *dev)
|
||||
if ( 0 != ( status & SAA7146_I2C_BUSY) ) {
|
||||
|
||||
/* yes, kill ongoing operation */
|
||||
DEB_I2C(("busy_state detected.\n"));
|
||||
DEB_I2C("busy_state detected\n");
|
||||
|
||||
/* set "ABORT-OPERATION"-bit (bit 7)*/
|
||||
saa7146_write(dev, I2C_STATUS, (dev->i2c_bitrate | MASK_07));
|
||||
@ -141,7 +142,7 @@ static int saa7146_i2c_reset(struct saa7146_dev *dev)
|
||||
|
||||
if ( dev->i2c_bitrate != status ) {
|
||||
|
||||
DEB_I2C(("error_state detected. status:0x%08x\n",status));
|
||||
DEB_I2C("error_state detected. status:0x%08x\n", status);
|
||||
|
||||
/* Repeat the abort operation. This seems to be necessary
|
||||
after serious protocol errors caused by e.g. the SAA7740 */
|
||||
@ -164,7 +165,7 @@ static int saa7146_i2c_reset(struct saa7146_dev *dev)
|
||||
/* if any error is still present, a fatal error has occurred ... */
|
||||
status = saa7146_i2c_status(dev);
|
||||
if ( dev->i2c_bitrate != status ) {
|
||||
DEB_I2C(("fatal error. status:0x%08x\n",status));
|
||||
DEB_I2C("fatal error. status:0x%08x\n", status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -181,7 +182,8 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, __le32 *dword, int shor
|
||||
unsigned long timeout;
|
||||
|
||||
/* write out i2c-command */
|
||||
DEB_I2C(("before: 0x%08x (status: 0x%08x), %d\n",*dword,saa7146_read(dev, I2C_STATUS), dev->i2c_op));
|
||||
DEB_I2C("before: 0x%08x (status: 0x%08x), %d\n",
|
||||
*dword, saa7146_read(dev, I2C_STATUS), dev->i2c_op);
|
||||
|
||||
if( 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags)) {
|
||||
|
||||
@ -202,7 +204,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, __le32 *dword, int shor
|
||||
/* a signal arrived */
|
||||
return -ERESTARTSYS;
|
||||
|
||||
printk(KERN_WARNING "%s %s [irq]: timed out waiting for end of xfer\n",
|
||||
pr_warn("%s %s [irq]: timed out waiting for end of xfer\n",
|
||||
dev->name, __func__);
|
||||
return -EIO;
|
||||
}
|
||||
@ -220,7 +222,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, __le32 *dword, int shor
|
||||
break;
|
||||
}
|
||||
if (time_after(jiffies,timeout)) {
|
||||
printk(KERN_WARNING "%s %s: timed out waiting for MC2\n",
|
||||
pr_warn("%s %s: timed out waiting for MC2\n",
|
||||
dev->name, __func__);
|
||||
return -EIO;
|
||||
}
|
||||
@ -237,7 +239,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, __le32 *dword, int shor
|
||||
/* this is normal when probing the bus
|
||||
* (no answer from nonexisistant device...)
|
||||
*/
|
||||
printk(KERN_WARNING "%s %s [poll]: timed out waiting for end of xfer\n",
|
||||
pr_warn("%s %s [poll]: timed out waiting for end of xfer\n",
|
||||
dev->name, __func__);
|
||||
return -EIO;
|
||||
}
|
||||
@ -257,24 +259,24 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, __le32 *dword, int shor
|
||||
if ( 0 == (status & SAA7146_I2C_ERR) ||
|
||||
0 == (status & SAA7146_I2C_BUSY) ) {
|
||||
/* it may take some time until ERR goes high - ignore */
|
||||
DEB_I2C(("unexpected i2c status %04x\n", status));
|
||||
DEB_I2C("unexpected i2c status %04x\n", status);
|
||||
}
|
||||
if( 0 != (status & SAA7146_I2C_SPERR) ) {
|
||||
DEB_I2C(("error due to invalid start/stop condition.\n"));
|
||||
DEB_I2C("error due to invalid start/stop condition\n");
|
||||
}
|
||||
if( 0 != (status & SAA7146_I2C_DTERR) ) {
|
||||
DEB_I2C(("error in data transmission.\n"));
|
||||
DEB_I2C("error in data transmission\n");
|
||||
}
|
||||
if( 0 != (status & SAA7146_I2C_DRERR) ) {
|
||||
DEB_I2C(("error when receiving data.\n"));
|
||||
DEB_I2C("error when receiving data\n");
|
||||
}
|
||||
if( 0 != (status & SAA7146_I2C_AL) ) {
|
||||
DEB_I2C(("error because arbitration lost.\n"));
|
||||
DEB_I2C("error because arbitration lost\n");
|
||||
}
|
||||
|
||||
/* we handle address-errors here */
|
||||
if( 0 != (status & SAA7146_I2C_APERR) ) {
|
||||
DEB_I2C(("error in address phase.\n"));
|
||||
DEB_I2C("error in address phase\n");
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
@ -284,7 +286,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, __le32 *dword, int shor
|
||||
/* read back data, just in case we were reading ... */
|
||||
*dword = cpu_to_le32(saa7146_read(dev, I2C_TRANSFER));
|
||||
|
||||
DEB_I2C(("after: 0x%08x\n",*dword));
|
||||
DEB_I2C("after: 0x%08x\n", *dword);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -299,7 +301,7 @@ static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *m
|
||||
return -ERESTARTSYS;
|
||||
|
||||
for(i=0;i<num;i++) {
|
||||
DEB_I2C(("msg:%d/%d\n",i+1,num));
|
||||
DEB_I2C("msg:%d/%d\n", i+1, num);
|
||||
}
|
||||
|
||||
/* prepare the message(s), get number of u32s to transfer */
|
||||
@ -316,7 +318,7 @@ static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *m
|
||||
/* reset the i2c-device if necessary */
|
||||
err = saa7146_i2c_reset(dev);
|
||||
if ( 0 > err ) {
|
||||
DEB_I2C(("could not reset i2c-device.\n"));
|
||||
DEB_I2C("could not reset i2c-device\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -336,7 +338,7 @@ static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *m
|
||||
address error and trust the saa7146 address error detection. */
|
||||
if (-EREMOTEIO == err && 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags))
|
||||
goto out;
|
||||
DEB_I2C(("error while sending message(s). starting again.\n"));
|
||||
DEB_I2C("error while sending message(s). starting again\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -356,13 +358,13 @@ static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *m
|
||||
|
||||
/* if any things had to be read, get the results */
|
||||
if ( 0 != saa7146_i2c_msg_cleanup(msgs, num, buffer)) {
|
||||
DEB_I2C(("could not cleanup i2c-message.\n"));
|
||||
DEB_I2C("could not cleanup i2c-message\n");
|
||||
err = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* return the number of delivered messages */
|
||||
DEB_I2C(("transmission successful. (msg:%d).\n",err));
|
||||
DEB_I2C("transmission successful. (msg:%d)\n", err);
|
||||
out:
|
||||
/* another bug in revision 0: the i2c-registers get uploaded randomly by other
|
||||
uploads, so we better clear them out before continuing */
|
||||
@ -370,7 +372,7 @@ out:
|
||||
__le32 zero = 0;
|
||||
saa7146_i2c_reset(dev);
|
||||
if( 0 != saa7146_i2c_writeout(dev, &zero, short_delay)) {
|
||||
INFO(("revision 0 error. this should never happen.\n"));
|
||||
pr_info("revision 0 error. this should never happen\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -400,7 +402,7 @@ static struct i2c_algorithm saa7146_algo = {
|
||||
|
||||
int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, u32 bitrate)
|
||||
{
|
||||
DEB_EE(("bitrate: 0x%08x\n",bitrate));
|
||||
DEB_EE("bitrate: 0x%08x\n", bitrate);
|
||||
|
||||
/* enable i2c-port pins */
|
||||
saa7146_write(dev, MC1, (MASK_08 | MASK_24));
|
||||
|
@ -14,7 +14,7 @@ static int vbi_workaround(struct saa7146_dev *dev)
|
||||
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
|
||||
DEB_VBI(("dev:%p\n",dev));
|
||||
DEB_VBI("dev:%p\n", dev);
|
||||
|
||||
/* once again, a bug in the saa7146: the brs acquisition
|
||||
is buggy and especially the BXO-counter does not work
|
||||
@ -40,14 +40,14 @@ static int vbi_workaround(struct saa7146_dev *dev)
|
||||
WRITE_RPS1(0xc000008c);
|
||||
/* wait for vbi_a or vbi_b*/
|
||||
if ( 0 != (SAA7146_USE_PORT_B_FOR_VBI & dev->ext_vv_data->flags)) {
|
||||
DEB_D(("...using port b\n"));
|
||||
DEB_D("...using port b\n");
|
||||
WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | CMD_E_FID_B);
|
||||
WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | CMD_O_FID_B);
|
||||
/*
|
||||
WRITE_RPS1(CMD_PAUSE | MASK_09);
|
||||
*/
|
||||
} else {
|
||||
DEB_D(("...using port a\n"));
|
||||
DEB_D("...using port a\n");
|
||||
WRITE_RPS1(CMD_PAUSE | MASK_10);
|
||||
}
|
||||
/* upload brs */
|
||||
@ -103,7 +103,7 @@ static int vbi_workaround(struct saa7146_dev *dev)
|
||||
|
||||
schedule();
|
||||
|
||||
DEB_VBI(("brs bug workaround %d/1.\n",i));
|
||||
DEB_VBI("brs bug workaround %d/1\n", i);
|
||||
|
||||
remove_wait_queue(&vv->vbi_wq, &wait);
|
||||
current->state = TASK_RUNNING;
|
||||
@ -116,7 +116,8 @@ static int vbi_workaround(struct saa7146_dev *dev)
|
||||
|
||||
if(signal_pending(current)) {
|
||||
|
||||
DEB_VBI(("aborted (rps:0x%08x).\n",saa7146_read(dev,RPS_ADDR1)));
|
||||
DEB_VBI("aborted (rps:0x%08x)\n",
|
||||
saa7146_read(dev, RPS_ADDR1));
|
||||
|
||||
/* stop rps1 for sure */
|
||||
saa7146_write(dev, MC1, MASK_29);
|
||||
@ -207,7 +208,7 @@ static int buffer_activate(struct saa7146_dev *dev,
|
||||
struct saa7146_vv *vv = dev->vv_data;
|
||||
buf->vb.state = VIDEOBUF_ACTIVE;
|
||||
|
||||
DEB_VBI(("dev:%p, buf:%p, next:%p\n",dev,buf,next));
|
||||
DEB_VBI("dev:%p, buf:%p, next:%p\n", dev, buf, next);
|
||||
saa7146_set_vbi_capture(dev,buf,next);
|
||||
|
||||
mod_timer(&vv->vbi_q.timeout, jiffies+BUFFER_TIMEOUT);
|
||||
@ -228,10 +229,10 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,e
|
||||
llength = vbi_pixel_to_capture;
|
||||
size = lines * llength;
|
||||
|
||||
DEB_VBI(("vb:%p\n",vb));
|
||||
DEB_VBI("vb:%p\n", vb);
|
||||
|
||||
if (0 != buf->vb.baddr && buf->vb.bsize < size) {
|
||||
DEB_VBI(("size mismatch.\n"));
|
||||
DEB_VBI("size mismatch\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -263,7 +264,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,e
|
||||
return 0;
|
||||
|
||||
oops:
|
||||
DEB_VBI(("error out.\n"));
|
||||
DEB_VBI("error out\n");
|
||||
saa7146_dma_free(dev,q,buf);
|
||||
|
||||
return err;
|
||||
@ -279,7 +280,7 @@ static int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned
|
||||
*size = lines * llength;
|
||||
*count = 2;
|
||||
|
||||
DEB_VBI(("count:%d, size:%d\n",*count,*size));
|
||||
DEB_VBI("count:%d, size:%d\n", *count, *size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -292,7 +293,7 @@ static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
|
||||
struct saa7146_vv *vv = dev->vv_data;
|
||||
struct saa7146_buf *buf = (struct saa7146_buf *)vb;
|
||||
|
||||
DEB_VBI(("vb:%p\n",vb));
|
||||
DEB_VBI("vb:%p\n", vb);
|
||||
saa7146_buffer_queue(dev,&vv->vbi_q,buf);
|
||||
}
|
||||
|
||||
@ -303,7 +304,7 @@ static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
|
||||
struct saa7146_dev *dev = fh->dev;
|
||||
struct saa7146_buf *buf = (struct saa7146_buf *)vb;
|
||||
|
||||
DEB_VBI(("vb:%p\n",vb));
|
||||
DEB_VBI("vb:%p\n", vb);
|
||||
saa7146_dma_free(dev,q,buf);
|
||||
}
|
||||
|
||||
@ -321,7 +322,7 @@ static void vbi_stop(struct saa7146_fh *fh, struct file *file)
|
||||
struct saa7146_dev *dev = fh->dev;
|
||||
struct saa7146_vv *vv = dev->vv_data;
|
||||
unsigned long flags;
|
||||
DEB_VBI(("dev:%p, fh:%p\n",dev, fh));
|
||||
DEB_VBI("dev:%p, fh:%p\n", dev, fh);
|
||||
|
||||
spin_lock_irqsave(&dev->slock,flags);
|
||||
|
||||
@ -354,14 +355,14 @@ static void vbi_read_timeout(unsigned long data)
|
||||
struct saa7146_fh *fh = file->private_data;
|
||||
struct saa7146_dev *dev = fh->dev;
|
||||
|
||||
DEB_VBI(("dev:%p, fh:%p\n",dev, fh));
|
||||
DEB_VBI("dev:%p, fh:%p\n", dev, fh);
|
||||
|
||||
vbi_stop(fh, file);
|
||||
}
|
||||
|
||||
static void vbi_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
|
||||
{
|
||||
DEB_VBI(("dev:%p\n",dev));
|
||||
DEB_VBI("dev:%p\n", dev);
|
||||
|
||||
INIT_LIST_HEAD(&vv->vbi_q.queue);
|
||||
|
||||
@ -380,11 +381,11 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file)
|
||||
u32 arbtr_ctrl = saa7146_read(dev, PCI_BT_V1);
|
||||
int ret = 0;
|
||||
|
||||
DEB_VBI(("dev:%p, fh:%p\n",dev,fh));
|
||||
DEB_VBI("dev:%p, fh:%p\n", dev, fh);
|
||||
|
||||
ret = saa7146_res_get(fh, RESOURCE_DMA3_BRS);
|
||||
if (0 == ret) {
|
||||
DEB_S(("cannot get vbi RESOURCE_DMA3_BRS resource\n"));
|
||||
DEB_S("cannot get vbi RESOURCE_DMA3_BRS resource\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
@ -425,7 +426,7 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file)
|
||||
saa7146_write(dev, BRS_CTRL, 0x00000001);
|
||||
|
||||
if (0 != (ret = vbi_workaround(dev))) {
|
||||
DEB_VBI(("vbi workaround failed!\n"));
|
||||
DEB_VBI("vbi workaround failed!\n");
|
||||
/* return ret;*/
|
||||
}
|
||||
}
|
||||
@ -439,7 +440,7 @@ static void vbi_close(struct saa7146_dev *dev, struct file *file)
|
||||
{
|
||||
struct saa7146_fh *fh = file->private_data;
|
||||
struct saa7146_vv *vv = dev->vv_data;
|
||||
DEB_VBI(("dev:%p, fh:%p\n",dev,fh));
|
||||
DEB_VBI("dev:%p, fh:%p\n", dev, fh);
|
||||
|
||||
if( fh == vv->vbi_streaming ) {
|
||||
vbi_stop(fh, file);
|
||||
@ -453,13 +454,13 @@ static void vbi_irq_done(struct saa7146_dev *dev, unsigned long status)
|
||||
spin_lock(&dev->slock);
|
||||
|
||||
if (vv->vbi_q.curr) {
|
||||
DEB_VBI(("dev:%p, curr:%p\n",dev,vv->vbi_q.curr));
|
||||
DEB_VBI("dev:%p, curr:%p\n", dev, vv->vbi_q.curr);
|
||||
/* this must be += 2, one count for each field */
|
||||
vv->vbi_fieldcount+=2;
|
||||
vv->vbi_q.curr->vb.field_count = vv->vbi_fieldcount;
|
||||
saa7146_buffer_finish(dev,&vv->vbi_q,VIDEOBUF_DONE);
|
||||
} else {
|
||||
DEB_VBI(("dev:%p\n",dev));
|
||||
DEB_VBI("dev:%p\n", dev);
|
||||
}
|
||||
saa7146_buffer_next(dev,&vv->vbi_q,1);
|
||||
|
||||
@ -473,7 +474,7 @@ static ssize_t vbi_read(struct file *file, char __user *data, size_t count, loff
|
||||
struct saa7146_vv *vv = dev->vv_data;
|
||||
ssize_t ret = 0;
|
||||
|
||||
DEB_VBI(("dev:%p, fh:%p\n",dev,fh));
|
||||
DEB_VBI("dev:%p, fh:%p\n", dev, fh);
|
||||
|
||||
if( NULL == vv->vbi_streaming ) {
|
||||
// fixme: check if dma3 is available
|
||||
@ -482,7 +483,8 @@ static ssize_t vbi_read(struct file *file, char __user *data, size_t count, loff
|
||||
}
|
||||
|
||||
if( fh != vv->vbi_streaming ) {
|
||||
DEB_VBI(("open %p is already using vbi capture.",vv->vbi_streaming));
|
||||
DEB_VBI("open %p is already using vbi capture\n",
|
||||
vv->vbi_streaming);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <media/saa7146_vv.h>
|
||||
#include <media/v4l2-chip-ident.h>
|
||||
|
||||
@ -94,7 +96,7 @@ struct saa7146_format* saa7146_format_by_fourcc(struct saa7146_dev *dev, int fou
|
||||
}
|
||||
}
|
||||
|
||||
DEB_D(("unknown pixelformat:'%4.4s'\n",(char *)&fourcc));
|
||||
DEB_D("unknown pixelformat:'%4.4s'\n", (char *)&fourcc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -107,32 +109,32 @@ int saa7146_start_preview(struct saa7146_fh *fh)
|
||||
struct v4l2_format fmt;
|
||||
int ret = 0, err = 0;
|
||||
|
||||
DEB_EE(("dev:%p, fh:%p\n",dev,fh));
|
||||
DEB_EE("dev:%p, fh:%p\n", dev, fh);
|
||||
|
||||
/* check if we have overlay informations */
|
||||
if( NULL == fh->ov.fh ) {
|
||||
DEB_D(("no overlay data available. try S_FMT first.\n"));
|
||||
DEB_D("no overlay data available. try S_FMT first.\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
/* check if streaming capture is running */
|
||||
if (IS_CAPTURE_ACTIVE(fh) != 0) {
|
||||
DEB_D(("streaming capture is active.\n"));
|
||||
DEB_D("streaming capture is active\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* check if overlay is running */
|
||||
if (IS_OVERLAY_ACTIVE(fh) != 0) {
|
||||
if (vv->video_fh == fh) {
|
||||
DEB_D(("overlay is already active.\n"));
|
||||
DEB_D("overlay is already active\n");
|
||||
return 0;
|
||||
}
|
||||
DEB_D(("overlay is already active in another open.\n"));
|
||||
DEB_D("overlay is already active in another open\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (0 == saa7146_res_get(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP)) {
|
||||
DEB_D(("cannot get necessary overlay resources\n"));
|
||||
DEB_D("cannot get necessary overlay resources\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
@ -145,13 +147,13 @@ int saa7146_start_preview(struct saa7146_fh *fh)
|
||||
fh->ov.win = fmt.fmt.win;
|
||||
vv->ov_data = &fh->ov;
|
||||
|
||||
DEB_D(("%dx%d+%d+%d %s field=%s\n",
|
||||
fh->ov.win.w.width,fh->ov.win.w.height,
|
||||
fh->ov.win.w.left,fh->ov.win.w.top,
|
||||
vv->ov_fmt->name,v4l2_field_names[fh->ov.win.field]));
|
||||
DEB_D("%dx%d+%d+%d %s field=%s\n",
|
||||
fh->ov.win.w.width, fh->ov.win.w.height,
|
||||
fh->ov.win.w.left, fh->ov.win.w.top,
|
||||
vv->ov_fmt->name, v4l2_field_names[fh->ov.win.field]);
|
||||
|
||||
if (0 != (ret = saa7146_enable_overlay(fh))) {
|
||||
DEB_D(("enabling overlay failed: %d\n",ret));
|
||||
DEB_D("enabling overlay failed: %d\n", ret);
|
||||
saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
|
||||
return ret;
|
||||
}
|
||||
@ -168,22 +170,22 @@ int saa7146_stop_preview(struct saa7146_fh *fh)
|
||||
struct saa7146_dev *dev = fh->dev;
|
||||
struct saa7146_vv *vv = dev->vv_data;
|
||||
|
||||
DEB_EE(("dev:%p, fh:%p\n",dev,fh));
|
||||
DEB_EE("dev:%p, fh:%p\n", dev, fh);
|
||||
|
||||
/* check if streaming capture is running */
|
||||
if (IS_CAPTURE_ACTIVE(fh) != 0) {
|
||||
DEB_D(("streaming capture is active.\n"));
|
||||
DEB_D("streaming capture is active\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* check if overlay is running at all */
|
||||
if ((vv->video_status & STATUS_OVERLAY) == 0) {
|
||||
DEB_D(("no active overlay.\n"));
|
||||
DEB_D("no active overlay\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vv->video_fh != fh) {
|
||||
DEB_D(("overlay is active, but in another open.\n"));
|
||||
DEB_D("overlay is active, but in another open\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
@ -268,7 +270,7 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu
|
||||
int length = dma->sglen;
|
||||
struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
|
||||
|
||||
DEB_EE(("dev:%p, buf:%p, sg_len:%d\n",dev,buf,length));
|
||||
DEB_EE("dev:%p, buf:%p, sg_len:%d\n", dev, buf, length);
|
||||
|
||||
if( 0 != IS_PLANAR(sfmt->trans)) {
|
||||
struct saa7146_pgtable *pt1 = &buf->pt[0];
|
||||
@ -288,7 +290,8 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu
|
||||
m3 = ((size+(size/2)+PAGE_SIZE)/PAGE_SIZE)-1;
|
||||
o1 = size%PAGE_SIZE;
|
||||
o2 = (size+(size/4))%PAGE_SIZE;
|
||||
DEB_CAP(("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",size,m1,m2,m3,o1,o2));
|
||||
DEB_CAP("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",
|
||||
size, m1, m2, m3, o1, o2);
|
||||
break;
|
||||
}
|
||||
case 16: {
|
||||
@ -298,7 +301,8 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu
|
||||
m3 = ((2*size+PAGE_SIZE)/PAGE_SIZE)-1;
|
||||
o1 = size%PAGE_SIZE;
|
||||
o2 = (size+(size/2))%PAGE_SIZE;
|
||||
DEB_CAP(("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",size,m1,m2,m3,o1,o2));
|
||||
DEB_CAP("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",
|
||||
size, m1, m2, m3, o1, o2);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@ -387,23 +391,23 @@ static int video_begin(struct saa7146_fh *fh)
|
||||
unsigned int resource;
|
||||
int ret = 0, err = 0;
|
||||
|
||||
DEB_EE(("dev:%p, fh:%p\n",dev,fh));
|
||||
DEB_EE("dev:%p, fh:%p\n", dev, fh);
|
||||
|
||||
if ((vv->video_status & STATUS_CAPTURE) != 0) {
|
||||
if (vv->video_fh == fh) {
|
||||
DEB_S(("already capturing.\n"));
|
||||
DEB_S("already capturing\n");
|
||||
return 0;
|
||||
}
|
||||
DEB_S(("already capturing in another open.\n"));
|
||||
DEB_S("already capturing in another open\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if ((vv->video_status & STATUS_OVERLAY) != 0) {
|
||||
DEB_S(("warning: suspending overlay video for streaming capture.\n"));
|
||||
DEB_S("warning: suspending overlay video for streaming capture\n");
|
||||
vv->ov_suspend = vv->video_fh;
|
||||
err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
|
||||
if (0 != err) {
|
||||
DEB_D(("suspending video failed. aborting\n"));
|
||||
DEB_D("suspending video failed. aborting\n");
|
||||
return err;
|
||||
}
|
||||
}
|
||||
@ -420,7 +424,7 @@ static int video_begin(struct saa7146_fh *fh)
|
||||
|
||||
ret = saa7146_res_get(fh, resource);
|
||||
if (0 == ret) {
|
||||
DEB_S(("cannot get capture resource %d\n",resource));
|
||||
DEB_S("cannot get capture resource %d\n", resource);
|
||||
if (vv->ov_suspend != NULL) {
|
||||
saa7146_start_preview(vv->ov_suspend);
|
||||
vv->ov_suspend = NULL;
|
||||
@ -448,15 +452,15 @@ static int video_end(struct saa7146_fh *fh, struct file *file)
|
||||
unsigned long flags;
|
||||
unsigned int resource;
|
||||
u32 dmas = 0;
|
||||
DEB_EE(("dev:%p, fh:%p\n",dev,fh));
|
||||
DEB_EE("dev:%p, fh:%p\n", dev, fh);
|
||||
|
||||
if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) {
|
||||
DEB_S(("not capturing.\n"));
|
||||
DEB_S("not capturing\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vv->video_fh != fh) {
|
||||
DEB_S(("capturing, but in another open.\n"));
|
||||
DEB_S("capturing, but in another open\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
@ -530,7 +534,7 @@ static int vidioc_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *f
|
||||
struct saa7146_vv *vv = dev->vv_data;
|
||||
struct saa7146_format *fmt;
|
||||
|
||||
DEB_EE(("VIDIOC_S_FBUF\n"));
|
||||
DEB_EE("VIDIOC_S_FBUF\n");
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
|
||||
return -EPERM;
|
||||
@ -542,13 +546,13 @@ static int vidioc_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *f
|
||||
|
||||
/* planar formats are not allowed for overlay video, clipping and video dma would clash */
|
||||
if (fmt->flags & FORMAT_IS_PLANAR)
|
||||
DEB_S(("planar pixelformat '%4.4s' not allowed for overlay\n",
|
||||
(char *)&fmt->pixelformat));
|
||||
DEB_S("planar pixelformat '%4.4s' not allowed for overlay\n",
|
||||
(char *)&fmt->pixelformat);
|
||||
|
||||
/* check if overlay is running */
|
||||
if (IS_OVERLAY_ACTIVE(fh) != 0) {
|
||||
if (vv->video_fh != fh) {
|
||||
DEB_D(("refusing to change framebuffer informations while overlay is active in another open.\n"));
|
||||
DEB_D("refusing to change framebuffer informations while overlay is active in another open\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
@ -559,7 +563,7 @@ static int vidioc_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *f
|
||||
|
||||
if (vv->ov_fb.fmt.bytesperline < vv->ov_fb.fmt.width) {
|
||||
vv->ov_fb.fmt.bytesperline = vv->ov_fb.fmt.width * fmt->depth / 8;
|
||||
DEB_D(("setting bytesperline to %d\n", vv->ov_fb.fmt.bytesperline));
|
||||
DEB_D("setting bytesperline to %d\n", vv->ov_fb.fmt.bytesperline);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -588,7 +592,7 @@ static int vidioc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *
|
||||
if (ctrl == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
DEB_EE(("VIDIOC_QUERYCTRL: id:%d\n", c->id));
|
||||
DEB_EE("VIDIOC_QUERYCTRL: id:%d\n", c->id);
|
||||
*c = *ctrl;
|
||||
return 0;
|
||||
}
|
||||
@ -607,25 +611,25 @@ static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *c)
|
||||
case V4L2_CID_BRIGHTNESS:
|
||||
value = saa7146_read(dev, BCS_CTRL);
|
||||
c->value = 0xff & (value >> 24);
|
||||
DEB_D(("V4L2_CID_BRIGHTNESS: %d\n", c->value));
|
||||
DEB_D("V4L2_CID_BRIGHTNESS: %d\n", c->value);
|
||||
break;
|
||||
case V4L2_CID_CONTRAST:
|
||||
value = saa7146_read(dev, BCS_CTRL);
|
||||
c->value = 0x7f & (value >> 16);
|
||||
DEB_D(("V4L2_CID_CONTRAST: %d\n", c->value));
|
||||
DEB_D("V4L2_CID_CONTRAST: %d\n", c->value);
|
||||
break;
|
||||
case V4L2_CID_SATURATION:
|
||||
value = saa7146_read(dev, BCS_CTRL);
|
||||
c->value = 0x7f & (value >> 0);
|
||||
DEB_D(("V4L2_CID_SATURATION: %d\n", c->value));
|
||||
DEB_D("V4L2_CID_SATURATION: %d\n", c->value);
|
||||
break;
|
||||
case V4L2_CID_VFLIP:
|
||||
c->value = vv->vflip;
|
||||
DEB_D(("V4L2_CID_VFLIP: %d\n", c->value));
|
||||
DEB_D("V4L2_CID_VFLIP: %d\n", c->value);
|
||||
break;
|
||||
case V4L2_CID_HFLIP:
|
||||
c->value = vv->hflip;
|
||||
DEB_D(("V4L2_CID_HFLIP: %d\n", c->value));
|
||||
DEB_D("V4L2_CID_HFLIP: %d\n", c->value);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
@ -641,7 +645,7 @@ static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c)
|
||||
|
||||
ctrl = ctrl_by_id(c->id);
|
||||
if (NULL == ctrl) {
|
||||
DEB_D(("unknown control %d\n", c->id));
|
||||
DEB_D("unknown control %d\n", c->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -686,14 +690,14 @@ static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c)
|
||||
case V4L2_CID_HFLIP:
|
||||
/* fixme: we can support changing VFLIP and HFLIP here... */
|
||||
if (IS_CAPTURE_ACTIVE(fh) != 0) {
|
||||
DEB_D(("V4L2_CID_HFLIP while active capture.\n"));
|
||||
DEB_D("V4L2_CID_HFLIP while active capture\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
vv->hflip = c->value;
|
||||
break;
|
||||
case V4L2_CID_VFLIP:
|
||||
if (IS_CAPTURE_ACTIVE(fh) != 0) {
|
||||
DEB_D(("V4L2_CID_VFLIP while active capture.\n"));
|
||||
DEB_D("V4L2_CID_VFLIP while active capture\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
vv->vflip = c->value;
|
||||
@ -748,7 +752,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_forma
|
||||
int maxw, maxh;
|
||||
int calc_bpl;
|
||||
|
||||
DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh));
|
||||
DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh);
|
||||
|
||||
fmt = saa7146_format_by_fourcc(dev, f->fmt.pix.pixelformat);
|
||||
if (NULL == fmt)
|
||||
@ -777,7 +781,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_forma
|
||||
vv->last_field = V4L2_FIELD_INTERLACED;
|
||||
break;
|
||||
default:
|
||||
DEB_D(("no known field mode '%d'.\n", field));
|
||||
DEB_D("no known field mode '%d'\n", field);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -796,8 +800,9 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_forma
|
||||
f->fmt.pix.bytesperline = calc_bpl;
|
||||
|
||||
f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height;
|
||||
DEB_D(("w:%d, h:%d, bytesperline:%d, sizeimage:%d\n", f->fmt.pix.width,
|
||||
f->fmt.pix.height, f->fmt.pix.bytesperline, f->fmt.pix.sizeimage));
|
||||
DEB_D("w:%d, h:%d, bytesperline:%d, sizeimage:%d\n",
|
||||
f->fmt.pix.width, f->fmt.pix.height,
|
||||
f->fmt.pix.bytesperline, f->fmt.pix.sizeimage);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -811,22 +816,23 @@ static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_f
|
||||
enum v4l2_field field;
|
||||
int maxw, maxh;
|
||||
|
||||
DEB_EE(("dev:%p\n", dev));
|
||||
DEB_EE("dev:%p\n", dev);
|
||||
|
||||
if (NULL == vv->ov_fb.base) {
|
||||
DEB_D(("no fb base set.\n"));
|
||||
DEB_D("no fb base set\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (NULL == vv->ov_fmt) {
|
||||
DEB_D(("no fb fmt set.\n"));
|
||||
DEB_D("no fb fmt set\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (win->w.width < 48 || win->w.height < 32) {
|
||||
DEB_D(("min width/height. (%d,%d)\n", win->w.width, win->w.height));
|
||||
DEB_D("min width/height. (%d,%d)\n",
|
||||
win->w.width, win->w.height);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (win->clipcount > 16) {
|
||||
DEB_D(("clipcount too big.\n"));
|
||||
DEB_D("clipcount too big\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -848,7 +854,7 @@ static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_f
|
||||
case V4L2_FIELD_INTERLACED:
|
||||
break;
|
||||
default:
|
||||
DEB_D(("no known field mode '%d'.\n", field));
|
||||
DEB_D("no known field mode '%d'\n", field);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -868,16 +874,17 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *__fh, struct v4l2_forma
|
||||
struct saa7146_vv *vv = dev->vv_data;
|
||||
int err;
|
||||
|
||||
DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh));
|
||||
DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh);
|
||||
if (IS_CAPTURE_ACTIVE(fh) != 0) {
|
||||
DEB_EE(("streaming capture is active\n"));
|
||||
DEB_EE("streaming capture is active\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
err = vidioc_try_fmt_vid_cap(file, fh, f);
|
||||
if (0 != err)
|
||||
return err;
|
||||
fh->video_fmt = f->fmt.pix;
|
||||
DEB_EE(("set to pixelformat '%4.4s'\n", (char *)&fh->video_fmt.pixelformat));
|
||||
DEB_EE("set to pixelformat '%4.4s'\n",
|
||||
(char *)&fh->video_fmt.pixelformat);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -888,7 +895,7 @@ static int vidioc_s_fmt_vid_overlay(struct file *file, void *__fh, struct v4l2_f
|
||||
struct saa7146_vv *vv = dev->vv_data;
|
||||
int err;
|
||||
|
||||
DEB_EE(("V4L2_BUF_TYPE_VIDEO_OVERLAY: dev:%p, fh:%p\n", dev, fh));
|
||||
DEB_EE("V4L2_BUF_TYPE_VIDEO_OVERLAY: dev:%p, fh:%p\n", dev, fh);
|
||||
err = vidioc_try_fmt_vid_overlay(file, fh, f);
|
||||
if (0 != err)
|
||||
return err;
|
||||
@ -931,7 +938,7 @@ static int vidioc_g_std(struct file *file, void *fh, v4l2_std_id *norm)
|
||||
if (e->index < 0 )
|
||||
return -EINVAL;
|
||||
if( e->index < dev->ext_vv_data->num_stds ) {
|
||||
DEB_EE(("VIDIOC_ENUMSTD: index:%d\n",e->index));
|
||||
DEB_EE("VIDIOC_ENUMSTD: index:%d\n", e->index);
|
||||
v4l2_video_std_construct(e, dev->ext_vv_data->stds[e->index].id, dev->ext_vv_data->stds[e->index].name);
|
||||
return 0;
|
||||
}
|
||||
@ -946,10 +953,10 @@ static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id *id)
|
||||
int found = 0;
|
||||
int err, i;
|
||||
|
||||
DEB_EE(("VIDIOC_S_STD\n"));
|
||||
DEB_EE("VIDIOC_S_STD\n");
|
||||
|
||||
if ((vv->video_status & STATUS_CAPTURE) == STATUS_CAPTURE) {
|
||||
DEB_D(("cannot change video standard while streaming capture is active\n"));
|
||||
DEB_D("cannot change video standard while streaming capture is active\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
@ -957,7 +964,7 @@ static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id *id)
|
||||
vv->ov_suspend = vv->video_fh;
|
||||
err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
|
||||
if (0 != err) {
|
||||
DEB_D(("suspending video failed. aborting\n"));
|
||||
DEB_D("suspending video failed. aborting\n");
|
||||
return err;
|
||||
}
|
||||
}
|
||||
@ -978,11 +985,11 @@ static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id *id)
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
DEB_EE(("VIDIOC_S_STD: standard not found.\n"));
|
||||
DEB_EE("VIDIOC_S_STD: standard not found\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
DEB_EE(("VIDIOC_S_STD: set to standard to '%s'\n", vv->standard->name));
|
||||
DEB_EE("VIDIOC_S_STD: set to standard to '%s'\n", vv->standard->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -990,7 +997,7 @@ static int vidioc_overlay(struct file *file, void *fh, unsigned int on)
|
||||
{
|
||||
int err;
|
||||
|
||||
DEB_D(("VIDIOC_OVERLAY on:%d\n", on));
|
||||
DEB_D("VIDIOC_OVERLAY on:%d\n", on);
|
||||
if (on)
|
||||
err = saa7146_start_preview(fh);
|
||||
else
|
||||
@ -1047,7 +1054,7 @@ static int vidioc_streamon(struct file *file, void *__fh, enum v4l2_buf_type typ
|
||||
struct saa7146_fh *fh = __fh;
|
||||
int err;
|
||||
|
||||
DEB_D(("VIDIOC_STREAMON, type:%d\n", type));
|
||||
DEB_D("VIDIOC_STREAMON, type:%d\n", type);
|
||||
|
||||
err = video_begin(fh);
|
||||
if (err)
|
||||
@ -1066,18 +1073,18 @@ static int vidioc_streamoff(struct file *file, void *__fh, enum v4l2_buf_type ty
|
||||
struct saa7146_vv *vv = dev->vv_data;
|
||||
int err;
|
||||
|
||||
DEB_D(("VIDIOC_STREAMOFF, type:%d\n", type));
|
||||
DEB_D("VIDIOC_STREAMOFF, type:%d\n", type);
|
||||
|
||||
/* ugly: we need to copy some checks from video_end(),
|
||||
because videobuf_streamoff() relies on the capture running.
|
||||
check and fix this */
|
||||
if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) {
|
||||
DEB_S(("not capturing.\n"));
|
||||
DEB_S("not capturing\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vv->video_fh != fh) {
|
||||
DEB_S(("capturing, but in another open.\n"));
|
||||
DEB_S("capturing, but in another open\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
@ -1087,7 +1094,7 @@ static int vidioc_streamoff(struct file *file, void *__fh, enum v4l2_buf_type ty
|
||||
else if (type == V4L2_BUF_TYPE_VBI_CAPTURE)
|
||||
err = videobuf_streamoff(&fh->vbi_q);
|
||||
if (0 != err) {
|
||||
DEB_D(("warning: videobuf_streamoff() failed.\n"));
|
||||
DEB_D("warning: videobuf_streamoff() failed\n");
|
||||
video_end(fh, file);
|
||||
} else {
|
||||
err = video_end(fh, file);
|
||||
@ -1174,25 +1181,27 @@ static int buffer_prepare(struct videobuf_queue *q,
|
||||
struct saa7146_buf *buf = (struct saa7146_buf *)vb;
|
||||
int size,err = 0;
|
||||
|
||||
DEB_CAP(("vbuf:%p\n",vb));
|
||||
DEB_CAP("vbuf:%p\n", vb);
|
||||
|
||||
/* sanity checks */
|
||||
if (fh->video_fmt.width < 48 ||
|
||||
fh->video_fmt.height < 32 ||
|
||||
fh->video_fmt.width > vv->standard->h_max_out ||
|
||||
fh->video_fmt.height > vv->standard->v_max_out) {
|
||||
DEB_D(("w (%d) / h (%d) out of bounds.\n",fh->video_fmt.width,fh->video_fmt.height));
|
||||
DEB_D("w (%d) / h (%d) out of bounds\n",
|
||||
fh->video_fmt.width, fh->video_fmt.height);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
size = fh->video_fmt.sizeimage;
|
||||
if (0 != buf->vb.baddr && buf->vb.bsize < size) {
|
||||
DEB_D(("size mismatch.\n"));
|
||||
DEB_D("size mismatch\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
DEB_CAP(("buffer_prepare [size=%dx%d,bytes=%d,fields=%s]\n",
|
||||
fh->video_fmt.width,fh->video_fmt.height,size,v4l2_field_names[fh->video_fmt.field]));
|
||||
DEB_CAP("buffer_prepare [size=%dx%d,bytes=%d,fields=%s]\n",
|
||||
fh->video_fmt.width, fh->video_fmt.height,
|
||||
size, v4l2_field_names[fh->video_fmt.field]);
|
||||
if (buf->vb.width != fh->video_fmt.width ||
|
||||
buf->vb.bytesperline != fh->video_fmt.bytesperline ||
|
||||
buf->vb.height != fh->video_fmt.height ||
|
||||
@ -1238,7 +1247,7 @@ static int buffer_prepare(struct videobuf_queue *q,
|
||||
return 0;
|
||||
|
||||
oops:
|
||||
DEB_D(("error out.\n"));
|
||||
DEB_D("error out\n");
|
||||
saa7146_dma_free(dev,q,buf);
|
||||
|
||||
return err;
|
||||
@ -1259,7 +1268,7 @@ static int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned
|
||||
*count = (max_memory*1048576) / *size;
|
||||
}
|
||||
|
||||
DEB_CAP(("%d buffers, %d bytes each.\n",*count,*size));
|
||||
DEB_CAP("%d buffers, %d bytes each\n", *count, *size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1272,7 +1281,7 @@ static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
|
||||
struct saa7146_vv *vv = dev->vv_data;
|
||||
struct saa7146_buf *buf = (struct saa7146_buf *)vb;
|
||||
|
||||
DEB_CAP(("vbuf:%p\n",vb));
|
||||
DEB_CAP("vbuf:%p\n", vb);
|
||||
saa7146_buffer_queue(fh->dev,&vv->video_q,buf);
|
||||
}
|
||||
|
||||
@ -1283,7 +1292,7 @@ static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
|
||||
struct saa7146_dev *dev = fh->dev;
|
||||
struct saa7146_buf *buf = (struct saa7146_buf *)vb;
|
||||
|
||||
DEB_CAP(("vbuf:%p\n",vb));
|
||||
DEB_CAP("vbuf:%p\n", vb);
|
||||
|
||||
saa7146_dma_free(dev,q,buf);
|
||||
|
||||
@ -1347,18 +1356,14 @@ static void video_close(struct saa7146_dev *dev, struct file *file)
|
||||
struct saa7146_fh *fh = file->private_data;
|
||||
struct saa7146_vv *vv = dev->vv_data;
|
||||
struct videobuf_queue *q = &fh->video_q;
|
||||
int err;
|
||||
|
||||
if (IS_CAPTURE_ACTIVE(fh) != 0) {
|
||||
err = video_end(fh, file);
|
||||
} else if (IS_OVERLAY_ACTIVE(fh) != 0) {
|
||||
err = saa7146_stop_preview(fh);
|
||||
}
|
||||
if (IS_CAPTURE_ACTIVE(fh) != 0)
|
||||
video_end(fh, file);
|
||||
else if (IS_OVERLAY_ACTIVE(fh) != 0)
|
||||
saa7146_stop_preview(fh);
|
||||
|
||||
videobuf_stop(q);
|
||||
|
||||
/* hmm, why is this function declared void? */
|
||||
/* return err */
|
||||
}
|
||||
|
||||
|
||||
@ -1368,7 +1373,7 @@ static void video_irq_done(struct saa7146_dev *dev, unsigned long st)
|
||||
struct saa7146_dmaqueue *q = &vv->video_q;
|
||||
|
||||
spin_lock(&dev->slock);
|
||||
DEB_CAP(("called.\n"));
|
||||
DEB_CAP("called\n");
|
||||
|
||||
/* only finish the buffer if we have one... */
|
||||
if( NULL != q->curr ) {
|
||||
@ -1386,15 +1391,15 @@ static ssize_t video_read(struct file *file, char __user *data, size_t count, lo
|
||||
struct saa7146_vv *vv = dev->vv_data;
|
||||
ssize_t ret = 0;
|
||||
|
||||
DEB_EE(("called.\n"));
|
||||
DEB_EE("called\n");
|
||||
|
||||
if ((vv->video_status & STATUS_CAPTURE) != 0) {
|
||||
/* fixme: should we allow read() captures while streaming capture? */
|
||||
if (vv->video_fh == fh) {
|
||||
DEB_S(("already capturing.\n"));
|
||||
DEB_S("already capturing\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
DEB_S(("already capturing in another open.\n"));
|
||||
DEB_S("already capturing in another open\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
|
@ -28,5 +28,5 @@ obj-$(CONFIG_MEDIA_TUNER_MAX2165) += max2165.o
|
||||
obj-$(CONFIG_MEDIA_TUNER_TDA18218) += tda18218.o
|
||||
obj-$(CONFIG_MEDIA_TUNER_TDA18212) += tda18212.o
|
||||
|
||||
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
|
||||
EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
|
||||
ccflags-y += -Idrivers/media/dvb/dvb-core
|
||||
ccflags-y += -Idrivers/media/dvb/frontends
|
||||
|
@ -430,11 +430,10 @@ static void mt2050_set_antenna(struct dvb_frontend *fe, unsigned char antenna)
|
||||
{
|
||||
struct microtune_priv *priv = fe->tuner_priv;
|
||||
unsigned char buf[2];
|
||||
int ret;
|
||||
|
||||
buf[0] = 6;
|
||||
buf[1] = antenna ? 0x11 : 0x10;
|
||||
ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
|
||||
tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
|
||||
tuner_dbg("mt2050: enabled antenna connector %d\n", antenna);
|
||||
}
|
||||
|
||||
@ -574,21 +573,20 @@ static int mt2050_init(struct dvb_frontend *fe)
|
||||
{
|
||||
struct microtune_priv *priv = fe->tuner_priv;
|
||||
unsigned char buf[2];
|
||||
int ret;
|
||||
|
||||
buf[0]=6;
|
||||
buf[1]=0x10;
|
||||
ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2); // power
|
||||
buf[0] = 6;
|
||||
buf[1] = 0x10;
|
||||
tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); /* power */
|
||||
|
||||
buf[0]=0x0f;
|
||||
buf[1]=0x0f;
|
||||
ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2); // m1lo
|
||||
buf[0] = 0x0f;
|
||||
buf[1] = 0x0f;
|
||||
tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); /* m1lo */
|
||||
|
||||
buf[0]=0x0d;
|
||||
ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
|
||||
tuner_i2c_xfer_recv(&priv->i2c_props,buf,1);
|
||||
buf[0] = 0x0d;
|
||||
tuner_i2c_xfer_send(&priv->i2c_props, buf, 1);
|
||||
tuner_i2c_xfer_recv(&priv->i2c_props, buf, 1);
|
||||
|
||||
tuner_dbg("mt2050: sro is %x\n",buf[0]);
|
||||
tuner_dbg("mt2050: sro is %x\n", buf[0]);
|
||||
|
||||
memcpy(&fe->ops.tuner_ops, &mt2050_tuner_ops, sizeof(struct dvb_tuner_ops));
|
||||
|
||||
|
@ -309,7 +309,6 @@ static u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum,
|
||||
static u16 MXL_SetGPIO(struct dvb_frontend *fe, u8 GPIO_Num, u8 GPIO_Val);
|
||||
static u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 *RegNum,
|
||||
u8 *RegVal, int *count);
|
||||
static u32 MXL_GetXtalInt(u32 Xtal_Freq);
|
||||
static u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq);
|
||||
static void MXL_SynthIFLO_Calc(struct dvb_frontend *fe);
|
||||
static void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe);
|
||||
@ -2307,14 +2306,6 @@ static u16 MXL_IFSynthInit(struct dvb_frontend *fe)
|
||||
return status ;
|
||||
}
|
||||
|
||||
static u32 MXL_GetXtalInt(u32 Xtal_Freq)
|
||||
{
|
||||
if ((Xtal_Freq % 1000000) == 0)
|
||||
return (Xtal_Freq / 10000);
|
||||
else
|
||||
return (((Xtal_Freq / 1000000) + 1)*100);
|
||||
}
|
||||
|
||||
static u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq)
|
||||
{
|
||||
struct mxl5005s_state *state = fe->tuner_priv;
|
||||
@ -2324,13 +2315,10 @@ static u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq)
|
||||
u32 Kdbl_RF = 2;
|
||||
u32 tg_divval;
|
||||
u32 tg_lo;
|
||||
u32 Xtal_Int;
|
||||
|
||||
u32 Fref_TG;
|
||||
u32 Fvco;
|
||||
|
||||
Xtal_Int = MXL_GetXtalInt(state->Fxtal);
|
||||
|
||||
state->RF_IN = RF_Freq;
|
||||
|
||||
MXL_SynthRFTGLO_Calc(fe);
|
||||
@ -2779,6 +2767,16 @@ static u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq)
|
||||
tg_lo = (((Fmax/10 - Fvco)/100)*32) / ((Fmax-Fmin)/1000)+8;
|
||||
|
||||
/* below equation is same as above but much harder to debug.
|
||||
*
|
||||
* static u32 MXL_GetXtalInt(u32 Xtal_Freq)
|
||||
* {
|
||||
* if ((Xtal_Freq % 1000000) == 0)
|
||||
* return (Xtal_Freq / 10000);
|
||||
* else
|
||||
* return (((Xtal_Freq / 1000000) + 1)*100);
|
||||
* }
|
||||
*
|
||||
* u32 Xtal_Int = MXL_GetXtalInt(state->Fxtal);
|
||||
* tg_lo = ( ((Fmax/10000 * Xtal_Int)/100) -
|
||||
* ((state->TG_LO/10000)*divider_val *
|
||||
* (state->Fxtal/10000)/100) )*32/((Fmax-Fmin)/10000 *
|
||||
|
@ -18,7 +18,20 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "tda18212_priv.h"
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include "tda18212.h"
|
||||
|
||||
struct tda18212_priv {
|
||||
struct tda18212_config *cfg;
|
||||
struct i2c_adapter *i2c;
|
||||
};
|
||||
|
||||
#define dbg(fmt, arg...) \
|
||||
do { \
|
||||
if (debug) \
|
||||
pr_info("%s: " fmt, __func__, ##arg); \
|
||||
} while (0)
|
||||
|
||||
static int debug;
|
||||
module_param(debug, int, 0644);
|
||||
@ -46,7 +59,8 @@ static int tda18212_wr_regs(struct tda18212_priv *priv, u8 reg, u8 *val,
|
||||
if (ret == 1) {
|
||||
ret = 0;
|
||||
} else {
|
||||
warn("i2c wr failed ret:%d reg:%02x len:%d", ret, reg, len);
|
||||
pr_warn("i2c wr failed ret:%d reg:%02x len:%d\n",
|
||||
ret, reg, len);
|
||||
ret = -EREMOTEIO;
|
||||
}
|
||||
return ret;
|
||||
@ -77,7 +91,8 @@ static int tda18212_rd_regs(struct tda18212_priv *priv, u8 reg, u8 *val,
|
||||
memcpy(val, buf, len);
|
||||
ret = 0;
|
||||
} else {
|
||||
warn("i2c rd failed ret:%d reg:%02x len:%d", ret, reg, len);
|
||||
pr_warn("i2c rd failed ret:%d reg:%02x len:%d\n",
|
||||
ret, reg, len);
|
||||
ret = -EREMOTEIO;
|
||||
}
|
||||
|
||||
@ -129,8 +144,8 @@ static int tda18212_set_params(struct dvb_frontend *fe,
|
||||
{ 0x92, 0x53, 0x03 }, /* DVB-C */
|
||||
};
|
||||
|
||||
dbg("%s: delsys=%d RF=%d BW=%d", __func__,
|
||||
c->delivery_system, c->frequency, c->bandwidth_hz);
|
||||
dbg("delsys=%d RF=%d BW=%d\n",
|
||||
c->delivery_system, c->frequency, c->bandwidth_hz);
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
|
||||
@ -196,7 +211,7 @@ exit:
|
||||
return ret;
|
||||
|
||||
error:
|
||||
dbg("%s: failed:%d", __func__, ret);
|
||||
dbg("failed:%d\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
@ -245,13 +260,13 @@ struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe,
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
|
||||
|
||||
dbg("%s: ret:%d chip ID:%02x", __func__, ret, val);
|
||||
dbg("ret:%d chip ID:%02x\n", ret, val);
|
||||
if (ret || val != 0xc7) {
|
||||
kfree(priv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
info("NXP TDA18212HN successfully identified.");
|
||||
pr_info("NXP TDA18212HN successfully identified\n");
|
||||
|
||||
memcpy(&fe->ops.tuner_ops, &tda18212_tuner_ops,
|
||||
sizeof(struct dvb_tuner_ops));
|
||||
|
@ -676,10 +676,28 @@ fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Overrides for Emacs so that we follow Linus's tabbing style.
|
||||
* ---------------------------------------------------------------------------
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
* End:
|
||||
*/
|
||||
int _tda_printk(struct tda18271_priv *state, const char *level,
|
||||
const char *func, const char *fmt, ...)
|
||||
{
|
||||
struct va_format vaf;
|
||||
va_list args;
|
||||
int rtn;
|
||||
|
||||
va_start(args, fmt);
|
||||
|
||||
vaf.fmt = fmt;
|
||||
vaf.va = &args;
|
||||
|
||||
if (state)
|
||||
rtn = printk("%s%s: [%d-%04x|%c] %pV",
|
||||
level, func, i2c_adapter_id(state->i2c_props.adap),
|
||||
state->i2c_props.addr,
|
||||
(state->role == TDA18271_MASTER) ? 'M' : 'S',
|
||||
&vaf);
|
||||
else
|
||||
rtn = printk("%s%s: %pV", level, func, &vaf);
|
||||
|
||||
va_end(args);
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
@ -1230,7 +1230,7 @@ static int tda18271_set_config(struct dvb_frontend *fe, void *priv_cfg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dvb_tuner_ops tda18271_tuner_ops = {
|
||||
static const struct dvb_tuner_ops tda18271_tuner_ops = {
|
||||
.info = {
|
||||
.name = "NXP TDA18271HD",
|
||||
.frequency_min = 45000000,
|
||||
|
@ -136,29 +136,26 @@ extern int tda18271_debug;
|
||||
#define DBG_ADV 8
|
||||
#define DBG_CAL 16
|
||||
|
||||
#define tda_printk(st, kern, fmt, arg...) do {\
|
||||
if (st) { \
|
||||
struct tda18271_priv *state = st; \
|
||||
printk(kern "%s: [%d-%04x|%s] " fmt, __func__, \
|
||||
i2c_adapter_id(state->i2c_props.adap), \
|
||||
state->i2c_props.addr, \
|
||||
(state->role == TDA18271_MASTER) \
|
||||
? "M" : "S", ##arg); \
|
||||
} else \
|
||||
printk(kern "%s: " fmt, __func__, ##arg); \
|
||||
__attribute__((format(printf, 4, 5)))
|
||||
int _tda_printk(struct tda18271_priv *state, const char *level,
|
||||
const char *func, const char *fmt, ...);
|
||||
|
||||
#define tda_printk(st, lvl, fmt, arg...) \
|
||||
_tda_printk(st, lvl, __func__, fmt, ##arg)
|
||||
|
||||
#define tda_dprintk(st, lvl, fmt, arg...) \
|
||||
do { \
|
||||
if (tda18271_debug & lvl) \
|
||||
tda_printk(st, KERN_DEBUG, fmt, ##arg); \
|
||||
} while (0)
|
||||
|
||||
#define tda_dprintk(st, lvl, fmt, arg...) do {\
|
||||
if (tda18271_debug & lvl) \
|
||||
tda_printk(st, KERN_DEBUG, fmt, ##arg); } while (0)
|
||||
|
||||
#define tda_info(fmt, arg...) printk(KERN_INFO fmt, ##arg)
|
||||
#define tda_warn(fmt, arg...) tda_printk(priv, KERN_WARNING, fmt, ##arg)
|
||||
#define tda_err(fmt, arg...) tda_printk(priv, KERN_ERR, fmt, ##arg)
|
||||
#define tda_dbg(fmt, arg...) tda_dprintk(priv, DBG_INFO, fmt, ##arg)
|
||||
#define tda_map(fmt, arg...) tda_dprintk(priv, DBG_MAP, fmt, ##arg)
|
||||
#define tda_reg(fmt, arg...) tda_dprintk(priv, DBG_REG, fmt, ##arg)
|
||||
#define tda_cal(fmt, arg...) tda_dprintk(priv, DBG_CAL, fmt, ##arg)
|
||||
#define tda_info(fmt, arg...) pr_info(fmt, ##arg)
|
||||
#define tda_warn(fmt, arg...) tda_printk(priv, KERN_WARNING, fmt, ##arg)
|
||||
#define tda_err(fmt, arg...) tda_printk(priv, KERN_ERR, fmt, ##arg)
|
||||
#define tda_dbg(fmt, arg...) tda_dprintk(priv, DBG_INFO, fmt, ##arg)
|
||||
#define tda_map(fmt, arg...) tda_dprintk(priv, DBG_MAP, fmt, ##arg)
|
||||
#define tda_reg(fmt, arg...) tda_dprintk(priv, DBG_REG, fmt, ##arg)
|
||||
#define tda_cal(fmt, arg...) tda_dprintk(priv, DBG_CAL, fmt, ##arg)
|
||||
|
||||
#define tda_fail(ret) \
|
||||
({ \
|
||||
|
@ -176,7 +176,7 @@ static int tda827xo_set_params(struct dvb_frontend *fe,
|
||||
if_freq = 5000000;
|
||||
break;
|
||||
}
|
||||
tuner_freq = params->frequency + if_freq;
|
||||
tuner_freq = params->frequency;
|
||||
|
||||
i = 0;
|
||||
while (tda827x_table[i].lomax < tuner_freq) {
|
||||
@ -185,6 +185,8 @@ static int tda827xo_set_params(struct dvb_frontend *fe,
|
||||
i++;
|
||||
}
|
||||
|
||||
tuner_freq += if_freq;
|
||||
|
||||
N = ((tuner_freq + 125000) / 250000) << (tda827x_table[i].spd + 2);
|
||||
buf[0] = 0;
|
||||
buf[1] = (N>>8) | 0x40;
|
||||
@ -540,7 +542,7 @@ static int tda827xa_set_params(struct dvb_frontend *fe,
|
||||
if_freq = 5000000;
|
||||
break;
|
||||
}
|
||||
tuner_freq = params->frequency + if_freq;
|
||||
tuner_freq = params->frequency;
|
||||
|
||||
if (fe->ops.info.type == FE_QAM) {
|
||||
dprintk("%s select tda827xa_dvbc\n", __func__);
|
||||
@ -554,6 +556,8 @@ static int tda827xa_set_params(struct dvb_frontend *fe,
|
||||
i++;
|
||||
}
|
||||
|
||||
tuner_freq += if_freq;
|
||||
|
||||
N = ((tuner_freq + 31250) / 62500) << frequency_map[i].spd;
|
||||
buf[0] = 0; // subaddress
|
||||
buf[1] = N >> 8;
|
||||
|
@ -614,6 +614,13 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type,
|
||||
p += len;
|
||||
size -= len;
|
||||
}
|
||||
|
||||
/* silently fail if the frontend doesn't support I2C flush */
|
||||
rc = do_tuner_callback(fe, XC2028_I2C_FLUSH, 0);
|
||||
if ((rc < 0) && (rc != -EINVAL)) {
|
||||
tuner_err("error executing flush: %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -933,11 +940,16 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
|
||||
* that xc2028 will be in a safe state.
|
||||
* Maybe this might also be needed for DTV.
|
||||
*/
|
||||
if (new_type == V4L2_TUNER_ANALOG_TV) {
|
||||
switch (new_type) {
|
||||
case V4L2_TUNER_ANALOG_TV:
|
||||
rc = send_seq(priv, {0x00, 0x00});
|
||||
|
||||
/* Analog modes require offset = 0 */
|
||||
} else {
|
||||
/* Analog mode requires offset = 0 */
|
||||
break;
|
||||
case V4L2_TUNER_RADIO:
|
||||
/* Radio mode requires offset = 0 */
|
||||
break;
|
||||
case V4L2_TUNER_DIGITAL_TV:
|
||||
/*
|
||||
* Digital modes require an offset to adjust to the
|
||||
* proper frequency. The offset depends on what
|
||||
|
@ -54,6 +54,7 @@ struct xc2028_config {
|
||||
/* xc2028 commands for callback */
|
||||
#define XC2028_TUNER_RESET 0
|
||||
#define XC2028_RESET_CLK 1
|
||||
#define XC2028_I2C_FLUSH 2
|
||||
|
||||
#if defined(CONFIG_MEDIA_TUNER_XC2028) || (defined(CONFIG_MEDIA_TUNER_XC2028_MODULE) && defined(MODULE))
|
||||
extern struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
|
||||
|
@ -12,5 +12,5 @@ obj-$(CONFIG_DVB_B2C2_FLEXCOP_PCI) += b2c2-flexcop-pci.o
|
||||
b2c2-flexcop-usb-objs = flexcop-usb.o
|
||||
obj-$(CONFIG_DVB_B2C2_FLEXCOP_USB) += b2c2-flexcop-usb.o
|
||||
|
||||
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
|
||||
EXTRA_CFLAGS += -Idrivers/media/common/tuners/
|
||||
ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
|
||||
ccflags-y += -Idrivers/media/common/tuners/
|
||||
|
@ -1,6 +1,6 @@
|
||||
obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o
|
||||
|
||||
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
|
||||
EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
|
||||
EXTRA_CFLAGS += -Idrivers/media/video/bt8xx
|
||||
EXTRA_CFLAGS += -Idrivers/media/common/tuners
|
||||
ccflags-y += -Idrivers/media/dvb/dvb-core
|
||||
ccflags-y += -Idrivers/media/dvb/frontends
|
||||
ccflags-y += -Idrivers/media/video/bt8xx
|
||||
ccflags-y += -Idrivers/media/common/tuners
|
||||
|
@ -6,9 +6,9 @@ ddbridge-objs := ddbridge-core.o
|
||||
|
||||
obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o
|
||||
|
||||
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
|
||||
EXTRA_CFLAGS += -Idrivers/media/dvb/frontends/
|
||||
EXTRA_CFLAGS += -Idrivers/media/common/tuners/
|
||||
ccflags-y += -Idrivers/media/dvb/dvb-core/
|
||||
ccflags-y += -Idrivers/media/dvb/frontends/
|
||||
ccflags-y += -Idrivers/media/common/tuners/
|
||||
|
||||
# For the staging CI driver cxd2099
|
||||
EXTRA_CFLAGS += -Idrivers/staging/cxd2099/
|
||||
ccflags-y += -Idrivers/staging/cxd2099/
|
||||
|
@ -507,15 +507,14 @@ static u32 ddb_input_avail(struct ddb_input *input)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t ddb_input_read(struct ddb_input *input, u8 *buf, size_t count)
|
||||
static ssize_t ddb_input_read(struct ddb_input *input, u8 *buf, size_t count)
|
||||
{
|
||||
struct ddb *dev = input->port->dev;
|
||||
u32 left = count;
|
||||
u32 idx, off, free, stat = input->stat;
|
||||
u32 idx, free, stat = input->stat;
|
||||
int ret;
|
||||
|
||||
idx = (stat >> 11) & 0x1f;
|
||||
off = (stat & 0x7ff) << 7;
|
||||
|
||||
while (left) {
|
||||
if (input->cbuf == idx)
|
||||
@ -525,6 +524,8 @@ static size_t ddb_input_read(struct ddb_input *input, u8 *buf, size_t count)
|
||||
free = left;
|
||||
ret = copy_to_user(buf, input->vbuf[input->cbuf] +
|
||||
input->coff, free);
|
||||
if (ret)
|
||||
return -EFAULT;
|
||||
input->coff += free;
|
||||
if (input->coff == input->dma_buf_size) {
|
||||
input->coff = 0;
|
||||
@ -939,6 +940,8 @@ static ssize_t ts_read(struct file *file, char *buf,
|
||||
break;
|
||||
}
|
||||
read = ddb_input_read(input, buf, left);
|
||||
if (read < 0)
|
||||
return read;
|
||||
left -= read;
|
||||
buf += read;
|
||||
}
|
||||
@ -1438,7 +1441,7 @@ static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct ddb *dev = file->private_data;
|
||||
void *parg = (void *)arg;
|
||||
int res = -EFAULT;
|
||||
int res;
|
||||
|
||||
switch (cmd) {
|
||||
case IOCTL_DDB_FLASHIO:
|
||||
@ -1447,29 +1450,29 @@ static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
u8 *rbuf, *wbuf;
|
||||
|
||||
if (copy_from_user(&fio, parg, sizeof(fio)))
|
||||
break;
|
||||
if (fio.write_len + fio.read_len > 1028) {
|
||||
printk(KERN_ERR "IOBUF too small\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
return -EFAULT;
|
||||
|
||||
if (fio.write_len > 1028 || fio.read_len > 1028)
|
||||
return -EINVAL;
|
||||
if (fio.write_len + fio.read_len > 1028)
|
||||
return -EINVAL;
|
||||
|
||||
wbuf = &dev->iobuf[0];
|
||||
if (!wbuf)
|
||||
return -ENOMEM;
|
||||
rbuf = wbuf + fio.write_len;
|
||||
if (copy_from_user(wbuf, fio.write_buf, fio.write_len)) {
|
||||
vfree(wbuf);
|
||||
break;
|
||||
}
|
||||
res = flashio(dev, wbuf, fio.write_len,
|
||||
rbuf, fio.read_len);
|
||||
|
||||
if (copy_from_user(wbuf, fio.write_buf, fio.write_len))
|
||||
return -EFAULT;
|
||||
res = flashio(dev, wbuf, fio.write_len, rbuf, fio.read_len);
|
||||
if (res)
|
||||
return res;
|
||||
if (copy_to_user(fio.read_buf, rbuf, fio.read_len))
|
||||
res = -EFAULT;
|
||||
return -EFAULT;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
return -ENOTTY;
|
||||
}
|
||||
return res;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct file_operations ddb_fops = {
|
||||
|
@ -1,3 +1,3 @@
|
||||
obj-$(CONFIG_DVB_DM1105) += dm1105.o
|
||||
|
||||
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends
|
||||
ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends
|
||||
|
@ -149,30 +149,25 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
|
||||
|
||||
dprintk ("%s\n", __func__);
|
||||
|
||||
if (mutex_lock_interruptible (&events->mtx))
|
||||
return;
|
||||
if ((status & FE_HAS_LOCK) && fe->ops.get_frontend)
|
||||
fe->ops.get_frontend(fe, &fepriv->parameters_out);
|
||||
|
||||
mutex_lock(&events->mtx);
|
||||
|
||||
wp = (events->eventw + 1) % MAX_EVENT;
|
||||
|
||||
if (wp == events->eventr) {
|
||||
events->overflow = 1;
|
||||
events->eventr = (events->eventr + 1) % MAX_EVENT;
|
||||
}
|
||||
|
||||
e = &events->events[events->eventw];
|
||||
|
||||
if (status & FE_HAS_LOCK)
|
||||
if (fe->ops.get_frontend)
|
||||
fe->ops.get_frontend(fe, &fepriv->parameters_out);
|
||||
|
||||
e->status = status;
|
||||
e->parameters = fepriv->parameters_out;
|
||||
|
||||
events->eventw = wp;
|
||||
|
||||
mutex_unlock(&events->mtx);
|
||||
|
||||
e->status = status;
|
||||
|
||||
wake_up_interruptible (&events->wait_queue);
|
||||
}
|
||||
|
||||
@ -207,19 +202,24 @@ static int dvb_frontend_get_event(struct dvb_frontend *fe,
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (mutex_lock_interruptible (&events->mtx))
|
||||
return -ERESTARTSYS;
|
||||
|
||||
memcpy (event, &events->events[events->eventr],
|
||||
sizeof(struct dvb_frontend_event));
|
||||
|
||||
mutex_lock(&events->mtx);
|
||||
*event = events->events[events->eventr];
|
||||
events->eventr = (events->eventr + 1) % MAX_EVENT;
|
||||
|
||||
mutex_unlock(&events->mtx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dvb_frontend_clear_events(struct dvb_frontend *fe)
|
||||
{
|
||||
struct dvb_frontend_private *fepriv = fe->frontend_priv;
|
||||
struct dvb_fe_events *events = &fepriv->events;
|
||||
|
||||
mutex_lock(&events->mtx);
|
||||
events->eventr = events->eventw;
|
||||
mutex_unlock(&events->mtx);
|
||||
}
|
||||
|
||||
static void dvb_frontend_init(struct dvb_frontend *fe)
|
||||
{
|
||||
dprintk ("DVB: initialising adapter %i frontend %i (%s)...\n",
|
||||
@ -537,7 +537,6 @@ static int dvb_frontend_thread(void *data)
|
||||
{
|
||||
struct dvb_frontend *fe = data;
|
||||
struct dvb_frontend_private *fepriv = fe->frontend_priv;
|
||||
unsigned long timeout;
|
||||
fe_status_t s;
|
||||
enum dvbfe_algo algo;
|
||||
|
||||
@ -558,7 +557,7 @@ static int dvb_frontend_thread(void *data)
|
||||
while (1) {
|
||||
up(&fepriv->sem); /* is locked when we enter the thread... */
|
||||
restart:
|
||||
timeout = wait_event_interruptible_timeout(fepriv->wait_queue,
|
||||
wait_event_interruptible_timeout(fepriv->wait_queue,
|
||||
dvb_frontend_should_wakeup(fe) || kthread_should_stop()
|
||||
|| freezing(current),
|
||||
fepriv->delay);
|
||||
@ -577,12 +576,10 @@ restart:
|
||||
|
||||
if (fepriv->reinitialise) {
|
||||
dvb_frontend_init(fe);
|
||||
if (fepriv->tone != -1) {
|
||||
if (fe->ops.set_tone && fepriv->tone != -1)
|
||||
fe->ops.set_tone(fe, fepriv->tone);
|
||||
}
|
||||
if (fepriv->voltage != -1) {
|
||||
if (fe->ops.set_voltage && fepriv->voltage != -1)
|
||||
fe->ops.set_voltage(fe, fepriv->voltage);
|
||||
}
|
||||
fepriv->reinitialise = 0;
|
||||
}
|
||||
|
||||
@ -1019,6 +1016,29 @@ static int is_legacy_delivery_system(fe_delivery_system_t s)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Initialize the cache with some default values derived from the
|
||||
* legacy frontend_info structure.
|
||||
*/
|
||||
static void dtv_property_cache_init(struct dvb_frontend *fe,
|
||||
struct dtv_frontend_properties *c)
|
||||
{
|
||||
switch (fe->ops.info.type) {
|
||||
case FE_QPSK:
|
||||
c->modulation = QPSK; /* implied for DVB-S in legacy API */
|
||||
c->rolloff = ROLLOFF_35;/* implied for DVB-S */
|
||||
c->delivery_system = SYS_DVBS;
|
||||
break;
|
||||
case FE_QAM:
|
||||
c->delivery_system = SYS_DVBC_ANNEX_AC;
|
||||
break;
|
||||
case FE_OFDM:
|
||||
c->delivery_system = SYS_DVBT;
|
||||
break;
|
||||
case FE_ATSC:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Synchronise the legacy tuning parameters into the cache, so that demodulator
|
||||
* drivers can use a single set_frontend tuning function, regardless of whether
|
||||
* it's being used for the legacy or new API, reducing code and complexity.
|
||||
@ -1032,17 +1052,13 @@ static void dtv_property_cache_sync(struct dvb_frontend *fe,
|
||||
|
||||
switch (fe->ops.info.type) {
|
||||
case FE_QPSK:
|
||||
c->modulation = QPSK; /* implied for DVB-S in legacy API */
|
||||
c->rolloff = ROLLOFF_35;/* implied for DVB-S */
|
||||
c->symbol_rate = p->u.qpsk.symbol_rate;
|
||||
c->fec_inner = p->u.qpsk.fec_inner;
|
||||
c->delivery_system = SYS_DVBS;
|
||||
break;
|
||||
case FE_QAM:
|
||||
c->symbol_rate = p->u.qam.symbol_rate;
|
||||
c->fec_inner = p->u.qam.fec_inner;
|
||||
c->modulation = p->u.qam.modulation;
|
||||
c->delivery_system = SYS_DVBC_ANNEX_AC;
|
||||
break;
|
||||
case FE_OFDM:
|
||||
if (p->u.ofdm.bandwidth == BANDWIDTH_6_MHZ)
|
||||
@ -1060,7 +1076,6 @@ static void dtv_property_cache_sync(struct dvb_frontend *fe,
|
||||
c->transmission_mode = p->u.ofdm.transmission_mode;
|
||||
c->guard_interval = p->u.ofdm.guard_interval;
|
||||
c->hierarchy = p->u.ofdm.hierarchy_information;
|
||||
c->delivery_system = SYS_DVBT;
|
||||
break;
|
||||
case FE_ATSC:
|
||||
c->modulation = p->u.vsb.modulation;
|
||||
@ -1132,16 +1147,13 @@ static void dtv_property_adv_params_sync(struct dvb_frontend *fe)
|
||||
p->frequency = c->frequency;
|
||||
p->inversion = c->inversion;
|
||||
|
||||
switch(c->modulation) {
|
||||
case PSK_8:
|
||||
case APSK_16:
|
||||
case APSK_32:
|
||||
case QPSK:
|
||||
if (c->delivery_system == SYS_DSS ||
|
||||
c->delivery_system == SYS_DVBS ||
|
||||
c->delivery_system == SYS_DVBS2 ||
|
||||
c->delivery_system == SYS_ISDBS ||
|
||||
c->delivery_system == SYS_TURBO) {
|
||||
p->u.qpsk.symbol_rate = c->symbol_rate;
|
||||
p->u.qpsk.fec_inner = c->fec_inner;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Fake out a generic DVB-T request so we pass validation in the ioctl */
|
||||
@ -1824,9 +1836,17 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
|
||||
|
||||
memcpy (&fepriv->parameters_in, parg,
|
||||
sizeof (struct dvb_frontend_parameters));
|
||||
dtv_property_cache_init(fe, c);
|
||||
dtv_property_cache_sync(fe, c, &fepriv->parameters_in);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize output parameters to match the values given by
|
||||
* the user. FE_SET_FRONTEND triggers an initial frontend event
|
||||
* with status = 0, which copies output parameters to userspace.
|
||||
*/
|
||||
fepriv->parameters_out = fepriv->parameters_in;
|
||||
|
||||
memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings));
|
||||
memcpy(&fetunesettings.parameters, parg,
|
||||
sizeof (struct dvb_frontend_parameters));
|
||||
@ -1884,8 +1904,9 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
|
||||
/* Request the search algorithm to search */
|
||||
fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
|
||||
|
||||
dvb_frontend_wakeup(fe);
|
||||
dvb_frontend_clear_events(fe);
|
||||
dvb_frontend_add_event(fe, 0);
|
||||
dvb_frontend_wakeup(fe);
|
||||
fepriv->status = 0;
|
||||
err = 0;
|
||||
break;
|
||||
|
@ -209,6 +209,7 @@ struct dvb_tuner_ops {
|
||||
|
||||
int (*get_frequency)(struct dvb_frontend *fe, u32 *frequency);
|
||||
int (*get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth);
|
||||
int (*get_if_frequency)(struct dvb_frontend *fe, u32 *frequency);
|
||||
|
||||
#define TUNER_STATUS_LOCKED 1
|
||||
#define TUNER_STATUS_STEREO 2
|
||||
|
@ -258,6 +258,19 @@ config DVB_USB_AF9005_REMOTE
|
||||
Say Y here to support the default remote control decoding for the
|
||||
Afatech AF9005 based receiver.
|
||||
|
||||
config DVB_USB_PCTV452E
|
||||
tristate "Pinnacle PCTV HDTV Pro USB device/TT Connect S2-3600"
|
||||
depends on DVB_USB
|
||||
select TTPCI_EEPROM
|
||||
select DVB_LNBP22 if !DVB_FE_CUSTOMISE
|
||||
select DVB_STB0899 if !DVB_FE_CUSTOMISE
|
||||
select DVB_STB6100 if !DVB_FE_CUSTOMISE
|
||||
help
|
||||
Support for external USB adapter designed by Pinnacle,
|
||||
shipped under the brand name 'PCTV HDTV Pro USB'.
|
||||
Also supports TT Connect S2-3600/3650 cards.
|
||||
Say Y if you own such a device and want to use it.
|
||||
|
||||
config DVB_USB_DW2102
|
||||
tristate "DvbWorld & TeVii DVB-S/S2 USB2.0 support"
|
||||
depends on DVB_USB
|
||||
@ -374,3 +387,18 @@ config DVB_USB_TECHNISAT_USB2
|
||||
select DVB_STV6110x if !DVB_FE_CUSTOMISE
|
||||
help
|
||||
Say Y here to support the Technisat USB2 DVB-S/S2 device
|
||||
|
||||
config DVB_USB_IT913X
|
||||
tristate "it913x driver"
|
||||
depends on DVB_USB
|
||||
select DVB_IT913X_FE
|
||||
help
|
||||
Say Y here to support the it913x device
|
||||
|
||||
config DVB_USB_MXL111SF
|
||||
tristate "MxL111SF DTV USB2.0 support"
|
||||
depends on DVB_USB
|
||||
select DVB_LGDT3305 if !DVB_FE_CUSTOMISE
|
||||
select VIDEO_TVEEPROM
|
||||
help
|
||||
Say Y here to support the MxL111SF USB2.0 DTV receiver.
|
||||
|
@ -64,6 +64,9 @@ obj-$(CONFIG_DVB_USB_AF9005_REMOTE) += dvb-usb-af9005-remote.o
|
||||
dvb-usb-anysee-objs = anysee.o
|
||||
obj-$(CONFIG_DVB_USB_ANYSEE) += dvb-usb-anysee.o
|
||||
|
||||
dvb-usb-pctv452e-objs = pctv452e.o
|
||||
obj-$(CONFIG_DVB_USB_PCTV452E) += dvb-usb-pctv452e.o
|
||||
|
||||
dvb-usb-dw2102-objs = dw2102.o
|
||||
obj-$(CONFIG_DVB_USB_DW2102) += dvb-usb-dw2102.o
|
||||
|
||||
@ -94,7 +97,15 @@ obj-$(CONFIG_DVB_USB_LME2510) += dvb-usb-lmedm04.o
|
||||
dvb-usb-technisat-usb2-objs = technisat-usb2.o
|
||||
obj-$(CONFIG_DVB_USB_TECHNISAT_USB2) += dvb-usb-technisat-usb2.o
|
||||
|
||||
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
|
||||
# due to tuner-xc3028
|
||||
EXTRA_CFLAGS += -Idrivers/media/common/tuners
|
||||
dvb-usb-it913x-objs := it913x.o
|
||||
obj-$(CONFIG_DVB_USB_IT913X) += dvb-usb-it913x.o
|
||||
|
||||
dvb-usb-mxl111sf-objs = mxl111sf.o mxl111sf-phy.o mxl111sf-i2c.o mxl111sf-gpio.o
|
||||
obj-$(CONFIG_DVB_USB_MXL111SF) += dvb-usb-mxl111sf.o
|
||||
obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-tuner.o
|
||||
|
||||
ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
|
||||
# due to tuner-xc3028
|
||||
ccflags-y += -Idrivers/media/common/tuners
|
||||
EXTRA_CFLAGS += -Idrivers/media/dvb/ttpci
|
||||
|
||||
|
@ -127,6 +127,8 @@ static struct dvb_usb_device_properties a800_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
.pid_filter_count = 32,
|
||||
.streaming_ctrl = dibusb2_0_streaming_ctrl,
|
||||
@ -147,7 +149,7 @@ static struct dvb_usb_device_properties a800_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
}},
|
||||
.size_of_priv = sizeof(struct dibusb_state),
|
||||
},
|
||||
},
|
||||
|
@ -63,11 +63,9 @@ static int af9005_write_word_agc(struct dvb_usb_device *d, u16 reghi,
|
||||
u16 reglo, u8 pos, u8 len, u16 value)
|
||||
{
|
||||
int ret;
|
||||
u8 temp;
|
||||
|
||||
if ((ret = af9005_write_ofdm_register(d, reglo, (u8) (value & 0xff))))
|
||||
return ret;
|
||||
temp = (u8) ((value & 0x0300) >> 8);
|
||||
return af9005_write_register_bits(d, reghi, pos, len,
|
||||
(u8) ((value & 0x300) >> 8));
|
||||
}
|
||||
|
@ -815,7 +815,7 @@ static int af9005_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
debug_dump(buf, 8, printk);
|
||||
}
|
||||
}
|
||||
adap->fe = af9005_fe_attach(adap->dev);
|
||||
adap->fe_adap[0].fe = af9005_fe_attach(adap->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -999,6 +999,8 @@ static struct dvb_usb_device_properties af9005_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.caps =
|
||||
DVB_USB_ADAP_HAS_PID_FILTER |
|
||||
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
@ -1018,6 +1020,7 @@ static struct dvb_usb_device_properties af9005_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
}
|
||||
},
|
||||
.power_ctrl = af9005_power_ctrl,
|
||||
|
@ -744,29 +744,31 @@ static const struct af9015_rc_setup af9015_rc_setup_hashes[] = {
|
||||
};
|
||||
|
||||
static const struct af9015_rc_setup af9015_rc_setup_usbids[] = {
|
||||
{ (USB_VID_TERRATEC << 16) + USB_PID_TERRATEC_CINERGY_T_STICK_RC,
|
||||
{ (USB_VID_TERRATEC << 16) | USB_PID_TERRATEC_CINERGY_T_STICK_RC,
|
||||
RC_MAP_TERRATEC_SLIM_2 },
|
||||
{ (USB_VID_TERRATEC << 16) + USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC,
|
||||
{ (USB_VID_TERRATEC << 16) | USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC,
|
||||
RC_MAP_TERRATEC_SLIM },
|
||||
{ (USB_VID_VISIONPLUS << 16) + USB_PID_AZUREWAVE_AD_TU700,
|
||||
{ (USB_VID_VISIONPLUS << 16) | USB_PID_AZUREWAVE_AD_TU700,
|
||||
RC_MAP_AZUREWAVE_AD_TU700 },
|
||||
{ (USB_VID_VISIONPLUS << 16) + USB_PID_TINYTWIN,
|
||||
{ (USB_VID_VISIONPLUS << 16) | USB_PID_TINYTWIN,
|
||||
RC_MAP_AZUREWAVE_AD_TU700 },
|
||||
{ (USB_VID_MSI_2 << 16) + USB_PID_MSI_DIGI_VOX_MINI_III,
|
||||
{ (USB_VID_MSI_2 << 16) | USB_PID_MSI_DIGI_VOX_MINI_III,
|
||||
RC_MAP_MSI_DIGIVOX_III },
|
||||
{ (USB_VID_MSI_2 << 16) + USB_PID_MSI_DIGIVOX_DUO,
|
||||
{ (USB_VID_MSI_2 << 16) | USB_PID_MSI_DIGIVOX_DUO,
|
||||
RC_MAP_MSI_DIGIVOX_III },
|
||||
{ (USB_VID_LEADTEK << 16) + USB_PID_WINFAST_DTV_DONGLE_GOLD,
|
||||
{ (USB_VID_LEADTEK << 16) | USB_PID_WINFAST_DTV_DONGLE_GOLD,
|
||||
RC_MAP_LEADTEK_Y04G0051 },
|
||||
{ (USB_VID_AVERMEDIA << 16) + USB_PID_AVERMEDIA_VOLAR_X,
|
||||
{ (USB_VID_LEADTEK << 16) | USB_PID_WINFAST_DTV2000DS,
|
||||
RC_MAP_LEADTEK_Y04G0051 },
|
||||
{ (USB_VID_AVERMEDIA << 16) | USB_PID_AVERMEDIA_VOLAR_X,
|
||||
RC_MAP_AVERMEDIA_M135A },
|
||||
{ (USB_VID_AFATECH << 16) + USB_PID_TREKSTOR_DVBT,
|
||||
{ (USB_VID_AFATECH << 16) | USB_PID_TREKSTOR_DVBT,
|
||||
RC_MAP_TREKSTOR },
|
||||
{ (USB_VID_KWORLD_2 << 16) + USB_PID_TINYTWIN_2,
|
||||
{ (USB_VID_KWORLD_2 << 16) | USB_PID_TINYTWIN_2,
|
||||
RC_MAP_DIGITALNOW_TINYTWIN },
|
||||
{ (USB_VID_GTEK << 16) + USB_PID_TINYTWIN_3,
|
||||
{ (USB_VID_GTEK << 16) | USB_PID_TINYTWIN_3,
|
||||
RC_MAP_DIGITALNOW_TINYTWIN },
|
||||
{ (USB_VID_KWORLD_2 << 16) + USB_PID_SVEON_STV22,
|
||||
{ (USB_VID_KWORLD_2 << 16) | USB_PID_SVEON_STV22,
|
||||
RC_MAP_MSI_DIGIVOX_III },
|
||||
{ }
|
||||
};
|
||||
@ -859,13 +861,13 @@ static int af9015_read_config(struct usb_device *udev)
|
||||
for (i = 0; i < af9015_properties_count; i++) {
|
||||
/* USB1.1 set smaller buffersize and disable 2nd adapter */
|
||||
if (udev->speed == USB_SPEED_FULL) {
|
||||
af9015_properties[i].adapter[0].stream.u.bulk.buffersize
|
||||
af9015_properties[i].adapter[0].fe[0].stream.u.bulk.buffersize
|
||||
= TS_USB11_FRAME_SIZE;
|
||||
/* disable 2nd adapter because we don't have
|
||||
PID-filters */
|
||||
af9015_config.dual_mode = 0;
|
||||
} else {
|
||||
af9015_properties[i].adapter[0].stream.u.bulk.buffersize
|
||||
af9015_properties[i].adapter[0].fe[0].stream.u.bulk.buffersize
|
||||
= TS_USB20_FRAME_SIZE;
|
||||
}
|
||||
}
|
||||
@ -1111,10 +1113,10 @@ static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
}
|
||||
|
||||
/* attach demodulator */
|
||||
adap->fe = dvb_attach(af9013_attach, &af9015_af9013_config[adap->id],
|
||||
adap->fe_adap[0].fe = dvb_attach(af9013_attach, &af9015_af9013_config[adap->id],
|
||||
&adap->dev->i2c_adap);
|
||||
|
||||
return adap->fe == NULL ? -ENODEV : 0;
|
||||
return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
|
||||
}
|
||||
|
||||
static struct mt2060_config af9015_mt2060_config = {
|
||||
@ -1188,49 +1190,49 @@ static int af9015_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
switch (af9015_af9013_config[adap->id].tuner) {
|
||||
case AF9013_TUNER_MT2060:
|
||||
case AF9013_TUNER_MT2060_2:
|
||||
ret = dvb_attach(mt2060_attach, adap->fe, &adap->dev->i2c_adap,
|
||||
ret = dvb_attach(mt2060_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap,
|
||||
&af9015_mt2060_config,
|
||||
af9015_config.mt2060_if1[adap->id])
|
||||
== NULL ? -ENODEV : 0;
|
||||
break;
|
||||
case AF9013_TUNER_QT1010:
|
||||
case AF9013_TUNER_QT1010A:
|
||||
ret = dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap,
|
||||
ret = dvb_attach(qt1010_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap,
|
||||
&af9015_qt1010_config) == NULL ? -ENODEV : 0;
|
||||
break;
|
||||
case AF9013_TUNER_TDA18271:
|
||||
ret = dvb_attach(tda18271_attach, adap->fe, 0xc0,
|
||||
ret = dvb_attach(tda18271_attach, adap->fe_adap[0].fe, 0xc0,
|
||||
&adap->dev->i2c_adap,
|
||||
&af9015_tda18271_config) == NULL ? -ENODEV : 0;
|
||||
break;
|
||||
case AF9013_TUNER_TDA18218:
|
||||
ret = dvb_attach(tda18218_attach, adap->fe,
|
||||
ret = dvb_attach(tda18218_attach, adap->fe_adap[0].fe,
|
||||
&adap->dev->i2c_adap,
|
||||
&af9015_tda18218_config) == NULL ? -ENODEV : 0;
|
||||
break;
|
||||
case AF9013_TUNER_MXL5003D:
|
||||
ret = dvb_attach(mxl5005s_attach, adap->fe,
|
||||
ret = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe,
|
||||
&adap->dev->i2c_adap,
|
||||
&af9015_mxl5003_config) == NULL ? -ENODEV : 0;
|
||||
break;
|
||||
case AF9013_TUNER_MXL5005D:
|
||||
case AF9013_TUNER_MXL5005R:
|
||||
ret = dvb_attach(mxl5005s_attach, adap->fe,
|
||||
ret = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe,
|
||||
&adap->dev->i2c_adap,
|
||||
&af9015_mxl5005_config) == NULL ? -ENODEV : 0;
|
||||
break;
|
||||
case AF9013_TUNER_ENV77H11D5:
|
||||
ret = dvb_attach(dvb_pll_attach, adap->fe, 0xc0,
|
||||
ret = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0xc0,
|
||||
&adap->dev->i2c_adap,
|
||||
DVB_PLL_TDA665X) == NULL ? -ENODEV : 0;
|
||||
break;
|
||||
case AF9013_TUNER_MC44S803:
|
||||
ret = dvb_attach(mc44s803_attach, adap->fe,
|
||||
ret = dvb_attach(mc44s803_attach, adap->fe_adap[0].fe,
|
||||
&adap->dev->i2c_adap,
|
||||
&af9015_mc44s803_config) == NULL ? -ENODEV : 0;
|
||||
break;
|
||||
case AF9013_TUNER_MXL5007T:
|
||||
ret = dvb_attach(mxl5007t_attach, adap->fe,
|
||||
ret = dvb_attach(mxl5007t_attach, adap->fe_adap[0].fe,
|
||||
&adap->dev->i2c_adap,
|
||||
0xc0, &af9015_mxl5007t_config) == NULL ? -ENODEV : 0;
|
||||
break;
|
||||
@ -1304,6 +1306,8 @@ static struct dvb_usb_device_properties af9015_properties[] = {
|
||||
.num_adapters = 2,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
|
||||
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
|
||||
@ -1319,8 +1323,11 @@ static struct dvb_usb_device_properties af9015_properties[] = {
|
||||
.count = 6,
|
||||
.endpoint = 0x84,
|
||||
},
|
||||
}},
|
||||
},
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.frontend_attach =
|
||||
af9015_af9013_frontend_attach,
|
||||
.tuner_attach = af9015_tuner_attach,
|
||||
@ -1335,6 +1342,7 @@ static struct dvb_usb_device_properties af9015_properties[] = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
}
|
||||
},
|
||||
|
||||
@ -1432,6 +1440,8 @@ static struct dvb_usb_device_properties af9015_properties[] = {
|
||||
.num_adapters = 2,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
|
||||
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
|
||||
@ -1447,8 +1457,11 @@ static struct dvb_usb_device_properties af9015_properties[] = {
|
||||
.count = 6,
|
||||
.endpoint = 0x84,
|
||||
},
|
||||
}},
|
||||
},
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.frontend_attach =
|
||||
af9015_af9013_frontend_attach,
|
||||
.tuner_attach = af9015_tuner_attach,
|
||||
@ -1463,6 +1476,7 @@ static struct dvb_usb_device_properties af9015_properties[] = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
}
|
||||
},
|
||||
|
||||
@ -1549,6 +1563,8 @@ static struct dvb_usb_device_properties af9015_properties[] = {
|
||||
.num_adapters = 2,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
|
||||
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
|
||||
@ -1564,8 +1580,11 @@ static struct dvb_usb_device_properties af9015_properties[] = {
|
||||
.count = 6,
|
||||
.endpoint = 0x84,
|
||||
},
|
||||
}},
|
||||
},
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.frontend_attach =
|
||||
af9015_af9013_frontend_attach,
|
||||
.tuner_attach = af9015_tuner_attach,
|
||||
@ -1580,6 +1599,7 @@ static struct dvb_usb_device_properties af9015_properties[] = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -446,6 +446,114 @@ static struct isl6423_config anysee_isl6423_config = {
|
||||
* IOE[5] STV0903 1=enabled
|
||||
*/
|
||||
|
||||
static int anysee_frontend_ctrl(struct dvb_frontend *fe, int onoff)
|
||||
{
|
||||
struct dvb_usb_adapter *adap = fe->dvb->priv;
|
||||
struct anysee_state *state = adap->dev->priv;
|
||||
int ret;
|
||||
|
||||
deb_info("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff);
|
||||
|
||||
/* no frontend sleep control */
|
||||
if (onoff == 0)
|
||||
return 0;
|
||||
|
||||
switch (state->hw) {
|
||||
case ANYSEE_HW_507FA: /* 15 */
|
||||
/* E30 Combo Plus */
|
||||
/* E30 C Plus */
|
||||
|
||||
if ((fe->id ^ dvb_usb_anysee_delsys) == 0) {
|
||||
/* disable DVB-T demod on IOD[0] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 0),
|
||||
0x01);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* enable DVB-C demod on IOD[5] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
|
||||
0x20);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* enable DVB-C tuner on IOE[0] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0),
|
||||
0x01);
|
||||
if (ret)
|
||||
goto error;
|
||||
} else {
|
||||
/* disable DVB-C demod on IOD[5] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
|
||||
0x20);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* enable DVB-T demod on IOD[0] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0),
|
||||
0x01);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* enable DVB-T tuner on IOE[0] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0),
|
||||
0x01);
|
||||
if (ret)
|
||||
goto error;
|
||||
}
|
||||
|
||||
break;
|
||||
case ANYSEE_HW_508TC: /* 18 */
|
||||
case ANYSEE_HW_508PTC: /* 21 */
|
||||
/* E7 TC */
|
||||
/* E7 PTC */
|
||||
|
||||
if ((fe->id ^ dvb_usb_anysee_delsys) == 0) {
|
||||
/* disable DVB-T demod on IOD[6] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 6),
|
||||
0x40);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* enable DVB-C demod on IOD[5] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
|
||||
0x20);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* enable IF route on IOE[0] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0),
|
||||
0x01);
|
||||
if (ret)
|
||||
goto error;
|
||||
} else {
|
||||
/* disable DVB-C demod on IOD[5] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
|
||||
0x20);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* enable DVB-T demod on IOD[6] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 6),
|
||||
0x40);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* enable IF route on IOE[0] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0),
|
||||
0x01);
|
||||
if (ret)
|
||||
goto error;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
int ret;
|
||||
@ -466,41 +574,54 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
}
|
||||
};
|
||||
|
||||
/* Check which hardware we have.
|
||||
* We must do this call two times to get reliable values (hw bug).
|
||||
*/
|
||||
ret = anysee_get_hw_info(adap->dev, hw_info);
|
||||
if (ret)
|
||||
goto error;
|
||||
/* detect hardware only once */
|
||||
if (adap->fe_adap[0].fe == NULL) {
|
||||
/* Check which hardware we have.
|
||||
* We must do this call two times to get reliable values (hw bug).
|
||||
*/
|
||||
ret = anysee_get_hw_info(adap->dev, hw_info);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = anysee_get_hw_info(adap->dev, hw_info);
|
||||
if (ret)
|
||||
goto error;
|
||||
ret = anysee_get_hw_info(adap->dev, hw_info);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* Meaning of these info bytes are guessed. */
|
||||
info("firmware version:%d.%d hardware id:%d",
|
||||
hw_info[1], hw_info[2], hw_info[0]);
|
||||
/* Meaning of these info bytes are guessed. */
|
||||
info("firmware version:%d.%d hardware id:%d",
|
||||
hw_info[1], hw_info[2], hw_info[0]);
|
||||
|
||||
state->hw = hw_info[0];
|
||||
state->hw = hw_info[0];
|
||||
}
|
||||
|
||||
/* set current frondend ID for devices having two frondends */
|
||||
if (adap->fe_adap[0].fe)
|
||||
state->fe_id++;
|
||||
|
||||
switch (state->hw) {
|
||||
case ANYSEE_HW_507T: /* 2 */
|
||||
/* E30 */
|
||||
|
||||
/* attach demod */
|
||||
adap->fe = dvb_attach(mt352_attach, &anysee_mt352_config,
|
||||
&adap->dev->i2c_adap);
|
||||
if (adap->fe)
|
||||
if (state->fe_id)
|
||||
break;
|
||||
|
||||
/* attach demod */
|
||||
adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
|
||||
adap->fe_adap[0].fe = dvb_attach(mt352_attach, &anysee_mt352_config,
|
||||
&adap->dev->i2c_adap);
|
||||
if (adap->fe_adap[0].fe)
|
||||
break;
|
||||
|
||||
/* attach demod */
|
||||
adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
|
||||
&adap->dev->i2c_adap);
|
||||
|
||||
break;
|
||||
case ANYSEE_HW_507CD: /* 6 */
|
||||
/* E30 Plus */
|
||||
|
||||
if (state->fe_id)
|
||||
break;
|
||||
|
||||
/* enable DVB-T demod on IOD[0] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01);
|
||||
if (ret)
|
||||
@ -512,33 +633,39 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
goto error;
|
||||
|
||||
/* attach demod */
|
||||
adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
|
||||
&adap->dev->i2c_adap);
|
||||
adap->fe_adap[0].fe = dvb_attach(zl10353_attach,
|
||||
&anysee_zl10353_config, &adap->dev->i2c_adap);
|
||||
|
||||
break;
|
||||
case ANYSEE_HW_507DC: /* 10 */
|
||||
/* E30 C Plus */
|
||||
|
||||
if (state->fe_id)
|
||||
break;
|
||||
|
||||
/* enable DVB-C demod on IOD[0] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* attach demod */
|
||||
adap->fe = dvb_attach(tda10023_attach, &anysee_tda10023_config,
|
||||
&adap->dev->i2c_adap, 0x48);
|
||||
adap->fe_adap[0].fe = dvb_attach(tda10023_attach,
|
||||
&anysee_tda10023_config, &adap->dev->i2c_adap, 0x48);
|
||||
|
||||
break;
|
||||
case ANYSEE_HW_507SI: /* 11 */
|
||||
/* E30 S2 Plus */
|
||||
|
||||
if (state->fe_id)
|
||||
break;
|
||||
|
||||
/* enable DVB-S/S2 demod on IOD[0] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* attach demod */
|
||||
adap->fe = dvb_attach(cx24116_attach, &anysee_cx24116_config,
|
||||
adap->fe_adap[0].fe = dvb_attach(cx24116_attach, &anysee_cx24116_config,
|
||||
&adap->dev->i2c_adap);
|
||||
|
||||
break;
|
||||
@ -564,32 +691,7 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
if (dvb_usb_anysee_delsys) {
|
||||
/* disable DVB-C demod on IOD[5] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
|
||||
0x20);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* enable DVB-T demod on IOD[0] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0),
|
||||
0x01);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* attach demod */
|
||||
if (tmp == 0xc7) {
|
||||
/* TDA18212 config */
|
||||
adap->fe = dvb_attach(zl10353_attach,
|
||||
&anysee_zl10353_tda18212_config2,
|
||||
&adap->dev->i2c_adap);
|
||||
} else {
|
||||
/* PLL config */
|
||||
adap->fe = dvb_attach(zl10353_attach,
|
||||
&anysee_zl10353_config,
|
||||
&adap->dev->i2c_adap);
|
||||
}
|
||||
} else {
|
||||
if ((state->fe_id ^ dvb_usb_anysee_delsys) == 0) {
|
||||
/* disable DVB-T demod on IOD[0] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 0),
|
||||
0x01);
|
||||
@ -605,15 +707,44 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
/* attach demod */
|
||||
if (tmp == 0xc7) {
|
||||
/* TDA18212 config */
|
||||
adap->fe = dvb_attach(tda10023_attach,
|
||||
adap->fe_adap[state->fe_id].fe = dvb_attach(
|
||||
tda10023_attach,
|
||||
&anysee_tda10023_tda18212_config,
|
||||
&adap->dev->i2c_adap, 0x48);
|
||||
} else {
|
||||
/* PLL config */
|
||||
adap->fe = dvb_attach(tda10023_attach,
|
||||
adap->fe_adap[state->fe_id].fe = dvb_attach(
|
||||
tda10023_attach,
|
||||
&anysee_tda10023_config,
|
||||
&adap->dev->i2c_adap, 0x48);
|
||||
}
|
||||
} else {
|
||||
/* disable DVB-C demod on IOD[5] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
|
||||
0x20);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* enable DVB-T demod on IOD[0] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0),
|
||||
0x01);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* attach demod */
|
||||
if (tmp == 0xc7) {
|
||||
/* TDA18212 config */
|
||||
adap->fe_adap[state->fe_id].fe = dvb_attach(
|
||||
zl10353_attach,
|
||||
&anysee_zl10353_tda18212_config2,
|
||||
&adap->dev->i2c_adap);
|
||||
} else {
|
||||
/* PLL config */
|
||||
adap->fe_adap[state->fe_id].fe = dvb_attach(
|
||||
zl10353_attach,
|
||||
&anysee_zl10353_config,
|
||||
&adap->dev->i2c_adap);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
@ -627,30 +758,7 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
if (dvb_usb_anysee_delsys) {
|
||||
/* disable DVB-C demod on IOD[5] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
|
||||
0x20);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* enable DVB-T demod on IOD[6] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 6),
|
||||
0x40);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* enable IF route on IOE[0] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0),
|
||||
0x01);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* attach demod */
|
||||
adap->fe = dvb_attach(zl10353_attach,
|
||||
&anysee_zl10353_tda18212_config,
|
||||
&adap->dev->i2c_adap);
|
||||
} else {
|
||||
if ((state->fe_id ^ dvb_usb_anysee_delsys) == 0) {
|
||||
/* disable DVB-T demod on IOD[6] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 6),
|
||||
0x40);
|
||||
@ -663,16 +771,27 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* enable IF route on IOE[0] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0),
|
||||
0x01);
|
||||
/* attach demod */
|
||||
adap->fe_adap[state->fe_id].fe = dvb_attach(tda10023_attach,
|
||||
&anysee_tda10023_tda18212_config,
|
||||
&adap->dev->i2c_adap, 0x48);
|
||||
} else {
|
||||
/* disable DVB-C demod on IOD[5] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
|
||||
0x20);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* enable DVB-T demod on IOD[6] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 6),
|
||||
0x40);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* attach demod */
|
||||
adap->fe = dvb_attach(tda10023_attach,
|
||||
&anysee_tda10023_tda18212_config,
|
||||
&adap->dev->i2c_adap, 0x48);
|
||||
adap->fe_adap[state->fe_id].fe = dvb_attach(zl10353_attach,
|
||||
&anysee_zl10353_tda18212_config,
|
||||
&adap->dev->i2c_adap);
|
||||
}
|
||||
|
||||
break;
|
||||
@ -681,6 +800,9 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
/* E7 S2 */
|
||||
/* E7 PS2 */
|
||||
|
||||
if (state->fe_id)
|
||||
break;
|
||||
|
||||
/* enable transport stream on IOA[7] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (1 << 7), 0x80);
|
||||
if (ret)
|
||||
@ -692,13 +814,13 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
goto error;
|
||||
|
||||
/* attach demod */
|
||||
adap->fe = dvb_attach(stv0900_attach, &anysee_stv0900_config,
|
||||
adap->fe_adap[0].fe = dvb_attach(stv0900_attach, &anysee_stv0900_config,
|
||||
&adap->dev->i2c_adap, 0);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!adap->fe) {
|
||||
if (!adap->fe_adap[0].fe) {
|
||||
/* we have no frontend :-( */
|
||||
ret = -ENODEV;
|
||||
err("Unsupported Anysee version. " \
|
||||
@ -713,14 +835,14 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
struct anysee_state *state = adap->dev->priv;
|
||||
struct dvb_frontend *fe;
|
||||
int ret;
|
||||
deb_info("%s:\n", __func__);
|
||||
deb_info("%s: fe=%d\n", __func__, state->fe_id);
|
||||
|
||||
switch (state->hw) {
|
||||
case ANYSEE_HW_507T: /* 2 */
|
||||
/* E30 */
|
||||
|
||||
/* attach tuner */
|
||||
fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc2 >> 1),
|
||||
fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, (0xc2 >> 1),
|
||||
NULL, DVB_PLL_THOMSON_DTT7579);
|
||||
|
||||
break;
|
||||
@ -728,7 +850,7 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
/* E30 Plus */
|
||||
|
||||
/* attach tuner */
|
||||
fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc2 >> 1),
|
||||
fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, (0xc2 >> 1),
|
||||
&adap->dev->i2c_adap, DVB_PLL_THOMSON_DTT7579);
|
||||
|
||||
break;
|
||||
@ -736,7 +858,7 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
/* E30 C Plus */
|
||||
|
||||
/* attach tuner */
|
||||
fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc0 >> 1),
|
||||
fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, (0xc0 >> 1),
|
||||
&adap->dev->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A);
|
||||
|
||||
break;
|
||||
@ -744,28 +866,14 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
/* E30 S2 Plus */
|
||||
|
||||
/* attach LNB controller */
|
||||
fe = dvb_attach(isl6423_attach, adap->fe, &adap->dev->i2c_adap,
|
||||
&anysee_isl6423_config);
|
||||
fe = dvb_attach(isl6423_attach, adap->fe_adap[0].fe,
|
||||
&adap->dev->i2c_adap, &anysee_isl6423_config);
|
||||
|
||||
break;
|
||||
case ANYSEE_HW_507FA: /* 15 */
|
||||
/* E30 Combo Plus */
|
||||
/* E30 C Plus */
|
||||
|
||||
if (dvb_usb_anysee_delsys) {
|
||||
/* enable DVB-T tuner on IOE[0] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0),
|
||||
0x01);
|
||||
if (ret)
|
||||
goto error;
|
||||
} else {
|
||||
/* enable DVB-C tuner on IOE[0] */
|
||||
ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0),
|
||||
0x01);
|
||||
if (ret)
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Try first attach TDA18212 silicon tuner on IOE[4], if that
|
||||
* fails attach old simple PLL. */
|
||||
|
||||
@ -775,8 +883,8 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
goto error;
|
||||
|
||||
/* attach tuner */
|
||||
fe = dvb_attach(tda18212_attach, adap->fe, &adap->dev->i2c_adap,
|
||||
&anysee_tda18212_config);
|
||||
fe = dvb_attach(tda18212_attach, adap->fe_adap[state->fe_id].fe,
|
||||
&adap->dev->i2c_adap, &anysee_tda18212_config);
|
||||
if (fe)
|
||||
break;
|
||||
|
||||
@ -786,8 +894,9 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
goto error;
|
||||
|
||||
/* attach tuner */
|
||||
fe = dvb_attach(dvb_pll_attach, adap->fe, (0xc0 >> 1),
|
||||
&adap->dev->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A);
|
||||
fe = dvb_attach(dvb_pll_attach, adap->fe_adap[state->fe_id].fe,
|
||||
(0xc0 >> 1), &adap->dev->i2c_adap,
|
||||
DVB_PLL_SAMSUNG_DTOS403IH102A);
|
||||
|
||||
break;
|
||||
case ANYSEE_HW_508TC: /* 18 */
|
||||
@ -801,8 +910,8 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
goto error;
|
||||
|
||||
/* attach tuner */
|
||||
fe = dvb_attach(tda18212_attach, adap->fe, &adap->dev->i2c_adap,
|
||||
&anysee_tda18212_config);
|
||||
fe = dvb_attach(tda18212_attach, adap->fe_adap[state->fe_id].fe,
|
||||
&adap->dev->i2c_adap, &anysee_tda18212_config);
|
||||
|
||||
break;
|
||||
case ANYSEE_HW_508S2: /* 19 */
|
||||
@ -811,12 +920,12 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
/* E7 PS2 */
|
||||
|
||||
/* attach tuner */
|
||||
fe = dvb_attach(stv6110_attach, adap->fe,
|
||||
fe = dvb_attach(stv6110_attach, adap->fe_adap[0].fe,
|
||||
&anysee_stv6110_config, &adap->dev->i2c_adap);
|
||||
|
||||
if (fe) {
|
||||
/* attach LNB controller */
|
||||
fe = dvb_attach(isl6423_attach, adap->fe,
|
||||
fe = dvb_attach(isl6423_attach, adap->fe_adap[0].fe,
|
||||
&adap->dev->i2c_adap, &anysee_isl6423_config);
|
||||
}
|
||||
|
||||
@ -918,6 +1027,9 @@ static struct dvb_usb_device_properties anysee_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 2,
|
||||
.frontend_ctrl = anysee_frontend_ctrl,
|
||||
.fe = {{
|
||||
.streaming_ctrl = anysee_streaming_ctrl,
|
||||
.frontend_attach = anysee_frontend_attach,
|
||||
.tuner_attach = anysee_tuner_attach,
|
||||
@ -931,6 +1043,21 @@ static struct dvb_usb_device_properties anysee_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}, {
|
||||
.streaming_ctrl = anysee_streaming_ctrl,
|
||||
.frontend_attach = anysee_frontend_attach,
|
||||
.tuner_attach = anysee_tuner_attach,
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 8,
|
||||
.endpoint = 0x82,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = (16*512),
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -59,6 +59,7 @@ enum cmd {
|
||||
struct anysee_state {
|
||||
u8 hw; /* PCB ID */
|
||||
u8 seq;
|
||||
u8 fe_id:1; /* frondend ID */
|
||||
};
|
||||
|
||||
#define ANYSEE_HW_507T 2 /* E30 */
|
||||
|
@ -140,9 +140,9 @@ static struct zl10353_config au6610_zl10353_config = {
|
||||
|
||||
static int au6610_zl10353_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
adap->fe = dvb_attach(zl10353_attach, &au6610_zl10353_config,
|
||||
adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &au6610_zl10353_config,
|
||||
&adap->dev->i2c_adap);
|
||||
if (adap->fe == NULL)
|
||||
if (adap->fe_adap[0].fe == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
@ -155,7 +155,7 @@ static struct qt1010_config au6610_qt1010_config = {
|
||||
static int au6610_qt1010_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
return dvb_attach(qt1010_attach,
|
||||
adap->fe, &adap->dev->i2c_adap,
|
||||
adap->fe_adap[0].fe, &adap->dev->i2c_adap,
|
||||
&au6610_qt1010_config) == NULL ? -ENODEV : 0;
|
||||
}
|
||||
|
||||
@ -204,6 +204,8 @@ static struct dvb_usb_device_properties au6610_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.frontend_attach = au6610_zl10353_frontend_attach,
|
||||
.tuner_attach = au6610_qt1010_tuner_attach,
|
||||
|
||||
@ -219,6 +221,7 @@ static struct dvb_usb_device_properties au6610_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -40,7 +40,6 @@ static const struct stb0899_s1_reg az6027_stb0899_s1_init_1[] = {
|
||||
{ STB0899_DISRX_ST0 , 0x04 },
|
||||
{ STB0899_DISRX_ST1 , 0x00 },
|
||||
{ STB0899_DISPARITY , 0x00 },
|
||||
{ STB0899_DISFIFO , 0x00 },
|
||||
{ STB0899_DISSTATUS , 0x20 },
|
||||
{ STB0899_DISF22 , 0x99 },
|
||||
{ STB0899_DISF22RX , 0xa8 },
|
||||
@ -782,7 +781,6 @@ static int az6027_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
|
||||
{
|
||||
|
||||
u8 buf;
|
||||
int ret;
|
||||
struct dvb_usb_adapter *adap = fe->dvb->priv;
|
||||
|
||||
struct i2c_msg i2c_msg = {
|
||||
@ -800,17 +798,17 @@ static int az6027_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
|
||||
switch (voltage) {
|
||||
case SEC_VOLTAGE_13:
|
||||
buf = 1;
|
||||
ret = i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
|
||||
i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
|
||||
break;
|
||||
|
||||
case SEC_VOLTAGE_18:
|
||||
buf = 2;
|
||||
ret = i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
|
||||
i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
|
||||
break;
|
||||
|
||||
case SEC_VOLTAGE_OFF:
|
||||
buf = 0;
|
||||
ret = i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
|
||||
i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -910,16 +908,16 @@ static int az6027_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
az6027_frontend_reset(adap);
|
||||
|
||||
deb_info("adap = %p, dev = %p\n", adap, adap->dev);
|
||||
adap->fe = stb0899_attach(&az6027_stb0899_config, &adap->dev->i2c_adap);
|
||||
adap->fe_adap[0].fe = stb0899_attach(&az6027_stb0899_config, &adap->dev->i2c_adap);
|
||||
|
||||
if (adap->fe) {
|
||||
if (adap->fe_adap[0].fe) {
|
||||
deb_info("found STB0899 DVB-S/DVB-S2 frontend @0x%02x", az6027_stb0899_config.demod_address);
|
||||
if (stb6100_attach(adap->fe, &az6027_stb6100_config, &adap->dev->i2c_adap)) {
|
||||
if (stb6100_attach(adap->fe_adap[0].fe, &az6027_stb6100_config, &adap->dev->i2c_adap)) {
|
||||
deb_info("found STB6100 DVB-S/DVB-S2 frontend @0x%02x", az6027_stb6100_config.tuner_address);
|
||||
adap->fe->ops.set_voltage = az6027_set_voltage;
|
||||
adap->fe_adap[0].fe->ops.set_voltage = az6027_set_voltage;
|
||||
az6027_ci_init(adap);
|
||||
} else {
|
||||
adap->fe = NULL;
|
||||
adap->fe_adap[0].fe = NULL;
|
||||
}
|
||||
} else
|
||||
warn("no front-end attached\n");
|
||||
@ -954,7 +952,6 @@ static int az6027_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int n
|
||||
{
|
||||
struct dvb_usb_device *d = i2c_get_adapdata(adap);
|
||||
int i = 0, j = 0, len = 0;
|
||||
int ret;
|
||||
u16 index;
|
||||
u16 value;
|
||||
int length;
|
||||
@ -990,7 +987,7 @@ static int az6027_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int n
|
||||
index = (((msg[i].buf[0] << 8) & 0xff00) | (msg[i].buf[1] & 0x00ff));
|
||||
value = msg[i].addr + (msg[i].len << 8);
|
||||
length = msg[i + 1].len + 6;
|
||||
ret = az6027_usb_in_op(d, req, value, index, data, length);
|
||||
az6027_usb_in_op(d, req, value, index, data, length);
|
||||
len = msg[i + 1].len;
|
||||
for (j = 0; j < len; j++)
|
||||
msg[i + 1].buf[j] = data[j + 5];
|
||||
@ -1017,7 +1014,7 @@ static int az6027_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int n
|
||||
index = 0x0;
|
||||
value = msg[i].addr;
|
||||
length = msg[i].len + 6;
|
||||
ret = az6027_usb_in_op(d, req, value, index, data, length);
|
||||
az6027_usb_in_op(d, req, value, index, data, length);
|
||||
len = msg[i].len;
|
||||
for (j = 0; j < len; j++)
|
||||
msg[i].buf[j] = data[j + 5];
|
||||
@ -1106,6 +1103,8 @@ static struct dvb_usb_device_properties az6027_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.streaming_ctrl = az6027_streaming_ctrl,
|
||||
.frontend_attach = az6027_frontend_attach,
|
||||
|
||||
@ -1120,6 +1119,7 @@ static struct dvb_usb_device_properties az6027_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
}
|
||||
},
|
||||
/*
|
||||
|
@ -186,9 +186,9 @@ static struct zl10353_config ce6230_zl10353_config = {
|
||||
static int ce6230_zl10353_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
deb_info("%s:\n", __func__);
|
||||
adap->fe = dvb_attach(zl10353_attach, &ce6230_zl10353_config,
|
||||
adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &ce6230_zl10353_config,
|
||||
&adap->dev->i2c_adap);
|
||||
if (adap->fe == NULL)
|
||||
if (adap->fe_adap[0].fe == NULL)
|
||||
return -ENODEV;
|
||||
return 0;
|
||||
}
|
||||
@ -214,7 +214,7 @@ static int ce6230_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
int ret;
|
||||
deb_info("%s:\n", __func__);
|
||||
ret = dvb_attach(mxl5005s_attach, adap->fe, &adap->dev->i2c_adap,
|
||||
ret = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap,
|
||||
&ce6230_mxl5003s_config) == NULL ? -ENODEV : 0;
|
||||
return ret;
|
||||
}
|
||||
@ -273,6 +273,8 @@ static struct dvb_usb_device_properties ce6230_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.frontend_attach = ce6230_zl10353_frontend_attach,
|
||||
.tuner_attach = ce6230_mxl5003s_tuner_attach,
|
||||
.stream = {
|
||||
@ -285,6 +287,7 @@ static struct dvb_usb_device_properties ce6230_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -69,7 +69,7 @@ static int cinergyt2_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
char state[3];
|
||||
int ret;
|
||||
|
||||
adap->fe = cinergyt2_fe_attach(adap->dev);
|
||||
adap->fe_adap[0].fe = cinergyt2_fe_attach(adap->dev);
|
||||
|
||||
ret = dvb_usb_generic_rw(adap->dev, query, sizeof(query), state,
|
||||
sizeof(state), 0);
|
||||
@ -198,6 +198,8 @@ static struct dvb_usb_device_properties cinergyt2_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.streaming_ctrl = cinergyt2_streaming_ctrl,
|
||||
.frontend_attach = cinergyt2_frontend_attach,
|
||||
|
||||
@ -212,6 +214,7 @@ static struct dvb_usb_device_properties cinergyt2_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -347,7 +347,7 @@ static void cxusb_d680_dmb_drain_message(struct dvb_usb_device *d)
|
||||
|
||||
static void cxusb_d680_dmb_drain_video(struct dvb_usb_device *d)
|
||||
{
|
||||
struct usb_data_stream_properties *p = &d->props.adapter[0].stream;
|
||||
struct usb_data_stream_properties *p = &d->props.adapter[0].fe[0].stream;
|
||||
const int timeout = 100;
|
||||
const int junk_len = p->u.bulk.buffersize;
|
||||
u8 *junk;
|
||||
@ -725,7 +725,7 @@ static struct max2165_config mygica_d689_max2165_cfg = {
|
||||
/* Callbacks for DVB USB */
|
||||
static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
dvb_attach(simple_tuner_attach, adap->fe,
|
||||
dvb_attach(simple_tuner_attach, adap->fe_adap[0].fe,
|
||||
&adap->dev->i2c_adap, 0x61,
|
||||
TUNER_PHILIPS_FMD1216ME_MK3);
|
||||
return 0;
|
||||
@ -733,27 +733,27 @@ static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
|
||||
static int cxusb_dee1601_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
dvb_attach(dvb_pll_attach, adap->fe, 0x61,
|
||||
dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x61,
|
||||
NULL, DVB_PLL_THOMSON_DTT7579);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cxusb_lgz201_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
dvb_attach(dvb_pll_attach, adap->fe, 0x61, NULL, DVB_PLL_LG_Z201);
|
||||
dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x61, NULL, DVB_PLL_LG_Z201);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cxusb_dtt7579_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
dvb_attach(dvb_pll_attach, adap->fe, 0x60,
|
||||
dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60,
|
||||
NULL, DVB_PLL_THOMSON_DTT7579);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
dvb_attach(simple_tuner_attach, adap->fe,
|
||||
dvb_attach(simple_tuner_attach, adap->fe_adap[0].fe,
|
||||
&adap->dev->i2c_adap, 0x61, TUNER_LG_TDVS_H06XF);
|
||||
return 0;
|
||||
}
|
||||
@ -795,9 +795,9 @@ static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
};
|
||||
|
||||
/* FIXME: generalize & move to common area */
|
||||
adap->fe->callback = dvico_bluebird_xc2028_callback;
|
||||
adap->fe_adap[0].fe->callback = dvico_bluebird_xc2028_callback;
|
||||
|
||||
fe = dvb_attach(xc2028_attach, adap->fe, &cfg);
|
||||
fe = dvb_attach(xc2028_attach, adap->fe_adap[0].fe, &cfg);
|
||||
if (fe == NULL || fe->ops.tuner_ops.set_config == NULL)
|
||||
return -EIO;
|
||||
|
||||
@ -808,7 +808,7 @@ static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
|
||||
static int cxusb_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
dvb_attach(mxl5005s_attach, adap->fe,
|
||||
dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe,
|
||||
&adap->dev->i2c_adap, &aver_a868r_tuner);
|
||||
return 0;
|
||||
}
|
||||
@ -816,7 +816,7 @@ static int cxusb_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
static int cxusb_d680_dmb_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
struct dvb_frontend *fe;
|
||||
fe = dvb_attach(mxl5005s_attach, adap->fe,
|
||||
fe = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe,
|
||||
&adap->dev->i2c_adap, &d680_dmb_tuner);
|
||||
return (fe == NULL) ? -EIO : 0;
|
||||
}
|
||||
@ -824,7 +824,7 @@ static int cxusb_d680_dmb_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
static int cxusb_mygica_d689_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
struct dvb_frontend *fe;
|
||||
fe = dvb_attach(max2165_attach, adap->fe,
|
||||
fe = dvb_attach(max2165_attach, adap->fe_adap[0].fe,
|
||||
&adap->dev->i2c_adap, &mygica_d689_max2165_cfg);
|
||||
return (fe == NULL) ? -EIO : 0;
|
||||
}
|
||||
@ -837,8 +837,9 @@ static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
|
||||
cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, &b, 1);
|
||||
|
||||
if ((adap->fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config,
|
||||
&adap->dev->i2c_adap)) != NULL)
|
||||
adap->fe_adap[0].fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config,
|
||||
&adap->dev->i2c_adap);
|
||||
if ((adap->fe_adap[0].fe) != NULL)
|
||||
return 0;
|
||||
|
||||
return -EIO;
|
||||
@ -851,8 +852,10 @@ static int cxusb_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
|
||||
cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
|
||||
|
||||
if ((adap->fe = dvb_attach(lgdt330x_attach, &cxusb_lgdt3303_config,
|
||||
&adap->dev->i2c_adap)) != NULL)
|
||||
adap->fe_adap[0].fe = dvb_attach(lgdt330x_attach,
|
||||
&cxusb_lgdt3303_config,
|
||||
&adap->dev->i2c_adap);
|
||||
if ((adap->fe_adap[0].fe) != NULL)
|
||||
return 0;
|
||||
|
||||
return -EIO;
|
||||
@ -860,9 +863,9 @@ static int cxusb_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
|
||||
static int cxusb_aver_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
adap->fe = dvb_attach(lgdt330x_attach, &cxusb_aver_lgdt3303_config,
|
||||
adap->fe_adap[0].fe = dvb_attach(lgdt330x_attach, &cxusb_aver_lgdt3303_config,
|
||||
&adap->dev->i2c_adap);
|
||||
if (adap->fe != NULL)
|
||||
if (adap->fe_adap[0].fe != NULL)
|
||||
return 0;
|
||||
|
||||
return -EIO;
|
||||
@ -876,8 +879,9 @@ static int cxusb_mt352_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
|
||||
cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
|
||||
|
||||
if ((adap->fe = dvb_attach(mt352_attach, &cxusb_mt352_config,
|
||||
&adap->dev->i2c_adap)) != NULL)
|
||||
adap->fe_adap[0].fe = dvb_attach(mt352_attach, &cxusb_mt352_config,
|
||||
&adap->dev->i2c_adap);
|
||||
if ((adap->fe_adap[0].fe) != NULL)
|
||||
return 0;
|
||||
|
||||
return -EIO;
|
||||
@ -890,11 +894,15 @@ static int cxusb_dee1601_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
|
||||
cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
|
||||
|
||||
if (((adap->fe = dvb_attach(mt352_attach, &cxusb_dee1601_config,
|
||||
&adap->dev->i2c_adap)) != NULL) ||
|
||||
((adap->fe = dvb_attach(zl10353_attach,
|
||||
&cxusb_zl10353_dee1601_config,
|
||||
&adap->dev->i2c_adap)) != NULL))
|
||||
adap->fe_adap[0].fe = dvb_attach(mt352_attach, &cxusb_dee1601_config,
|
||||
&adap->dev->i2c_adap);
|
||||
if ((adap->fe_adap[0].fe) != NULL)
|
||||
return 0;
|
||||
|
||||
adap->fe_adap[0].fe = dvb_attach(zl10353_attach,
|
||||
&cxusb_zl10353_dee1601_config,
|
||||
&adap->dev->i2c_adap);
|
||||
if ((adap->fe_adap[0].fe) != NULL)
|
||||
return 0;
|
||||
|
||||
return -EIO;
|
||||
@ -917,9 +925,11 @@ static int cxusb_dualdig4_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
cxusb_bluebird_gpio_pulse(adap->dev, 0x01, 1);
|
||||
cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1);
|
||||
|
||||
if ((adap->fe = dvb_attach(zl10353_attach,
|
||||
&cxusb_zl10353_xc3028_config_no_i2c_gate,
|
||||
&adap->dev->i2c_adap)) == NULL)
|
||||
adap->fe_adap[0].fe =
|
||||
dvb_attach(zl10353_attach,
|
||||
&cxusb_zl10353_xc3028_config_no_i2c_gate,
|
||||
&adap->dev->i2c_adap);
|
||||
if ((adap->fe_adap[0].fe) == NULL)
|
||||
return -EIO;
|
||||
|
||||
/* try to determine if there is no IR decoder on the I2C bus */
|
||||
@ -1031,9 +1041,9 @@ static int cxusb_dualdig4_rev2_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
|
||||
adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
|
||||
&cxusb_dualdig4_rev2_config);
|
||||
if (adap->fe == NULL)
|
||||
if (adap->fe_adap[0].fe == NULL)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
@ -1084,15 +1094,15 @@ static int cxusb_dualdig4_rev2_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
struct dib0700_adapter_state *st = adap->priv;
|
||||
struct i2c_adapter *tun_i2c =
|
||||
dib7000p_get_i2c_master(adap->fe,
|
||||
dib7000p_get_i2c_master(adap->fe_adap[0].fe,
|
||||
DIBX000_I2C_INTERFACE_TUNER, 1);
|
||||
|
||||
if (dvb_attach(dib0070_attach, adap->fe, tun_i2c,
|
||||
if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c,
|
||||
&dib7070p_dib0070_config) == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
st->set_param_save = adap->fe->ops.tuner_ops.set_params;
|
||||
adap->fe->ops.tuner_ops.set_params = dib7070_set_param_override;
|
||||
st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
|
||||
adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7070_set_param_override;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1108,14 +1118,16 @@ static int cxusb_nano2_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
cxusb_bluebird_gpio_pulse(adap->dev, 0x01, 1);
|
||||
cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1);
|
||||
|
||||
if ((adap->fe = dvb_attach(zl10353_attach,
|
||||
&cxusb_zl10353_xc3028_config,
|
||||
&adap->dev->i2c_adap)) != NULL)
|
||||
adap->fe_adap[0].fe = dvb_attach(zl10353_attach,
|
||||
&cxusb_zl10353_xc3028_config,
|
||||
&adap->dev->i2c_adap);
|
||||
if ((adap->fe_adap[0].fe) != NULL)
|
||||
return 0;
|
||||
|
||||
if ((adap->fe = dvb_attach(mt352_attach,
|
||||
&cxusb_mt352_xc3028_config,
|
||||
&adap->dev->i2c_adap)) != NULL)
|
||||
adap->fe_adap[0].fe = dvb_attach(mt352_attach,
|
||||
&cxusb_mt352_xc3028_config,
|
||||
&adap->dev->i2c_adap);
|
||||
if ((adap->fe_adap[0].fe) != NULL)
|
||||
return 0;
|
||||
|
||||
return -EIO;
|
||||
@ -1150,7 +1162,7 @@ static int cxusb_d680_dmb_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
usb_clear_halt(d->udev,
|
||||
usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
|
||||
usb_clear_halt(d->udev,
|
||||
usb_rcvbulkpipe(d->udev, d->props.adapter[0].stream.endpoint));
|
||||
usb_rcvbulkpipe(d->udev, d->props.adapter[0].fe[0].stream.endpoint));
|
||||
|
||||
/* Drain USB pipes to avoid hang after reboot */
|
||||
for (n = 0; n < 5; n++) {
|
||||
@ -1172,8 +1184,8 @@ static int cxusb_d680_dmb_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
msleep(100);
|
||||
|
||||
/* Attach frontend */
|
||||
adap->fe = dvb_attach(lgs8gxx_attach, &d680_lgs8gl5_cfg, &d->i2c_adap);
|
||||
if (adap->fe == NULL)
|
||||
adap->fe_adap[0].fe = dvb_attach(lgs8gxx_attach, &d680_lgs8gl5_cfg, &d->i2c_adap);
|
||||
if (adap->fe_adap[0].fe == NULL)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
@ -1207,7 +1219,7 @@ static int cxusb_mygica_d689_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
usb_clear_halt(d->udev,
|
||||
usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
|
||||
usb_clear_halt(d->udev,
|
||||
usb_rcvbulkpipe(d->udev, d->props.adapter[0].stream.endpoint));
|
||||
usb_rcvbulkpipe(d->udev, d->props.adapter[0].fe[0].stream.endpoint));
|
||||
|
||||
|
||||
/* Reset the tuner */
|
||||
@ -1223,9 +1235,9 @@ static int cxusb_mygica_d689_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
msleep(100);
|
||||
|
||||
/* Attach frontend */
|
||||
adap->fe = dvb_attach(atbm8830_attach, &mygica_d689_atbm8830_cfg,
|
||||
adap->fe_adap[0].fe = dvb_attach(atbm8830_attach, &mygica_d689_atbm8830_cfg,
|
||||
&d->i2c_adap);
|
||||
if (adap->fe == NULL)
|
||||
if (adap->fe_adap[0].fe == NULL)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
@ -1383,6 +1395,8 @@ static struct dvb_usb_device_properties cxusb_medion_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.streaming_ctrl = cxusb_streaming_ctrl,
|
||||
.frontend_attach = cxusb_cx22702_frontend_attach,
|
||||
.tuner_attach = cxusb_fmd1216me_tuner_attach,
|
||||
@ -1397,7 +1411,7 @@ static struct dvb_usb_device_properties cxusb_medion_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
}},
|
||||
},
|
||||
},
|
||||
.power_ctrl = cxusb_power_ctrl,
|
||||
@ -1429,6 +1443,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.streaming_ctrl = cxusb_streaming_ctrl,
|
||||
.frontend_attach = cxusb_lgdt3303_frontend_attach,
|
||||
.tuner_attach = cxusb_lgh064f_tuner_attach,
|
||||
@ -1444,6 +1460,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
|
||||
@ -1483,6 +1500,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.streaming_ctrl = cxusb_streaming_ctrl,
|
||||
.frontend_attach = cxusb_dee1601_frontend_attach,
|
||||
.tuner_attach = cxusb_dee1601_tuner_attach,
|
||||
@ -1497,6 +1516,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
|
||||
@ -1544,6 +1564,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties = {
|
||||
.num_adapters = 2,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.streaming_ctrl = cxusb_streaming_ctrl,
|
||||
.frontend_attach = cxusb_mt352_frontend_attach,
|
||||
.tuner_attach = cxusb_lgz201_tuner_attach,
|
||||
@ -1559,6 +1581,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
.power_ctrl = cxusb_bluebird_power_ctrl,
|
||||
@ -1596,6 +1619,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.streaming_ctrl = cxusb_streaming_ctrl,
|
||||
.frontend_attach = cxusb_mt352_frontend_attach,
|
||||
.tuner_attach = cxusb_dtt7579_tuner_attach,
|
||||
@ -1611,6 +1636,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
.power_ctrl = cxusb_bluebird_power_ctrl,
|
||||
@ -1645,6 +1671,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.streaming_ctrl = cxusb_streaming_ctrl,
|
||||
.frontend_attach = cxusb_dualdig4_frontend_attach,
|
||||
.tuner_attach = cxusb_dvico_xc3028_tuner_attach,
|
||||
@ -1659,6 +1687,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
|
||||
@ -1695,6 +1724,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.streaming_ctrl = cxusb_streaming_ctrl,
|
||||
.frontend_attach = cxusb_nano2_frontend_attach,
|
||||
.tuner_attach = cxusb_dvico_xc3028_tuner_attach,
|
||||
@ -1709,6 +1740,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
|
||||
@ -1747,6 +1779,8 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_prope
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.streaming_ctrl = cxusb_streaming_ctrl,
|
||||
.frontend_attach = cxusb_nano2_frontend_attach,
|
||||
.tuner_attach = cxusb_dvico_xc3028_tuner_attach,
|
||||
@ -1761,6 +1795,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_prope
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
|
||||
@ -1796,6 +1831,8 @@ static struct dvb_usb_device_properties cxusb_aver_a868r_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.streaming_ctrl = cxusb_aver_streaming_ctrl,
|
||||
.frontend_attach = cxusb_aver_lgdt3303_frontend_attach,
|
||||
.tuner_attach = cxusb_mxl5003s_tuner_attach,
|
||||
@ -1810,7 +1847,7 @@ static struct dvb_usb_device_properties cxusb_aver_a868r_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
}},
|
||||
},
|
||||
},
|
||||
.power_ctrl = cxusb_aver_power_ctrl,
|
||||
@ -1839,10 +1876,12 @@ struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.size_of_priv = sizeof(struct dib0700_adapter_state),
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.streaming_ctrl = cxusb_streaming_ctrl,
|
||||
.frontend_attach = cxusb_dualdig4_rev2_frontend_attach,
|
||||
.tuner_attach = cxusb_dualdig4_rev2_tuner_attach,
|
||||
.size_of_priv = sizeof(struct dib0700_adapter_state),
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
@ -1854,6 +1893,7 @@ struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
|
||||
@ -1889,6 +1929,8 @@ static struct dvb_usb_device_properties cxusb_d680_dmb_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.streaming_ctrl = cxusb_d680_dmb_streaming_ctrl,
|
||||
.frontend_attach = cxusb_d680_dmb_frontend_attach,
|
||||
.tuner_attach = cxusb_d680_dmb_tuner_attach,
|
||||
@ -1904,6 +1946,7 @@ static struct dvb_usb_device_properties cxusb_d680_dmb_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
|
||||
@ -1940,6 +1983,8 @@ static struct dvb_usb_device_properties cxusb_mygica_d689_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.streaming_ctrl = cxusb_d680_dmb_streaming_ctrl,
|
||||
.frontend_attach = cxusb_mygica_d689_frontend_attach,
|
||||
.tuner_attach = cxusb_mygica_d689_tuner_attach,
|
||||
@ -1955,6 +2000,7 @@ static struct dvb_usb_device_properties cxusb_mygica_d689_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
|
||||
|
@ -30,6 +30,11 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion,
|
||||
struct dib0700_state *st = d->priv;
|
||||
int ret;
|
||||
|
||||
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
|
||||
err("could not acquire lock");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
|
||||
REQUEST_GET_VERSION,
|
||||
USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
|
||||
@ -46,6 +51,7 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion,
|
||||
if (fwtype != NULL)
|
||||
*fwtype = (st->buf[12] << 24) | (st->buf[13] << 16) |
|
||||
(st->buf[14] << 8) | st->buf[15];
|
||||
mutex_unlock(&d->usb_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -108,7 +114,12 @@ int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen
|
||||
int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val)
|
||||
{
|
||||
struct dib0700_state *st = d->priv;
|
||||
s16 ret;
|
||||
int ret;
|
||||
|
||||
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
|
||||
err("could not acquire lock");
|
||||
return 0;
|
||||
}
|
||||
|
||||
st->buf[0] = REQUEST_SET_GPIO;
|
||||
st->buf[1] = gpio;
|
||||
@ -116,6 +127,7 @@ int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_
|
||||
|
||||
ret = dib0700_ctrl_wr(d, st->buf, 3);
|
||||
|
||||
mutex_unlock(&d->usb_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -125,6 +137,11 @@ static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets)
|
||||
int ret;
|
||||
|
||||
if (st->fw_version >= 0x10201) {
|
||||
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
|
||||
err("could not acquire lock");
|
||||
return 0;
|
||||
}
|
||||
|
||||
st->buf[0] = REQUEST_SET_USB_XFER_LEN;
|
||||
st->buf[1] = (nb_ts_packets >> 8) & 0xff;
|
||||
st->buf[2] = nb_ts_packets & 0xff;
|
||||
@ -132,6 +149,7 @@ static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets)
|
||||
deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets);
|
||||
|
||||
ret = dib0700_ctrl_wr(d, st->buf, 3);
|
||||
mutex_unlock(&d->usb_mutex);
|
||||
} else {
|
||||
deb_info("this firmware does not allow to change the USB xfer len\n");
|
||||
ret = -EIO;
|
||||
@ -208,6 +226,10 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
|
||||
|
||||
} else {
|
||||
/* Write request */
|
||||
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
|
||||
err("could not acquire lock");
|
||||
return 0;
|
||||
}
|
||||
st->buf[0] = REQUEST_NEW_I2C_WRITE;
|
||||
st->buf[1] = msg[i].addr << 1;
|
||||
st->buf[2] = (en_start << 7) | (en_stop << 6) |
|
||||
@ -227,6 +249,7 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
|
||||
USB_TYPE_VENDOR | USB_DIR_OUT,
|
||||
0, 0, st->buf, msg[i].len + 4,
|
||||
USB_CTRL_GET_TIMEOUT);
|
||||
mutex_unlock(&d->usb_mutex);
|
||||
if (result < 0) {
|
||||
deb_info("i2c write error (status = %d)\n", result);
|
||||
break;
|
||||
@ -249,6 +272,10 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,
|
||||
|
||||
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
|
||||
return -EAGAIN;
|
||||
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
|
||||
err("could not acquire lock");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
/* fill in the address */
|
||||
@ -279,6 +306,7 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&d->usb_mutex);
|
||||
mutex_unlock(&d->i2c_mutex);
|
||||
|
||||
return i;
|
||||
@ -337,7 +365,12 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll,
|
||||
u16 pll_loopdiv, u16 free_div, u16 dsuScaler)
|
||||
{
|
||||
struct dib0700_state *st = d->priv;
|
||||
s16 ret;
|
||||
int ret;
|
||||
|
||||
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
|
||||
err("could not acquire lock");
|
||||
return 0;
|
||||
}
|
||||
|
||||
st->buf[0] = REQUEST_SET_CLOCK;
|
||||
st->buf[1] = (en_pll << 7) | (pll_src << 6) |
|
||||
@ -352,6 +385,7 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll,
|
||||
st->buf[9] = dsuScaler & 0xff; /* LSB */
|
||||
|
||||
ret = dib0700_ctrl_wr(d, st->buf, 10);
|
||||
mutex_unlock(&d->usb_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -360,10 +394,16 @@ int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz)
|
||||
{
|
||||
struct dib0700_state *st = d->priv;
|
||||
u16 divider;
|
||||
int ret;
|
||||
|
||||
if (scl_kHz == 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
|
||||
err("could not acquire lock");
|
||||
return 0;
|
||||
}
|
||||
|
||||
st->buf[0] = REQUEST_SET_I2C_PARAM;
|
||||
divider = (u16) (30000 / scl_kHz);
|
||||
st->buf[1] = 0;
|
||||
@ -379,7 +419,11 @@ int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz)
|
||||
deb_info("setting I2C speed: %04x %04x %04x (%d kHz).",
|
||||
(st->buf[2] << 8) | (st->buf[3]), (st->buf[4] << 8) |
|
||||
st->buf[5], (st->buf[6] << 8) | st->buf[7], scl_kHz);
|
||||
return dib0700_ctrl_wr(d, st->buf, 8);
|
||||
|
||||
ret = dib0700_ctrl_wr(d, st->buf, 8);
|
||||
mutex_unlock(&d->usb_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@ -484,13 +528,13 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw
|
||||
for (adap_num = 0; adap_num < dib0700_devices[i].num_adapters;
|
||||
adap_num++) {
|
||||
if (fw_version >= 0x10201) {
|
||||
dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = 188*nb_packet_buffer_size;
|
||||
dib0700_devices[i].adapter[adap_num].fe[0].stream.u.bulk.buffersize = 188*nb_packet_buffer_size;
|
||||
} else {
|
||||
/* for fw version older than 1.20.1,
|
||||
* the buffersize has to be n times 512 */
|
||||
dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = ((188*nb_packet_buffer_size+188/2)/512)*512;
|
||||
if (dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize < 512)
|
||||
dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = 512;
|
||||
dib0700_devices[i].adapter[adap_num].fe[0].stream.u.bulk.buffersize = ((188*nb_packet_buffer_size+188/2)/512)*512;
|
||||
if (dib0700_devices[i].adapter[adap_num].fe[0].stream.u.bulk.buffersize < 512)
|
||||
dib0700_devices[i].adapter[adap_num].fe[0].stream.u.bulk.buffersize = 512;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -515,6 +559,11 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
||||
}
|
||||
}
|
||||
|
||||
if (mutex_lock_interruptible(&adap->dev->usb_mutex) < 0) {
|
||||
err("could not acquire lock");
|
||||
return 0;
|
||||
}
|
||||
|
||||
st->buf[0] = REQUEST_ENABLE_VIDEO;
|
||||
/* this bit gives a kind of command,
|
||||
* rather than enabling something or not */
|
||||
@ -530,25 +579,28 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
||||
deb_info("modifying (%d) streaming state for %d\n", onoff, adap->id);
|
||||
|
||||
st->channel_state &= ~0x3;
|
||||
if ((adap->stream.props.endpoint != 2)
|
||||
&& (adap->stream.props.endpoint != 3)) {
|
||||
deb_info("the endpoint number (%i) is not correct, use the adapter id instead", adap->stream.props.endpoint);
|
||||
if ((adap->fe_adap[0].stream.props.endpoint != 2)
|
||||
&& (adap->fe_adap[0].stream.props.endpoint != 3)) {
|
||||
deb_info("the endpoint number (%i) is not correct, use the adapter id instead", adap->fe_adap[0].stream.props.endpoint);
|
||||
if (onoff)
|
||||
st->channel_state |= 1 << (adap->id);
|
||||
else
|
||||
st->channel_state |= 1 << ~(adap->id);
|
||||
} else {
|
||||
if (onoff)
|
||||
st->channel_state |= 1 << (adap->stream.props.endpoint-2);
|
||||
st->channel_state |= 1 << (adap->fe_adap[0].stream.props.endpoint-2);
|
||||
else
|
||||
st->channel_state |= 1 << (3-adap->stream.props.endpoint);
|
||||
st->channel_state |= 1 << (3-adap->fe_adap[0].stream.props.endpoint);
|
||||
}
|
||||
|
||||
st->buf[2] |= st->channel_state;
|
||||
|
||||
deb_info("data for streaming: %x %x\n", st->buf[1], st->buf[2]);
|
||||
|
||||
return dib0700_ctrl_wr(adap->dev, st->buf, 4);
|
||||
ret = dib0700_ctrl_wr(adap->dev, st->buf, 4);
|
||||
mutex_unlock(&adap->dev->usb_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
|
||||
@ -557,6 +609,11 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
|
||||
struct dib0700_state *st = d->priv;
|
||||
int new_proto, ret;
|
||||
|
||||
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
|
||||
err("could not acquire lock");
|
||||
return 0;
|
||||
}
|
||||
|
||||
st->buf[0] = REQUEST_SET_RC;
|
||||
st->buf[1] = 0;
|
||||
st->buf[2] = 0;
|
||||
@ -567,23 +624,29 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
|
||||
else if (rc_type == RC_TYPE_NEC)
|
||||
new_proto = 0;
|
||||
else if (rc_type == RC_TYPE_RC6) {
|
||||
if (st->fw_version < 0x10200)
|
||||
return -EINVAL;
|
||||
if (st->fw_version < 0x10200) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
new_proto = 2;
|
||||
} else
|
||||
return -EINVAL;
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
st->buf[1] = new_proto;
|
||||
|
||||
ret = dib0700_ctrl_wr(d, st->buf, 3);
|
||||
if (ret < 0) {
|
||||
err("ir protocol setup failed");
|
||||
return ret;
|
||||
goto out;
|
||||
}
|
||||
|
||||
d->props.rc.core.protocol = rc_type;
|
||||
|
||||
out:
|
||||
mutex_unlock(&d->usb_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -23,7 +23,7 @@ int dibusb_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
||||
if (adap->priv != NULL) {
|
||||
struct dibusb_state *st = adap->priv;
|
||||
if (st->ops.fifo_ctrl != NULL)
|
||||
if (st->ops.fifo_ctrl(adap->fe,onoff)) {
|
||||
if (st->ops.fifo_ctrl(adap->fe_adap[0].fe, onoff)) {
|
||||
err("error while controlling the fifo of the demod.");
|
||||
return -ENODEV;
|
||||
}
|
||||
@ -37,7 +37,8 @@ int dibusb_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onof
|
||||
if (adap->priv != NULL) {
|
||||
struct dibusb_state *st = adap->priv;
|
||||
if (st->ops.pid_ctrl != NULL)
|
||||
st->ops.pid_ctrl(adap->fe,index,pid,onoff);
|
||||
st->ops.pid_ctrl(adap->fe_adap[0].fe,
|
||||
index, pid, onoff);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -48,7 +49,7 @@ int dibusb_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
||||
if (adap->priv != NULL) {
|
||||
struct dibusb_state *st = adap->priv;
|
||||
if (st->ops.pid_parse != NULL)
|
||||
if (st->ops.pid_parse(adap->fe,onoff) < 0)
|
||||
if (st->ops.pid_parse(adap->fe_adap[0].fe, onoff) < 0)
|
||||
err("could not handle pid_parser");
|
||||
}
|
||||
return 0;
|
||||
@ -254,8 +255,16 @@ int dibusb_dib3000mc_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
msleep(1000);
|
||||
}
|
||||
|
||||
if ((adap->fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap, DEFAULT_DIB3000P_I2C_ADDRESS, &mod3000p_dib3000p_config)) != NULL ||
|
||||
(adap->fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap, DEFAULT_DIB3000MC_I2C_ADDRESS, &mod3000p_dib3000p_config)) != NULL) {
|
||||
adap->fe_adap[0].fe = dvb_attach(dib3000mc_attach,
|
||||
&adap->dev->i2c_adap,
|
||||
DEFAULT_DIB3000P_I2C_ADDRESS,
|
||||
&mod3000p_dib3000p_config);
|
||||
if ((adap->fe_adap[0].fe) == NULL)
|
||||
adap->fe_adap[0].fe = dvb_attach(dib3000mc_attach,
|
||||
&adap->dev->i2c_adap,
|
||||
DEFAULT_DIB3000MC_I2C_ADDRESS,
|
||||
&mod3000p_dib3000p_config);
|
||||
if ((adap->fe_adap[0].fe) != NULL) {
|
||||
if (adap->priv != NULL) {
|
||||
struct dibusb_state *st = adap->priv;
|
||||
st->ops.pid_parse = dib3000mc_pid_parse;
|
||||
@ -309,15 +318,15 @@ int dibusb_dib3000mc_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
}
|
||||
}
|
||||
|
||||
tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe, 1);
|
||||
if (dvb_attach(mt2060_attach, adap->fe, tun_i2c, &stk3000p_mt2060_config, if1) == NULL) {
|
||||
tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe_adap[0].fe, 1);
|
||||
if (dvb_attach(mt2060_attach, adap->fe_adap[0].fe, tun_i2c, &stk3000p_mt2060_config, if1) == NULL) {
|
||||
/* not found - use panasonic pll parameters */
|
||||
if (dvb_attach(dvb_pll_attach, adap->fe, 0x60, tun_i2c, DVB_PLL_ENV57H1XD5) == NULL)
|
||||
if (dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60, tun_i2c, DVB_PLL_ENV57H1XD5) == NULL)
|
||||
return -ENOMEM;
|
||||
} else {
|
||||
st->mt2060_present = 1;
|
||||
/* set the correct parameters for the dib3000p */
|
||||
dib3000mc_set_config(adap->fe, &stk3000p_dib3000p_config);
|
||||
dib3000mc_set_config(adap->fe_adap[0].fe, &stk3000p_dib3000p_config);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -31,11 +31,12 @@ static int dibusb_dib3000mb_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
|
||||
demod_cfg.demod_address = 0x8;
|
||||
|
||||
if ((adap->fe = dvb_attach(dib3000mb_attach, &demod_cfg,
|
||||
&adap->dev->i2c_adap, &st->ops)) == NULL)
|
||||
adap->fe_adap[0].fe = dvb_attach(dib3000mb_attach, &demod_cfg,
|
||||
&adap->dev->i2c_adap, &st->ops);
|
||||
if ((adap->fe_adap[0].fe) == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
adap->fe->ops.i2c_gate_ctrl = dib3000mb_i2c_gate_ctrl;
|
||||
adap->fe_adap[0].fe->ops.i2c_gate_ctrl = dib3000mb_i2c_gate_ctrl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -46,7 +47,7 @@ static int dibusb_thomson_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
|
||||
st->tuner_addr = 0x61;
|
||||
|
||||
dvb_attach(dvb_pll_attach, adap->fe, 0x61, &adap->dev->i2c_adap,
|
||||
dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x61, &adap->dev->i2c_adap,
|
||||
DVB_PLL_TUA6010XS);
|
||||
return 0;
|
||||
}
|
||||
@ -57,7 +58,7 @@ static int dibusb_panasonic_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
|
||||
st->tuner_addr = 0x60;
|
||||
|
||||
dvb_attach(dvb_pll_attach, adap->fe, 0x60, &adap->dev->i2c_adap,
|
||||
dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60, &adap->dev->i2c_adap,
|
||||
DVB_PLL_TDA665X);
|
||||
return 0;
|
||||
}
|
||||
@ -78,16 +79,16 @@ static int dibusb_tuner_probe_and_attach(struct dvb_usb_adapter *adap)
|
||||
/* the Panasonic sits on I2C addrass 0x60, the Thomson on 0x61 */
|
||||
msg[0].addr = msg[1].addr = st->tuner_addr = 0x60;
|
||||
|
||||
if (adap->fe->ops.i2c_gate_ctrl)
|
||||
adap->fe->ops.i2c_gate_ctrl(adap->fe,1);
|
||||
if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl)
|
||||
adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 1);
|
||||
|
||||
if (i2c_transfer(&adap->dev->i2c_adap, msg, 2) != 2) {
|
||||
err("tuner i2c write failed.");
|
||||
ret = -EREMOTEIO;
|
||||
}
|
||||
|
||||
if (adap->fe->ops.i2c_gate_ctrl)
|
||||
adap->fe->ops.i2c_gate_ctrl(adap->fe,0);
|
||||
if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl)
|
||||
adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 0);
|
||||
|
||||
if (b2[0] == 0xfe) {
|
||||
info("This device has the Thomson Cable onboard. Which is default.");
|
||||
@ -185,6 +186,8 @@ static struct dvb_usb_device_properties dibusb1_1_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
.pid_filter_count = 16,
|
||||
|
||||
@ -205,6 +208,7 @@ static struct dvb_usb_device_properties dibusb1_1_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
.size_of_priv = sizeof(struct dibusb_state),
|
||||
}
|
||||
},
|
||||
@ -272,6 +276,8 @@ static struct dvb_usb_device_properties dibusb1_1_an2235_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.caps = DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_ADAP_HAS_PID_FILTER,
|
||||
.pid_filter_count = 16,
|
||||
|
||||
@ -292,6 +298,7 @@ static struct dvb_usb_device_properties dibusb1_1_an2235_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
.size_of_priv = sizeof(struct dibusb_state),
|
||||
},
|
||||
},
|
||||
@ -338,6 +345,8 @@ static struct dvb_usb_device_properties dibusb2_0b_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
.pid_filter_count = 16,
|
||||
|
||||
@ -358,6 +367,7 @@ static struct dvb_usb_device_properties dibusb2_0b_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
.size_of_priv = sizeof(struct dibusb_state),
|
||||
}
|
||||
},
|
||||
@ -398,6 +408,8 @@ static struct dvb_usb_device_properties artec_t1_usb2_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
.pid_filter_count = 16,
|
||||
|
||||
@ -417,6 +429,7 @@ static struct dvb_usb_device_properties artec_t1_usb2_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
.size_of_priv = sizeof(struct dibusb_state),
|
||||
}
|
||||
},
|
||||
|
@ -57,6 +57,8 @@ static struct dvb_usb_device_properties dibusb_mc_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
.pid_filter_count = 32,
|
||||
.streaming_ctrl = dibusb2_0_streaming_ctrl,
|
||||
@ -76,6 +78,7 @@ static struct dvb_usb_device_properties dibusb_mc_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
.size_of_priv = sizeof(struct dibusb_state),
|
||||
}
|
||||
},
|
||||
|
@ -137,11 +137,16 @@ static int digitv_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
struct digitv_state *st = adap->dev->priv;
|
||||
|
||||
if ((adap->fe = dvb_attach(mt352_attach, &digitv_mt352_config, &adap->dev->i2c_adap)) != NULL) {
|
||||
adap->fe_adap[0].fe = dvb_attach(mt352_attach, &digitv_mt352_config,
|
||||
&adap->dev->i2c_adap);
|
||||
if ((adap->fe_adap[0].fe) != NULL) {
|
||||
st->is_nxt6000 = 0;
|
||||
return 0;
|
||||
}
|
||||
if ((adap->fe = dvb_attach(nxt6000_attach, &digitv_nxt6000_config, &adap->dev->i2c_adap)) != NULL) {
|
||||
adap->fe_adap[0].fe = dvb_attach(nxt6000_attach,
|
||||
&digitv_nxt6000_config,
|
||||
&adap->dev->i2c_adap);
|
||||
if ((adap->fe_adap[0].fe) != NULL) {
|
||||
st->is_nxt6000 = 1;
|
||||
return 0;
|
||||
}
|
||||
@ -152,11 +157,11 @@ static int digitv_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
struct digitv_state *st = adap->dev->priv;
|
||||
|
||||
if (!dvb_attach(dvb_pll_attach, adap->fe, 0x60, NULL, DVB_PLL_TDED4))
|
||||
if (!dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60, NULL, DVB_PLL_TDED4))
|
||||
return -ENODEV;
|
||||
|
||||
if (st->is_nxt6000)
|
||||
adap->fe->ops.tuner_ops.set_params = digitv_nxt6000_tuner_set_params;
|
||||
adap->fe_adap[0].fe->ops.tuner_ops.set_params = digitv_nxt6000_tuner_set_params;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -292,6 +297,8 @@ static struct dvb_usb_device_properties digitv_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.frontend_attach = digitv_frontend_attach,
|
||||
.tuner_attach = digitv_tuner_attach,
|
||||
|
||||
@ -306,6 +313,7 @@ static struct dvb_usb_device_properties digitv_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
}
|
||||
},
|
||||
.identify_state = digitv_identify_state,
|
||||
|
@ -90,7 +90,7 @@ static int dtt200u_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
||||
|
||||
static int dtt200u_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
adap->fe = dtt200u_fe_attach(adap->dev);
|
||||
adap->fe_adap[0].fe = dtt200u_fe_attach(adap->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -140,6 +140,8 @@ static struct dvb_usb_device_properties dtt200u_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
|
||||
.pid_filter_count = 15,
|
||||
|
||||
@ -157,6 +159,7 @@ static struct dvb_usb_device_properties dtt200u_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
}
|
||||
},
|
||||
.power_ctrl = dtt200u_power_ctrl,
|
||||
@ -187,6 +190,8 @@ static struct dvb_usb_device_properties wt220u_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
|
||||
.pid_filter_count = 15,
|
||||
|
||||
@ -204,6 +209,7 @@ static struct dvb_usb_device_properties wt220u_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
}
|
||||
},
|
||||
.power_ctrl = dtt200u_power_ctrl,
|
||||
@ -234,6 +240,8 @@ static struct dvb_usb_device_properties wt220u_fc_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
|
||||
.pid_filter_count = 15,
|
||||
|
||||
@ -251,6 +259,7 @@ static struct dvb_usb_device_properties wt220u_fc_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
}
|
||||
},
|
||||
.power_ctrl = dtt200u_power_ctrl,
|
||||
@ -281,6 +290,8 @@ static struct dvb_usb_device_properties wt220u_zl0353_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
|
||||
.pid_filter_count = 15,
|
||||
|
||||
@ -298,6 +309,7 @@ static struct dvb_usb_device_properties wt220u_zl0353_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
}
|
||||
},
|
||||
.power_ctrl = dtt200u_power_ctrl,
|
||||
|
@ -115,13 +115,13 @@ static struct zl10353_config dtv5100_zl10353_config = {
|
||||
|
||||
static int dtv5100_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
adap->fe = dvb_attach(zl10353_attach, &dtv5100_zl10353_config,
|
||||
adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &dtv5100_zl10353_config,
|
||||
&adap->dev->i2c_adap);
|
||||
if (adap->fe == NULL)
|
||||
if (adap->fe_adap[0].fe == NULL)
|
||||
return -EIO;
|
||||
|
||||
/* disable i2c gate, or it won't work... is this safe? */
|
||||
adap->fe->ops.i2c_gate_ctrl = NULL;
|
||||
adap->fe_adap[0].fe->ops.i2c_gate_ctrl = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -133,7 +133,7 @@ static struct qt1010_config dtv5100_qt1010_config = {
|
||||
static int dtv5100_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
return dvb_attach(qt1010_attach,
|
||||
adap->fe, &adap->dev->i2c_adap,
|
||||
adap->fe_adap[0].fe, &adap->dev->i2c_adap,
|
||||
&dtv5100_qt1010_config) == NULL ? -ENODEV : 0;
|
||||
}
|
||||
|
||||
@ -180,6 +180,8 @@ static struct dvb_usb_device_properties dtv5100_properties = {
|
||||
|
||||
.num_adapters = 1,
|
||||
.adapter = {{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.frontend_attach = dtv5100_frontend_attach,
|
||||
.tuner_attach = dtv5100_tuner_attach,
|
||||
|
||||
@ -193,6 +195,7 @@ static struct dvb_usb_device_properties dtv5100_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
} },
|
||||
|
||||
.i2c_algo = &dtv5100_i2c_algo,
|
||||
|
@ -17,15 +17,20 @@ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
|
||||
if (adap == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
if ((adap->active_fe < 0) ||
|
||||
(adap->active_fe >= adap->num_frontends_initialized)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
newfeedcount = adap->feedcount + (onoff ? 1 : -1);
|
||||
|
||||
/* stop feed before setting a new pid if there will be no pid anymore */
|
||||
if (newfeedcount == 0) {
|
||||
deb_ts("stop feeding\n");
|
||||
usb_urb_kill(&adap->stream);
|
||||
usb_urb_kill(&adap->fe_adap[adap->active_fe].stream);
|
||||
|
||||
if (adap->props.streaming_ctrl != NULL) {
|
||||
ret = adap->props.streaming_ctrl(adap, 0);
|
||||
if (adap->props.fe[adap->active_fe].streaming_ctrl != NULL) {
|
||||
ret = adap->props.fe[adap->active_fe].streaming_ctrl(adap, 0);
|
||||
if (ret < 0) {
|
||||
err("error while stopping stream.");
|
||||
return ret;
|
||||
@ -36,36 +41,37 @@ static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
|
||||
adap->feedcount = newfeedcount;
|
||||
|
||||
/* activate the pid on the device specific pid_filter */
|
||||
deb_ts("setting pid (%s): %5d %04x at index %d '%s'\n",adap->pid_filtering ?
|
||||
"yes" : "no", dvbdmxfeed->pid,dvbdmxfeed->pid,dvbdmxfeed->index,onoff ?
|
||||
"on" : "off");
|
||||
if (adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER &&
|
||||
adap->pid_filtering &&
|
||||
adap->props.pid_filter != NULL)
|
||||
adap->props.pid_filter(adap, dvbdmxfeed->index, dvbdmxfeed->pid,onoff);
|
||||
deb_ts("setting pid (%s): %5d %04x at index %d '%s'\n",
|
||||
adap->fe_adap[adap->active_fe].pid_filtering ?
|
||||
"yes" : "no", dvbdmxfeed->pid, dvbdmxfeed->pid,
|
||||
dvbdmxfeed->index, onoff ? "on" : "off");
|
||||
if (adap->props.fe[adap->active_fe].caps & DVB_USB_ADAP_HAS_PID_FILTER &&
|
||||
adap->fe_adap[adap->active_fe].pid_filtering &&
|
||||
adap->props.fe[adap->active_fe].pid_filter != NULL)
|
||||
adap->props.fe[adap->active_fe].pid_filter(adap, dvbdmxfeed->index, dvbdmxfeed->pid, onoff);
|
||||
|
||||
/* start the feed if this was the first feed and there is still a feed
|
||||
* for reception.
|
||||
*/
|
||||
if (adap->feedcount == onoff && adap->feedcount > 0) {
|
||||
deb_ts("submitting all URBs\n");
|
||||
usb_urb_submit(&adap->stream);
|
||||
usb_urb_submit(&adap->fe_adap[adap->active_fe].stream);
|
||||
|
||||
deb_ts("controlling pid parser\n");
|
||||
if (adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER &&
|
||||
adap->props.caps &
|
||||
if (adap->props.fe[adap->active_fe].caps & DVB_USB_ADAP_HAS_PID_FILTER &&
|
||||
adap->props.fe[adap->active_fe].caps &
|
||||
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF &&
|
||||
adap->props.pid_filter_ctrl != NULL) {
|
||||
ret = adap->props.pid_filter_ctrl(adap,
|
||||
adap->pid_filtering);
|
||||
adap->props.fe[adap->active_fe].pid_filter_ctrl != NULL) {
|
||||
ret = adap->props.fe[adap->active_fe].pid_filter_ctrl(adap,
|
||||
adap->fe_adap[adap->active_fe].pid_filtering);
|
||||
if (ret < 0) {
|
||||
err("could not handle pid_parser");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
deb_ts("start feeding\n");
|
||||
if (adap->props.streaming_ctrl != NULL) {
|
||||
ret = adap->props.streaming_ctrl(adap, 1);
|
||||
if (adap->props.fe[adap->active_fe].streaming_ctrl != NULL) {
|
||||
ret = adap->props.fe[adap->active_fe].streaming_ctrl(adap, 1);
|
||||
if (ret < 0) {
|
||||
err("error while enabling fifo.");
|
||||
return ret;
|
||||
@ -90,6 +96,7 @@ static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
|
||||
|
||||
int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap, short *adapter_nums)
|
||||
{
|
||||
int i;
|
||||
int ret = dvb_register_adapter(&adap->dvb_adap, adap->dev->desc->name,
|
||||
adap->dev->owner, &adap->dev->udev->dev,
|
||||
adapter_nums);
|
||||
@ -112,7 +119,12 @@ int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap, short *adapter_nums)
|
||||
adap->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
|
||||
adap->demux.priv = adap;
|
||||
|
||||
adap->demux.feednum = adap->demux.filternum = adap->max_feed_count;
|
||||
adap->demux.filternum = 0;
|
||||
for (i = 0; i < adap->props.num_frontends; i++) {
|
||||
if (adap->demux.filternum < adap->fe_adap[i].max_feed_count)
|
||||
adap->demux.filternum = adap->fe_adap[i].max_feed_count;
|
||||
}
|
||||
adap->demux.feednum = adap->demux.filternum;
|
||||
adap->demux.start_feed = dvb_usb_start_feed;
|
||||
adap->demux.stop_feed = dvb_usb_stop_feed;
|
||||
adap->demux.write_to_decoder = NULL;
|
||||
@ -156,14 +168,33 @@ int dvb_usb_adapter_dvb_exit(struct dvb_usb_adapter *adap)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dvb_usb_set_active_fe(struct dvb_frontend *fe, int onoff)
|
||||
{
|
||||
struct dvb_usb_adapter *adap = fe->dvb->priv;
|
||||
|
||||
int ret = (adap->props.frontend_ctrl) ?
|
||||
adap->props.frontend_ctrl(fe, onoff) : 0;
|
||||
|
||||
if (ret < 0) {
|
||||
err("frontend_ctrl request failed");
|
||||
return ret;
|
||||
}
|
||||
if (onoff)
|
||||
adap->active_fe = fe->id;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dvb_usb_fe_wakeup(struct dvb_frontend *fe)
|
||||
{
|
||||
struct dvb_usb_adapter *adap = fe->dvb->priv;
|
||||
|
||||
dvb_usb_device_power_ctrl(adap->dev, 1);
|
||||
|
||||
if (adap->fe_init)
|
||||
adap->fe_init(fe);
|
||||
dvb_usb_set_active_fe(fe, 1);
|
||||
|
||||
if (adap->fe_adap[fe->id].fe_init)
|
||||
adap->fe_adap[fe->id].fe_init(fe);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -172,45 +203,81 @@ static int dvb_usb_fe_sleep(struct dvb_frontend *fe)
|
||||
{
|
||||
struct dvb_usb_adapter *adap = fe->dvb->priv;
|
||||
|
||||
if (adap->fe_sleep)
|
||||
adap->fe_sleep(fe);
|
||||
if (adap->fe_adap[fe->id].fe_sleep)
|
||||
adap->fe_adap[fe->id].fe_sleep(fe);
|
||||
|
||||
dvb_usb_set_active_fe(fe, 0);
|
||||
|
||||
return dvb_usb_device_power_ctrl(adap->dev, 0);
|
||||
}
|
||||
|
||||
int dvb_usb_adapter_frontend_init(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
if (adap->props.frontend_attach == NULL) {
|
||||
err("strange: '%s' #%d doesn't want to attach a frontend.",adap->dev->desc->name, adap->id);
|
||||
return 0;
|
||||
}
|
||||
int ret, i;
|
||||
|
||||
/* re-assign sleep and wakeup functions */
|
||||
if (adap->props.frontend_attach(adap) == 0 && adap->fe != NULL) {
|
||||
adap->fe_init = adap->fe->ops.init; adap->fe->ops.init = dvb_usb_fe_wakeup;
|
||||
adap->fe_sleep = adap->fe->ops.sleep; adap->fe->ops.sleep = dvb_usb_fe_sleep;
|
||||
/* register all given adapter frontends */
|
||||
for (i = 0; i < adap->props.num_frontends; i++) {
|
||||
|
||||
if (dvb_register_frontend(&adap->dvb_adap, adap->fe)) {
|
||||
err("Frontend registration failed.");
|
||||
dvb_frontend_detach(adap->fe);
|
||||
adap->fe = NULL;
|
||||
return -ENODEV;
|
||||
if (adap->props.fe[i].frontend_attach == NULL) {
|
||||
err("strange: '%s' #%d,%d "
|
||||
"doesn't want to attach a frontend.",
|
||||
adap->dev->desc->name, adap->id, i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = adap->props.fe[i].frontend_attach(adap);
|
||||
if (ret || adap->fe_adap[i].fe == NULL) {
|
||||
/* only print error when there is no FE at all */
|
||||
if (i == 0)
|
||||
err("no frontend was attached by '%s'",
|
||||
adap->dev->desc->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
adap->fe_adap[i].fe->id = i;
|
||||
|
||||
/* re-assign sleep and wakeup functions */
|
||||
adap->fe_adap[i].fe_init = adap->fe_adap[i].fe->ops.init;
|
||||
adap->fe_adap[i].fe->ops.init = dvb_usb_fe_wakeup;
|
||||
adap->fe_adap[i].fe_sleep = adap->fe_adap[i].fe->ops.sleep;
|
||||
adap->fe_adap[i].fe->ops.sleep = dvb_usb_fe_sleep;
|
||||
|
||||
if (dvb_register_frontend(&adap->dvb_adap, adap->fe_adap[i].fe)) {
|
||||
err("Frontend %d registration failed.", i);
|
||||
dvb_frontend_detach(adap->fe_adap[i].fe);
|
||||
adap->fe_adap[i].fe = NULL;
|
||||
/* In error case, do not try register more FEs,
|
||||
* still leaving already registered FEs alive. */
|
||||
if (i == 0)
|
||||
return -ENODEV;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* only attach the tuner if the demod is there */
|
||||
if (adap->props.tuner_attach != NULL)
|
||||
adap->props.tuner_attach(adap);
|
||||
} else
|
||||
err("no frontend was attached by '%s'",adap->dev->desc->name);
|
||||
if (adap->props.fe[i].tuner_attach != NULL)
|
||||
adap->props.fe[i].tuner_attach(adap);
|
||||
|
||||
adap->num_frontends_initialized++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dvb_usb_adapter_frontend_exit(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
if (adap->fe != NULL) {
|
||||
dvb_unregister_frontend(adap->fe);
|
||||
dvb_frontend_detach(adap->fe);
|
||||
int i = adap->num_frontends_initialized - 1;
|
||||
|
||||
/* unregister all given adapter frontends */
|
||||
for (; i >= 0; i--) {
|
||||
if (adap->fe_adap[i].fe != NULL) {
|
||||
dvb_unregister_frontend(adap->fe_adap[i].fe);
|
||||
dvb_frontend_detach(adap->fe_adap[i].fe);
|
||||
}
|
||||
}
|
||||
adap->num_frontends_initialized = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -136,6 +136,7 @@
|
||||
#define USB_PID_KWORLD_PC160_2T 0xc160
|
||||
#define USB_PID_KWORLD_PC160_T 0xc161
|
||||
#define USB_PID_KWORLD_UB383_T 0xe383
|
||||
#define USB_PID_KWORLD_UB499_2T_T09 0xe409
|
||||
#define USB_PID_KWORLD_VSTREAM_COLD 0x17de
|
||||
#define USB_PID_KWORLD_VSTREAM_WARM 0x17df
|
||||
#define USB_PID_TERRATEC_CINERGY_T_USB_XE 0x0055
|
||||
@ -240,6 +241,9 @@
|
||||
#define USB_PID_PCTV_200E 0x020e
|
||||
#define USB_PID_PCTV_400E 0x020f
|
||||
#define USB_PID_PCTV_450E 0x0222
|
||||
#define USB_PID_PCTV_452E 0x021f
|
||||
#define USB_PID_TECHNOTREND_CONNECT_S2_3600 0x3007
|
||||
#define USB_PID_TECHNOTREND_CONNECT_S2_3650_CI 0x300a
|
||||
#define USB_PID_NEBULA_DIGITV 0x0201
|
||||
#define USB_PID_DVICO_BLUEBIRD_LGDT 0xd820
|
||||
#define USB_PID_DVICO_BLUEBIRD_LG064F_COLD 0xd500
|
||||
|
@ -29,7 +29,7 @@ MODULE_PARM_DESC(force_pid_filter_usage, "force all dvb-usb-devices to use a PID
|
||||
static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
|
||||
{
|
||||
struct dvb_usb_adapter *adap;
|
||||
int ret, n;
|
||||
int ret, n, o;
|
||||
|
||||
for (n = 0; n < d->props.num_adapters; n++) {
|
||||
adap = &d->adapter[n];
|
||||
@ -38,31 +38,42 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
|
||||
|
||||
memcpy(&adap->props, &d->props.adapter[n], sizeof(struct dvb_usb_adapter_properties));
|
||||
|
||||
for (o = 0; o < adap->props.num_frontends; o++) {
|
||||
struct dvb_usb_adapter_fe_properties *props = &adap->props.fe[o];
|
||||
/* speed - when running at FULL speed we need a HW PID filter */
|
||||
if (d->udev->speed == USB_SPEED_FULL && !(adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER)) {
|
||||
if (d->udev->speed == USB_SPEED_FULL && !(props->caps & DVB_USB_ADAP_HAS_PID_FILTER)) {
|
||||
err("This USB2.0 device cannot be run on a USB1.1 port. (it lacks a hardware PID filter)");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if ((d->udev->speed == USB_SPEED_FULL && adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER) ||
|
||||
(adap->props.caps & DVB_USB_ADAP_NEED_PID_FILTERING)) {
|
||||
info("will use the device's hardware PID filter (table count: %d).", adap->props.pid_filter_count);
|
||||
adap->pid_filtering = 1;
|
||||
adap->max_feed_count = adap->props.pid_filter_count;
|
||||
if ((d->udev->speed == USB_SPEED_FULL && props->caps & DVB_USB_ADAP_HAS_PID_FILTER) ||
|
||||
(props->caps & DVB_USB_ADAP_NEED_PID_FILTERING)) {
|
||||
info("will use the device's hardware PID filter (table count: %d).", props->pid_filter_count);
|
||||
adap->fe_adap[o].pid_filtering = 1;
|
||||
adap->fe_adap[o].max_feed_count = props->pid_filter_count;
|
||||
} else {
|
||||
info("will pass the complete MPEG2 transport stream to the software demuxer.");
|
||||
adap->pid_filtering = 0;
|
||||
adap->max_feed_count = 255;
|
||||
adap->fe_adap[o].pid_filtering = 0;
|
||||
adap->fe_adap[o].max_feed_count = 255;
|
||||
}
|
||||
|
||||
if (!adap->pid_filtering &&
|
||||
if (!adap->fe_adap[o].pid_filtering &&
|
||||
dvb_usb_force_pid_filter_usage &&
|
||||
adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER) {
|
||||
props->caps & DVB_USB_ADAP_HAS_PID_FILTER) {
|
||||
info("pid filter enabled by module option.");
|
||||
adap->pid_filtering = 1;
|
||||
adap->max_feed_count = adap->props.pid_filter_count;
|
||||
adap->fe_adap[o].pid_filtering = 1;
|
||||
adap->fe_adap[o].max_feed_count = props->pid_filter_count;
|
||||
}
|
||||
|
||||
if (props->size_of_priv > 0) {
|
||||
adap->fe_adap[o].priv = kzalloc(props->size_of_priv, GFP_KERNEL);
|
||||
if (adap->fe_adap[o].priv == NULL) {
|
||||
err("no memory for priv for adapter %d fe %d.", n, o);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (adap->props.size_of_priv > 0) {
|
||||
adap->priv = kzalloc(adap->props.size_of_priv, GFP_KERNEL);
|
||||
if (adap->priv == NULL) {
|
||||
@ -77,6 +88,10 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* use exclusive FE lock if there is multiple shared FEs */
|
||||
if (adap->fe_adap[1].fe)
|
||||
adap->dvb_adap.mfe_shared = 1;
|
||||
|
||||
d->num_adapters_initialized++;
|
||||
d->state |= DVB_USB_STATE_DVB;
|
||||
}
|
||||
|
@ -82,16 +82,28 @@ static void dvb_usb_data_complete_204(struct usb_data_stream *stream, u8 *buffer
|
||||
|
||||
int dvb_usb_adapter_stream_init(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
adap->stream.udev = adap->dev->udev;
|
||||
if (adap->props.caps & DVB_USB_ADAP_RECEIVES_204_BYTE_TS)
|
||||
adap->stream.complete = dvb_usb_data_complete_204;
|
||||
else
|
||||
adap->stream.complete = dvb_usb_data_complete;
|
||||
adap->stream.user_priv = adap;
|
||||
return usb_urb_init(&adap->stream, &adap->props.stream);
|
||||
int i, ret = 0;
|
||||
for (i = 0; i < adap->props.num_frontends; i++) {
|
||||
|
||||
adap->fe_adap[i].stream.udev = adap->dev->udev;
|
||||
if (adap->props.fe[i].caps & DVB_USB_ADAP_RECEIVES_204_BYTE_TS)
|
||||
adap->fe_adap[i].stream.complete =
|
||||
dvb_usb_data_complete_204;
|
||||
else
|
||||
adap->fe_adap[i].stream.complete = dvb_usb_data_complete;
|
||||
adap->fe_adap[i].stream.user_priv = adap;
|
||||
ret = usb_urb_init(&adap->fe_adap[i].stream,
|
||||
&adap->props.fe[i].stream);
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int dvb_usb_adapter_stream_exit(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
return usb_urb_exit(&adap->stream);
|
||||
int i;
|
||||
for (i = 0; i < adap->props.num_frontends; i++)
|
||||
usb_urb_exit(&adap->fe_adap[i].stream);
|
||||
return 0;
|
||||
}
|
||||
|
@ -124,6 +124,8 @@ struct usb_data_stream_properties {
|
||||
* @caps: capabilities of the DVB USB device.
|
||||
* @pid_filter_count: number of PID filter position in the optional hardware
|
||||
* PID-filter.
|
||||
* @num_frontends: number of frontends of the DVB USB adapter.
|
||||
* @frontend_ctrl: called to power on/off active frontend.
|
||||
* @streaming_ctrl: called to start and stop the MPEG2-TS streaming of the
|
||||
* device (not URB submitting/killing).
|
||||
* @pid_filter_ctrl: called to en/disable the PID filter, if any.
|
||||
@ -134,7 +136,7 @@ struct usb_data_stream_properties {
|
||||
* pll_desc and pll_init_buf of struct dvb_usb_device).
|
||||
* @stream: configuration of the USB streaming
|
||||
*/
|
||||
struct dvb_usb_adapter_properties {
|
||||
struct dvb_usb_adapter_fe_properties {
|
||||
#define DVB_USB_ADAP_HAS_PID_FILTER 0x01
|
||||
#define DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF 0x02
|
||||
#define DVB_USB_ADAP_NEED_PID_FILTERING 0x04
|
||||
@ -152,9 +154,18 @@ struct dvb_usb_adapter_properties {
|
||||
struct usb_data_stream_properties stream;
|
||||
|
||||
int size_of_priv;
|
||||
};
|
||||
|
||||
#define MAX_NO_OF_FE_PER_ADAP 2
|
||||
struct dvb_usb_adapter_properties {
|
||||
int size_of_priv;
|
||||
|
||||
int (*frontend_ctrl) (struct dvb_frontend *, int);
|
||||
int (*fe_ioctl_override) (struct dvb_frontend *,
|
||||
unsigned int, void *, unsigned int);
|
||||
|
||||
int num_frontends;
|
||||
struct dvb_usb_adapter_fe_properties fe[MAX_NO_OF_FE_PER_ADAP];
|
||||
};
|
||||
|
||||
/**
|
||||
@ -345,6 +356,20 @@ struct usb_data_stream {
|
||||
*
|
||||
* @stream: the usb data stream.
|
||||
*/
|
||||
struct dvb_usb_fe_adapter {
|
||||
struct dvb_frontend *fe;
|
||||
|
||||
int (*fe_init) (struct dvb_frontend *);
|
||||
int (*fe_sleep) (struct dvb_frontend *);
|
||||
|
||||
struct usb_data_stream stream;
|
||||
|
||||
int pid_filtering;
|
||||
int max_feed_count;
|
||||
|
||||
void *priv;
|
||||
};
|
||||
|
||||
struct dvb_usb_adapter {
|
||||
struct dvb_usb_device *dev;
|
||||
struct dvb_usb_adapter_properties props;
|
||||
@ -356,20 +381,16 @@ struct dvb_usb_adapter {
|
||||
u8 id;
|
||||
|
||||
int feedcount;
|
||||
int pid_filtering;
|
||||
|
||||
/* dvb */
|
||||
struct dvb_adapter dvb_adap;
|
||||
struct dmxdev dmxdev;
|
||||
struct dvb_demux demux;
|
||||
struct dvb_net dvb_net;
|
||||
struct dvb_frontend *fe;
|
||||
int max_feed_count;
|
||||
|
||||
int (*fe_init) (struct dvb_frontend *);
|
||||
int (*fe_sleep) (struct dvb_frontend *);
|
||||
|
||||
struct usb_data_stream stream;
|
||||
struct dvb_usb_fe_adapter fe_adap[MAX_NO_OF_FE_PER_ADAP];
|
||||
int active_fe;
|
||||
int num_frontends_initialized;
|
||||
|
||||
void *priv;
|
||||
};
|
||||
|
@ -992,18 +992,18 @@ static int dw2104_frontend_attach(struct dvb_usb_adapter *d)
|
||||
struct dvb_tuner_ops *tuner_ops = NULL;
|
||||
|
||||
if (demod_probe & 4) {
|
||||
d->fe = dvb_attach(stv0900_attach, &dw2104a_stv0900_config,
|
||||
d->fe_adap[0].fe = dvb_attach(stv0900_attach, &dw2104a_stv0900_config,
|
||||
&d->dev->i2c_adap, 0);
|
||||
if (d->fe != NULL) {
|
||||
if (dvb_attach(stb6100_attach, d->fe,
|
||||
if (d->fe_adap[0].fe != NULL) {
|
||||
if (dvb_attach(stb6100_attach, d->fe_adap[0].fe,
|
||||
&dw2104a_stb6100_config,
|
||||
&d->dev->i2c_adap)) {
|
||||
tuner_ops = &d->fe->ops.tuner_ops;
|
||||
tuner_ops = &d->fe_adap[0].fe->ops.tuner_ops;
|
||||
tuner_ops->set_frequency = stb6100_set_freq;
|
||||
tuner_ops->get_frequency = stb6100_get_freq;
|
||||
tuner_ops->set_bandwidth = stb6100_set_bandw;
|
||||
tuner_ops->get_bandwidth = stb6100_get_bandw;
|
||||
d->fe->ops.set_voltage = dw210x_set_voltage;
|
||||
d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
|
||||
info("Attached STV0900+STB6100!\n");
|
||||
return 0;
|
||||
}
|
||||
@ -1011,13 +1011,13 @@ static int dw2104_frontend_attach(struct dvb_usb_adapter *d)
|
||||
}
|
||||
|
||||
if (demod_probe & 2) {
|
||||
d->fe = dvb_attach(stv0900_attach, &dw2104_stv0900_config,
|
||||
d->fe_adap[0].fe = dvb_attach(stv0900_attach, &dw2104_stv0900_config,
|
||||
&d->dev->i2c_adap, 0);
|
||||
if (d->fe != NULL) {
|
||||
if (dvb_attach(stv6110_attach, d->fe,
|
||||
if (d->fe_adap[0].fe != NULL) {
|
||||
if (dvb_attach(stv6110_attach, d->fe_adap[0].fe,
|
||||
&dw2104_stv6110_config,
|
||||
&d->dev->i2c_adap)) {
|
||||
d->fe->ops.set_voltage = dw210x_set_voltage;
|
||||
d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
|
||||
info("Attached STV0900+STV6110A!\n");
|
||||
return 0;
|
||||
}
|
||||
@ -1025,19 +1025,19 @@ static int dw2104_frontend_attach(struct dvb_usb_adapter *d)
|
||||
}
|
||||
|
||||
if (demod_probe & 1) {
|
||||
d->fe = dvb_attach(cx24116_attach, &dw2104_config,
|
||||
d->fe_adap[0].fe = dvb_attach(cx24116_attach, &dw2104_config,
|
||||
&d->dev->i2c_adap);
|
||||
if (d->fe != NULL) {
|
||||
d->fe->ops.set_voltage = dw210x_set_voltage;
|
||||
if (d->fe_adap[0].fe != NULL) {
|
||||
d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
|
||||
info("Attached cx24116!\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
d->fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config,
|
||||
d->fe_adap[0].fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config,
|
||||
&d->dev->i2c_adap);
|
||||
if (d->fe != NULL) {
|
||||
d->fe->ops.set_voltage = dw210x_set_voltage;
|
||||
if (d->fe_adap[0].fe != NULL) {
|
||||
d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
|
||||
info("Attached DS3000!\n");
|
||||
return 0;
|
||||
}
|
||||
@ -1053,22 +1053,22 @@ static int dw2102_frontend_attach(struct dvb_usb_adapter *d)
|
||||
{
|
||||
if (dw2102_properties.i2c_algo == &dw2102_serit_i2c_algo) {
|
||||
/*dw2102_properties.adapter->tuner_attach = NULL;*/
|
||||
d->fe = dvb_attach(si21xx_attach, &serit_sp1511lhb_config,
|
||||
d->fe_adap[0].fe = dvb_attach(si21xx_attach, &serit_sp1511lhb_config,
|
||||
&d->dev->i2c_adap);
|
||||
if (d->fe != NULL) {
|
||||
d->fe->ops.set_voltage = dw210x_set_voltage;
|
||||
if (d->fe_adap[0].fe != NULL) {
|
||||
d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
|
||||
info("Attached si21xx!\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (dw2102_properties.i2c_algo == &dw2102_earda_i2c_algo) {
|
||||
d->fe = dvb_attach(stv0288_attach, &earda_config,
|
||||
d->fe_adap[0].fe = dvb_attach(stv0288_attach, &earda_config,
|
||||
&d->dev->i2c_adap);
|
||||
if (d->fe != NULL) {
|
||||
if (dvb_attach(stb6000_attach, d->fe, 0x61,
|
||||
if (d->fe_adap[0].fe != NULL) {
|
||||
if (dvb_attach(stb6000_attach, d->fe_adap[0].fe, 0x61,
|
||||
&d->dev->i2c_adap)) {
|
||||
d->fe->ops.set_voltage = dw210x_set_voltage;
|
||||
d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
|
||||
info("Attached stv0288!\n");
|
||||
return 0;
|
||||
}
|
||||
@ -1077,10 +1077,10 @@ static int dw2102_frontend_attach(struct dvb_usb_adapter *d)
|
||||
|
||||
if (dw2102_properties.i2c_algo == &dw2102_i2c_algo) {
|
||||
/*dw2102_properties.adapter->tuner_attach = dw2102_tuner_attach;*/
|
||||
d->fe = dvb_attach(stv0299_attach, &sharp_z0194a_config,
|
||||
d->fe_adap[0].fe = dvb_attach(stv0299_attach, &sharp_z0194a_config,
|
||||
&d->dev->i2c_adap);
|
||||
if (d->fe != NULL) {
|
||||
d->fe->ops.set_voltage = dw210x_set_voltage;
|
||||
if (d->fe_adap[0].fe != NULL) {
|
||||
d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
|
||||
info("Attached stv0299!\n");
|
||||
return 0;
|
||||
}
|
||||
@ -1090,9 +1090,9 @@ static int dw2102_frontend_attach(struct dvb_usb_adapter *d)
|
||||
|
||||
static int dw3101_frontend_attach(struct dvb_usb_adapter *d)
|
||||
{
|
||||
d->fe = dvb_attach(tda10023_attach, &dw3101_tda10023_config,
|
||||
d->fe_adap[0].fe = dvb_attach(tda10023_attach, &dw3101_tda10023_config,
|
||||
&d->dev->i2c_adap, 0x48);
|
||||
if (d->fe != NULL) {
|
||||
if (d->fe_adap[0].fe != NULL) {
|
||||
info("Attached tda10023!\n");
|
||||
return 0;
|
||||
}
|
||||
@ -1101,12 +1101,12 @@ static int dw3101_frontend_attach(struct dvb_usb_adapter *d)
|
||||
|
||||
static int zl100313_frontend_attach(struct dvb_usb_adapter *d)
|
||||
{
|
||||
d->fe = dvb_attach(mt312_attach, &zl313_config,
|
||||
d->fe_adap[0].fe = dvb_attach(mt312_attach, &zl313_config,
|
||||
&d->dev->i2c_adap);
|
||||
if (d->fe != NULL) {
|
||||
if (dvb_attach(zl10039_attach, d->fe, 0x60,
|
||||
if (d->fe_adap[0].fe != NULL) {
|
||||
if (dvb_attach(zl10039_attach, d->fe_adap[0].fe, 0x60,
|
||||
&d->dev->i2c_adap)) {
|
||||
d->fe->ops.set_voltage = dw210x_set_voltage;
|
||||
d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
|
||||
info("Attached zl100313+zl10039!\n");
|
||||
return 0;
|
||||
}
|
||||
@ -1119,16 +1119,16 @@ static int stv0288_frontend_attach(struct dvb_usb_adapter *d)
|
||||
{
|
||||
u8 obuf[] = {7, 1};
|
||||
|
||||
d->fe = dvb_attach(stv0288_attach, &earda_config,
|
||||
d->fe_adap[0].fe = dvb_attach(stv0288_attach, &earda_config,
|
||||
&d->dev->i2c_adap);
|
||||
|
||||
if (d->fe == NULL)
|
||||
if (d->fe_adap[0].fe == NULL)
|
||||
return -EIO;
|
||||
|
||||
if (NULL == dvb_attach(stb6000_attach, d->fe, 0x61, &d->dev->i2c_adap))
|
||||
if (NULL == dvb_attach(stb6000_attach, d->fe_adap[0].fe, 0x61, &d->dev->i2c_adap))
|
||||
return -EIO;
|
||||
|
||||
d->fe->ops.set_voltage = dw210x_set_voltage;
|
||||
d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
|
||||
|
||||
dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
|
||||
|
||||
@ -1143,14 +1143,14 @@ static int ds3000_frontend_attach(struct dvb_usb_adapter *d)
|
||||
struct s6x0_state *st = (struct s6x0_state *)d->dev->priv;
|
||||
u8 obuf[] = {7, 1};
|
||||
|
||||
d->fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config,
|
||||
d->fe_adap[0].fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config,
|
||||
&d->dev->i2c_adap);
|
||||
|
||||
if (d->fe == NULL)
|
||||
if (d->fe_adap[0].fe == NULL)
|
||||
return -EIO;
|
||||
|
||||
st->old_set_voltage = d->fe->ops.set_voltage;
|
||||
d->fe->ops.set_voltage = s660_set_voltage;
|
||||
st->old_set_voltage = d->fe_adap[0].fe->ops.set_voltage;
|
||||
d->fe_adap[0].fe->ops.set_voltage = s660_set_voltage;
|
||||
|
||||
dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
|
||||
|
||||
@ -1163,12 +1163,12 @@ static int prof_7500_frontend_attach(struct dvb_usb_adapter *d)
|
||||
{
|
||||
u8 obuf[] = {7, 1};
|
||||
|
||||
d->fe = dvb_attach(stv0900_attach, &prof_7500_stv0900_config,
|
||||
d->fe_adap[0].fe = dvb_attach(stv0900_attach, &prof_7500_stv0900_config,
|
||||
&d->dev->i2c_adap, 0);
|
||||
if (d->fe == NULL)
|
||||
if (d->fe_adap[0].fe == NULL)
|
||||
return -EIO;
|
||||
|
||||
d->fe->ops.set_voltage = dw210x_set_voltage;
|
||||
d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
|
||||
|
||||
dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
|
||||
|
||||
@ -1204,9 +1204,9 @@ static int su3000_frontend_attach(struct dvb_usb_adapter *d)
|
||||
if (dvb_usb_generic_rw(d->dev, obuf, 1, ibuf, 1, 0) < 0)
|
||||
err("command 0x51 transfer failed.");
|
||||
|
||||
d->fe = dvb_attach(ds3000_attach, &su3000_ds3000_config,
|
||||
d->fe_adap[0].fe = dvb_attach(ds3000_attach, &su3000_ds3000_config,
|
||||
&d->dev->i2c_adap);
|
||||
if (d->fe == NULL)
|
||||
if (d->fe_adap[0].fe == NULL)
|
||||
return -EIO;
|
||||
|
||||
info("Attached DS3000!\n");
|
||||
@ -1216,14 +1216,14 @@ static int su3000_frontend_attach(struct dvb_usb_adapter *d)
|
||||
|
||||
static int dw2102_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
dvb_attach(dvb_pll_attach, adap->fe, 0x60,
|
||||
dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60,
|
||||
&adap->dev->i2c_adap, DVB_PLL_OPERA1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dw3101_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
dvb_attach(dvb_pll_attach, adap->fe, 0x60,
|
||||
dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60,
|
||||
&adap->dev->i2c_adap, DVB_PLL_TUA6034);
|
||||
|
||||
return 0;
|
||||
@ -1535,7 +1535,7 @@ static int dw2102_load_firmware(struct usb_device *dev,
|
||||
DW210X_READ_MSG);
|
||||
if ((reset16[0] == 0xa1) || (reset16[0] == 0x80)) {
|
||||
dw2102_properties.i2c_algo = &dw2102_i2c_algo;
|
||||
dw2102_properties.adapter->tuner_attach = &dw2102_tuner_attach;
|
||||
dw2102_properties.adapter->fe[0].tuner_attach = &dw2102_tuner_attach;
|
||||
break;
|
||||
} else {
|
||||
/* check STV0288 frontend */
|
||||
@ -1591,6 +1591,8 @@ static struct dvb_usb_device_properties dw2102_properties = {
|
||||
.read_mac_address = dw210x_read_mac_address,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.frontend_attach = dw2102_frontend_attach,
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
@ -1602,6 +1604,7 @@ static struct dvb_usb_device_properties dw2102_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
}
|
||||
},
|
||||
.num_device_descs = 3,
|
||||
@ -1642,6 +1645,8 @@ static struct dvb_usb_device_properties dw2104_properties = {
|
||||
.read_mac_address = dw210x_read_mac_address,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.frontend_attach = dw2104_frontend_attach,
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
@ -1653,6 +1658,7 @@ static struct dvb_usb_device_properties dw2104_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
}
|
||||
},
|
||||
.num_device_descs = 2,
|
||||
@ -1689,6 +1695,8 @@ static struct dvb_usb_device_properties dw3101_properties = {
|
||||
.read_mac_address = dw210x_read_mac_address,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.frontend_attach = dw3101_frontend_attach,
|
||||
.tuner_attach = dw3101_tuner_attach,
|
||||
.stream = {
|
||||
@ -1701,6 +1709,7 @@ static struct dvb_usb_device_properties dw3101_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
}
|
||||
},
|
||||
.num_device_descs = 1,
|
||||
@ -1733,6 +1742,8 @@ static struct dvb_usb_device_properties s6x0_properties = {
|
||||
.read_mac_address = s6x0_read_mac_address,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.frontend_attach = zl100313_frontend_attach,
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
@ -1744,6 +1755,7 @@ static struct dvb_usb_device_properties s6x0_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
}
|
||||
},
|
||||
.num_device_descs = 1,
|
||||
@ -1810,6 +1822,8 @@ static struct dvb_usb_device_properties su3000_properties = {
|
||||
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.streaming_ctrl = su3000_streaming_ctrl,
|
||||
.frontend_attach = su3000_frontend_attach,
|
||||
.stream = {
|
||||
@ -1822,6 +1836,7 @@ static struct dvb_usb_device_properties su3000_properties = {
|
||||
}
|
||||
}
|
||||
}
|
||||
}},
|
||||
}
|
||||
},
|
||||
.num_device_descs = 3,
|
||||
@ -1855,7 +1870,7 @@ static int dw2102_probe(struct usb_interface *intf,
|
||||
p1100->devices[0] = d1100;
|
||||
p1100->rc.legacy.rc_map_table = rc_map_tbs_table;
|
||||
p1100->rc.legacy.rc_map_size = ARRAY_SIZE(rc_map_tbs_table);
|
||||
p1100->adapter->frontend_attach = stv0288_frontend_attach;
|
||||
p1100->adapter->fe[0].frontend_attach = stv0288_frontend_attach;
|
||||
|
||||
s660 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
|
||||
if (!s660) {
|
||||
@ -1869,7 +1884,7 @@ static int dw2102_probe(struct usb_interface *intf,
|
||||
s660->devices[0] = d660;
|
||||
s660->devices[1] = d480_1;
|
||||
s660->devices[2] = d480_2;
|
||||
s660->adapter->frontend_attach = ds3000_frontend_attach;
|
||||
s660->adapter->fe[0].frontend_attach = ds3000_frontend_attach;
|
||||
|
||||
p7500 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
|
||||
if (!p7500) {
|
||||
@ -1883,7 +1898,7 @@ static int dw2102_probe(struct usb_interface *intf,
|
||||
p7500->devices[0] = d7500;
|
||||
p7500->rc.legacy.rc_map_table = rc_map_tbs_table;
|
||||
p7500->rc.legacy.rc_map_size = ARRAY_SIZE(rc_map_tbs_table);
|
||||
p7500->adapter->frontend_attach = prof_7500_frontend_attach;
|
||||
p7500->adapter->fe[0].frontend_attach = prof_7500_frontend_attach;
|
||||
|
||||
if (0 == dvb_usb_device_init(intf, &dw2102_properties,
|
||||
THIS_MODULE, NULL, adapter_nr) ||
|
||||
|
@ -200,9 +200,9 @@ static struct ec100_config ec168_ec100_config = {
|
||||
static int ec168_ec100_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
deb_info("%s:\n", __func__);
|
||||
adap->fe = dvb_attach(ec100_attach, &ec168_ec100_config,
|
||||
adap->fe_adap[0].fe = dvb_attach(ec100_attach, &ec168_ec100_config,
|
||||
&adap->dev->i2c_adap);
|
||||
if (adap->fe == NULL)
|
||||
if (adap->fe_adap[0].fe == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
@ -228,7 +228,7 @@ static struct mxl5005s_config ec168_mxl5003s_config = {
|
||||
static int ec168_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
deb_info("%s:\n", __func__);
|
||||
return dvb_attach(mxl5005s_attach, adap->fe, &adap->dev->i2c_adap,
|
||||
return dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap,
|
||||
&ec168_mxl5003s_config) == NULL ? -ENODEV : 0;
|
||||
}
|
||||
|
||||
@ -382,6 +382,8 @@ static struct dvb_usb_device_properties ec168_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.streaming_ctrl = ec168_streaming_ctrl,
|
||||
.frontend_attach = ec168_ec100_frontend_attach,
|
||||
.tuner_attach = ec168_mxl5003s_tuner_attach,
|
||||
@ -395,6 +397,7 @@ static struct dvb_usb_device_properties ec168_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -403,8 +403,8 @@ static int friio_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
if (friio_initialize(adap->dev) < 0)
|
||||
return -EIO;
|
||||
|
||||
adap->fe = jdvbt90502_attach(adap->dev);
|
||||
if (adap->fe == NULL)
|
||||
adap->fe_adap[0].fe = jdvbt90502_attach(adap->dev);
|
||||
if (adap->fe_adap[0].fe == NULL)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
@ -473,6 +473,8 @@ static struct dvb_usb_device_properties friio_properties = {
|
||||
/* caps:0 => no pid filter, 188B TS packet */
|
||||
/* GL861 has a HW pid filter, but no info available. */
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.caps = 0,
|
||||
|
||||
.frontend_attach = friio_frontend_attach,
|
||||
@ -490,6 +492,7 @@ static struct dvb_usb_device_properties friio_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
}
|
||||
},
|
||||
.i2c_algo = &gl861_i2c_algo,
|
||||
|
@ -103,9 +103,9 @@ static struct zl10353_config gl861_zl10353_config = {
|
||||
static int gl861_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
|
||||
adap->fe = dvb_attach(zl10353_attach, &gl861_zl10353_config,
|
||||
adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &gl861_zl10353_config,
|
||||
&adap->dev->i2c_adap);
|
||||
if (adap->fe == NULL)
|
||||
if (adap->fe_adap[0].fe == NULL)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
@ -118,7 +118,7 @@ static struct qt1010_config gl861_qt1010_config = {
|
||||
static int gl861_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
return dvb_attach(qt1010_attach,
|
||||
adap->fe, &adap->dev->i2c_adap,
|
||||
adap->fe_adap[0].fe, &adap->dev->i2c_adap,
|
||||
&gl861_qt1010_config) == NULL ? -ENODEV : 0;
|
||||
}
|
||||
|
||||
@ -167,6 +167,8 @@ static struct dvb_usb_device_properties gl861_properties = {
|
||||
|
||||
.num_adapters = 1,
|
||||
.adapter = {{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
|
||||
.frontend_attach = gl861_frontend_attach,
|
||||
.tuner_attach = gl861_tuner_attach,
|
||||
@ -181,6 +183,7 @@ static struct dvb_usb_device_properties gl861_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
} },
|
||||
.i2c_algo = &gl861_i2c_algo,
|
||||
|
||||
|
@ -144,19 +144,25 @@ static int gp8psk_fe_set_frontend(struct dvb_frontend* fe,
|
||||
cmd[6] = (freq >> 16) & 0xff;
|
||||
cmd[7] = (freq >> 24) & 0xff;
|
||||
|
||||
/* backwards compatibility: DVB-S + 8-PSK were used for Turbo-FEC */
|
||||
if (c->delivery_system == SYS_DVBS && c->modulation == PSK_8)
|
||||
c->delivery_system = SYS_TURBO;
|
||||
|
||||
switch (c->delivery_system) {
|
||||
case SYS_DVBS:
|
||||
/* Allow QPSK and 8PSK (even for DVB-S) */
|
||||
if (c->modulation != QPSK && c->modulation != PSK_8) {
|
||||
if (c->modulation != QPSK) {
|
||||
deb_fe("%s: unsupported modulation selected (%d)\n",
|
||||
__func__, c->modulation);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
c->fec_inner = FEC_AUTO;
|
||||
break;
|
||||
case SYS_DVBS2:
|
||||
case SYS_DVBS2: /* kept for backwards compatibility */
|
||||
deb_fe("%s: DVB-S2 delivery system selected\n", __func__);
|
||||
break;
|
||||
case SYS_TURBO:
|
||||
deb_fe("%s: Turbo-FEC delivery system selected\n", __func__);
|
||||
break;
|
||||
|
||||
default:
|
||||
deb_fe("%s: unsupported delivery system selected (%d)\n",
|
||||
@ -189,7 +195,10 @@ static int gp8psk_fe_set_frontend(struct dvb_frontend* fe,
|
||||
default:
|
||||
cmd[9] = 5; break;
|
||||
}
|
||||
cmd[8] = ADV_MOD_DVB_QPSK;
|
||||
if (c->delivery_system == SYS_TURBO)
|
||||
cmd[8] = ADV_MOD_TURBO_QPSK;
|
||||
else
|
||||
cmd[8] = ADV_MOD_DVB_QPSK;
|
||||
break;
|
||||
case PSK_8: /* PSK_8 is for compatibility with DN */
|
||||
cmd[8] = ADV_MOD_TURBO_8PSK;
|
||||
|
@ -230,7 +230,7 @@ static int gp8psk_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
||||
|
||||
static int gp8psk_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
adap->fe = gp8psk_fe_attach(adap->dev);
|
||||
adap->fe_adap[0].fe = gp8psk_fe_attach(adap->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -268,6 +268,8 @@ static struct dvb_usb_device_properties gp8psk_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.streaming_ctrl = gp8psk_streaming_ctrl,
|
||||
.frontend_attach = gp8psk_frontend_attach,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
@ -281,6 +283,7 @@ static struct dvb_usb_device_properties gp8psk_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
}
|
||||
},
|
||||
.power_ctrl = gp8psk_power_ctrl,
|
||||
|
651
drivers/media/dvb/dvb-usb/it913x.c
Normal file
651
drivers/media/dvb/dvb-usb/it913x.c
Normal file
@ -0,0 +1,651 @@
|
||||
/* DVB USB compliant linux driver for IT9137
|
||||
*
|
||||
* Copyright (C) 2011 Malcolm Priestley (tvboxspy@gmail.com)
|
||||
* IT9137 (C) ITE Tech Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License Version 2, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*
|
||||
* see Documentation/dvb/README.dvb-usb for more information
|
||||
* see Documentation/dvb/it9137.txt for firmware information
|
||||
*
|
||||
*/
|
||||
#define DVB_USB_LOG_PREFIX "it913x"
|
||||
|
||||
#include <linux/usb.h>
|
||||
#include <linux/usb/input.h>
|
||||
#include <media/rc-core.h>
|
||||
|
||||
#include "dvb-usb.h"
|
||||
#include "it913x-fe.h"
|
||||
|
||||
/* debug */
|
||||
static int dvb_usb_it913x_debug;
|
||||
#define l_dprintk(var, level, args...) do { \
|
||||
if ((var >= level)) \
|
||||
printk(KERN_DEBUG DVB_USB_LOG_PREFIX ": " args); \
|
||||
} while (0)
|
||||
|
||||
#define deb_info(level, args...) l_dprintk(dvb_usb_it913x_debug, level, args)
|
||||
#define debug_data_snipet(level, name, p) \
|
||||
deb_info(level, name" (%02x%02x%02x%02x%02x%02x%02x%02x)", \
|
||||
*p, *(p+1), *(p+2), *(p+3), *(p+4), \
|
||||
*(p+5), *(p+6), *(p+7));
|
||||
|
||||
|
||||
module_param_named(debug, dvb_usb_it913x_debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))."
|
||||
DVB_USB_DEBUG_STATUS);
|
||||
|
||||
static int pid_filter;
|
||||
module_param_named(pid, pid_filter, int, 0644);
|
||||
MODULE_PARM_DESC(pid, "set default 0=on 1=off");
|
||||
|
||||
int cmd_counter;
|
||||
|
||||
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
|
||||
|
||||
struct it913x_state {
|
||||
u8 id;
|
||||
};
|
||||
|
||||
static int it913x_bulk_write(struct usb_device *dev,
|
||||
u8 *snd, int len, u8 pipe)
|
||||
{
|
||||
int ret, actual_l;
|
||||
|
||||
ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, pipe),
|
||||
snd, len , &actual_l, 100);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int it913x_bulk_read(struct usb_device *dev,
|
||||
u8 *rev, int len, u8 pipe)
|
||||
{
|
||||
int ret, actual_l;
|
||||
|
||||
ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, pipe),
|
||||
rev, len , &actual_l, 200);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u16 check_sum(u8 *p, u8 len)
|
||||
{
|
||||
u16 sum = 0;
|
||||
u8 i = 1;
|
||||
while (i < len)
|
||||
sum += (i++ & 1) ? (*p++) << 8 : *p++;
|
||||
return ~sum;
|
||||
}
|
||||
|
||||
static int it913x_io(struct usb_device *udev, u8 mode, u8 pro,
|
||||
u8 cmd, u32 reg, u8 addr, u8 *data, u8 len)
|
||||
{
|
||||
int ret = 0, i, buf_size = 1;
|
||||
u8 *buff;
|
||||
u8 rlen;
|
||||
u16 chk_sum;
|
||||
|
||||
buff = kzalloc(256, GFP_KERNEL);
|
||||
if (!buff) {
|
||||
info("USB Buffer Failed");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
buff[buf_size++] = pro;
|
||||
buff[buf_size++] = cmd;
|
||||
buff[buf_size++] = cmd_counter;
|
||||
|
||||
switch (mode) {
|
||||
case READ_LONG:
|
||||
case WRITE_LONG:
|
||||
buff[buf_size++] = len;
|
||||
buff[buf_size++] = 2;
|
||||
buff[buf_size++] = (reg >> 24);
|
||||
buff[buf_size++] = (reg >> 16) & 0xff;
|
||||
buff[buf_size++] = (reg >> 8) & 0xff;
|
||||
buff[buf_size++] = reg & 0xff;
|
||||
break;
|
||||
case READ_SHORT:
|
||||
buff[buf_size++] = addr;
|
||||
break;
|
||||
case WRITE_SHORT:
|
||||
buff[buf_size++] = len;
|
||||
buff[buf_size++] = addr;
|
||||
buff[buf_size++] = (reg >> 8) & 0xff;
|
||||
buff[buf_size++] = reg & 0xff;
|
||||
break;
|
||||
case READ_DATA:
|
||||
case WRITE_DATA:
|
||||
break;
|
||||
case WRITE_CMD:
|
||||
mode = 7;
|
||||
break;
|
||||
default:
|
||||
kfree(buff);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (mode & 1) {
|
||||
for (i = 0; i < len ; i++)
|
||||
buff[buf_size++] = data[i];
|
||||
}
|
||||
chk_sum = check_sum(&buff[1], buf_size);
|
||||
|
||||
buff[buf_size++] = chk_sum >> 8;
|
||||
buff[0] = buf_size;
|
||||
buff[buf_size++] = (chk_sum & 0xff);
|
||||
|
||||
ret = it913x_bulk_write(udev, buff, buf_size , 0x02);
|
||||
|
||||
ret |= it913x_bulk_read(udev, buff, (mode & 1) ?
|
||||
5 : len + 5 , 0x01);
|
||||
|
||||
rlen = (mode & 0x1) ? 0x1 : len;
|
||||
|
||||
if (mode & 1)
|
||||
ret |= buff[2];
|
||||
else
|
||||
memcpy(data, &buff[3], rlen);
|
||||
|
||||
cmd_counter++;
|
||||
|
||||
kfree(buff);
|
||||
|
||||
return (ret < 0) ? -ENODEV : 0;
|
||||
}
|
||||
|
||||
static int it913x_wr_reg(struct usb_device *udev, u8 pro, u32 reg , u8 data)
|
||||
{
|
||||
int ret;
|
||||
u8 b[1];
|
||||
b[0] = data;
|
||||
ret = it913x_io(udev, WRITE_LONG, pro,
|
||||
CMD_DEMOD_WRITE, reg, 0, b, sizeof(b));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int it913x_read_reg(struct usb_device *udev, u32 reg)
|
||||
{
|
||||
int ret;
|
||||
u8 data[1];
|
||||
|
||||
ret = it913x_io(udev, READ_LONG, DEV_0,
|
||||
CMD_DEMOD_READ, reg, 0, &data[0], 1);
|
||||
|
||||
return (ret < 0) ? ret : data[0];
|
||||
}
|
||||
|
||||
static u32 it913x_query(struct usb_device *udev, u8 pro)
|
||||
{
|
||||
int ret;
|
||||
u32 res = 0;
|
||||
u8 data[4];
|
||||
ret = it913x_io(udev, READ_LONG, pro, CMD_DEMOD_READ,
|
||||
0x1222, 0, &data[0], 1);
|
||||
if (data[0] == 0x1) {
|
||||
ret = it913x_io(udev, READ_SHORT, pro,
|
||||
CMD_QUERYINFO, 0, 0x1, &data[0], 4);
|
||||
res = (data[0] << 24) + (data[1] << 16) +
|
||||
(data[2] << 8) + data[3];
|
||||
}
|
||||
|
||||
return (ret < 0) ? 0 : res;
|
||||
}
|
||||
|
||||
static int it913x_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
||||
{
|
||||
int ret = 0;
|
||||
u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD;
|
||||
|
||||
if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
|
||||
return -EAGAIN;
|
||||
deb_info(1, "PID_C (%02x)", onoff);
|
||||
|
||||
if (!onoff)
|
||||
ret = it913x_wr_reg(adap->dev->udev, pro, PID_RST, 0x1);
|
||||
|
||||
mutex_unlock(&adap->dev->i2c_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int it913x_pid_filter(struct dvb_usb_adapter *adap,
|
||||
int index, u16 pid, int onoff)
|
||||
{
|
||||
struct usb_device *udev = adap->dev->udev;
|
||||
int ret = 0;
|
||||
u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD;
|
||||
|
||||
if (pid_filter > 0)
|
||||
return 0;
|
||||
|
||||
if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
|
||||
return -EAGAIN;
|
||||
deb_info(1, "PID_F (%02x)", onoff);
|
||||
if (onoff) {
|
||||
ret = it913x_wr_reg(udev, pro, PID_EN, 0x1);
|
||||
|
||||
ret |= it913x_wr_reg(udev, pro, PID_LSB, (u8)(pid & 0xff));
|
||||
|
||||
ret |= it913x_wr_reg(udev, pro, PID_MSB, (u8)(pid >> 8));
|
||||
|
||||
ret |= it913x_wr_reg(udev, pro, PID_INX_EN, (u8)onoff);
|
||||
|
||||
ret |= it913x_wr_reg(udev, pro, PID_INX, (u8)(index & 0x1f));
|
||||
|
||||
}
|
||||
|
||||
mutex_unlock(&adap->dev->i2c_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int it913x_return_status(struct usb_device *udev)
|
||||
{
|
||||
u32 firm = 0;
|
||||
|
||||
firm = it913x_query(udev, DEV_0);
|
||||
if (firm > 0)
|
||||
info("Firmware Version %d", firm);
|
||||
|
||||
return (firm > 0) ? firm : 0;
|
||||
}
|
||||
|
||||
static int it913x_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
|
||||
int num)
|
||||
{
|
||||
struct dvb_usb_device *d = i2c_get_adapdata(adap);
|
||||
static u8 data[256];
|
||||
int ret;
|
||||
u32 reg;
|
||||
u8 pro;
|
||||
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
|
||||
return -EAGAIN;
|
||||
|
||||
debug_data_snipet(1, "Message out", msg[0].buf);
|
||||
deb_info(2, "num of messages %d address %02x", num, msg[0].addr);
|
||||
|
||||
pro = (msg[0].addr & 0x2) ? DEV_0_DMOD : 0x0;
|
||||
pro |= (msg[0].addr & 0x20) ? DEV_1 : DEV_0;
|
||||
memcpy(data, msg[0].buf, msg[0].len);
|
||||
reg = (data[0] << 24) + (data[1] << 16) +
|
||||
(data[2] << 8) + data[3];
|
||||
if (num == 2) {
|
||||
ret = it913x_io(d->udev, READ_LONG, pro,
|
||||
CMD_DEMOD_READ, reg, 0, data, msg[1].len);
|
||||
memcpy(msg[1].buf, data, msg[1].len);
|
||||
} else
|
||||
ret = it913x_io(d->udev, WRITE_LONG, pro, CMD_DEMOD_WRITE,
|
||||
reg, 0, &data[4], msg[0].len - 4);
|
||||
|
||||
mutex_unlock(&d->i2c_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32 it913x_i2c_func(struct i2c_adapter *adapter)
|
||||
{
|
||||
return I2C_FUNC_I2C;
|
||||
}
|
||||
|
||||
static struct i2c_algorithm it913x_i2c_algo = {
|
||||
.master_xfer = it913x_i2c_xfer,
|
||||
.functionality = it913x_i2c_func,
|
||||
};
|
||||
|
||||
/* Callbacks for DVB USB */
|
||||
#define IT913X_POLL 250
|
||||
static int it913x_rc_query(struct dvb_usb_device *d)
|
||||
{
|
||||
u8 ibuf[4];
|
||||
int ret;
|
||||
u32 key;
|
||||
/* Avoid conflict with frontends*/
|
||||
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
|
||||
return -EAGAIN;
|
||||
|
||||
ret = it913x_io(d->udev, READ_LONG, PRO_LINK, CMD_IR_GET,
|
||||
0, 0, &ibuf[0], sizeof(ibuf));
|
||||
|
||||
if ((ibuf[2] + ibuf[3]) == 0xff) {
|
||||
key = ibuf[2];
|
||||
key += ibuf[0] << 8;
|
||||
deb_info(1, "INT Key =%08x", key);
|
||||
if (d->rc_dev != NULL)
|
||||
rc_keydown(d->rc_dev, key, 0);
|
||||
}
|
||||
mutex_unlock(&d->i2c_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
static int it913x_identify_state(struct usb_device *udev,
|
||||
struct dvb_usb_device_properties *props,
|
||||
struct dvb_usb_device_description **desc,
|
||||
int *cold)
|
||||
{
|
||||
int ret = 0, firm_no;
|
||||
u8 reg, adap, ep, tun0, tun1;
|
||||
|
||||
firm_no = it913x_return_status(udev);
|
||||
|
||||
ep = it913x_read_reg(udev, 0x49ac);
|
||||
adap = it913x_read_reg(udev, 0x49c5);
|
||||
tun0 = it913x_read_reg(udev, 0x49d0);
|
||||
info("No. Adapters=%x Endpoints=%x Tuner Type=%x", adap, ep, tun0);
|
||||
|
||||
if (firm_no > 0) {
|
||||
*cold = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (adap > 2) {
|
||||
tun1 = it913x_read_reg(udev, 0x49e0);
|
||||
ret = it913x_wr_reg(udev, DEV_0, GPIOH1_EN, 0x1);
|
||||
ret |= it913x_wr_reg(udev, DEV_0, GPIOH1_ON, 0x1);
|
||||
ret |= it913x_wr_reg(udev, DEV_0, GPIOH1_O, 0x1);
|
||||
msleep(50); /* Delay noticed reset cycle ? */
|
||||
ret |= it913x_wr_reg(udev, DEV_0, GPIOH1_O, 0x0);
|
||||
msleep(50);
|
||||
reg = it913x_read_reg(udev, GPIOH1_O);
|
||||
if (reg == 0) {
|
||||
ret |= it913x_wr_reg(udev, DEV_0, GPIOH1_O, 0x1);
|
||||
ret |= it913x_return_status(udev);
|
||||
if (ret != 0)
|
||||
ret = it913x_wr_reg(udev, DEV_0,
|
||||
GPIOH1_O, 0x0);
|
||||
}
|
||||
} else
|
||||
props->num_adapters = 1;
|
||||
|
||||
reg = it913x_read_reg(udev, IO_MUX_POWER_CLK);
|
||||
|
||||
ret |= it913x_wr_reg(udev, DEV_0, 0x4bfb, CHIP2_I2C_ADDR);
|
||||
|
||||
ret |= it913x_wr_reg(udev, DEV_0, CLK_O_EN, 0x1);
|
||||
|
||||
*cold = 1;
|
||||
|
||||
return (ret < 0) ? -ENODEV : 0;
|
||||
}
|
||||
|
||||
static int it913x_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
||||
{
|
||||
int ret = 0;
|
||||
u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD;
|
||||
|
||||
if (mutex_lock_interruptible(&adap->dev->i2c_mutex) < 0)
|
||||
return -EAGAIN;
|
||||
deb_info(1, "STM (%02x)", onoff);
|
||||
|
||||
if (!onoff)
|
||||
ret = it913x_wr_reg(adap->dev->udev, pro, PID_RST, 0x1);
|
||||
|
||||
|
||||
mutex_unlock(&adap->dev->i2c_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int it913x_download_firmware(struct usb_device *udev,
|
||||
const struct firmware *fw)
|
||||
{
|
||||
int ret = 0, i;
|
||||
u8 packet_size, dlen, tun1;
|
||||
u8 *fw_data;
|
||||
|
||||
packet_size = 0x29;
|
||||
|
||||
tun1 = it913x_read_reg(udev, 0x49e0);
|
||||
|
||||
ret = it913x_wr_reg(udev, DEV_0, I2C_CLK, I2C_CLK_100);
|
||||
|
||||
info("FRM Starting Firmware Download");
|
||||
/* This uses scatter write firmware headers follow */
|
||||
/* 03 XX 00 XX = chip number? */
|
||||
|
||||
for (i = 0; i < fw->size; i += packet_size) {
|
||||
if (i > 0)
|
||||
packet_size = 0x39;
|
||||
fw_data = (u8 *)(fw->data + i);
|
||||
dlen = ((i + packet_size) > fw->size)
|
||||
? (fw->size - i) : packet_size;
|
||||
ret |= it913x_io(udev, WRITE_DATA, DEV_0,
|
||||
CMD_SCATTER_WRITE, 0, 0, fw_data, dlen);
|
||||
udelay(1000);
|
||||
}
|
||||
|
||||
ret |= it913x_io(udev, WRITE_CMD, DEV_0,
|
||||
CMD_BOOT, 0, 0, NULL, 0);
|
||||
|
||||
msleep(100);
|
||||
|
||||
if (ret < 0)
|
||||
info("FRM Firmware Download Failed (%04x)" , ret);
|
||||
else
|
||||
info("FRM Firmware Download Completed - Resetting Device");
|
||||
|
||||
ret |= it913x_return_status(udev);
|
||||
|
||||
msleep(30);
|
||||
|
||||
ret |= it913x_wr_reg(udev, DEV_0, I2C_CLK, I2C_CLK_400);
|
||||
|
||||
/* Tuner function */
|
||||
ret |= it913x_wr_reg(udev, DEV_0_DMOD , 0xec4c, 0xa0);
|
||||
|
||||
ret |= it913x_wr_reg(udev, DEV_0, PADODPU, 0x0);
|
||||
ret |= it913x_wr_reg(udev, DEV_0, AGC_O_D, 0x0);
|
||||
if (tun1 > 0) {
|
||||
ret |= it913x_wr_reg(udev, DEV_1, PADODPU, 0x0);
|
||||
ret |= it913x_wr_reg(udev, DEV_1, AGC_O_D, 0x0);
|
||||
}
|
||||
|
||||
return (ret < 0) ? -ENODEV : 0;
|
||||
}
|
||||
|
||||
static int it913x_name(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
const char *desc = adap->dev->desc->name;
|
||||
char *fe_name[] = {"_1", "_2", "_3", "_4"};
|
||||
char *name = adap->fe_adap[0].fe->ops.info.name;
|
||||
|
||||
strlcpy(name, desc, 128);
|
||||
strlcat(name, fe_name[adap->id], 128);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int it913x_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
struct usb_device *udev = adap->dev->udev;
|
||||
int ret = 0;
|
||||
u8 adf = it913x_read_reg(udev, IO_MUX_POWER_CLK);
|
||||
u8 adap_addr = I2C_BASE_ADDR + (adap->id << 5);
|
||||
u16 ep_size = adap->props.fe[0].stream.u.bulk.buffersize;
|
||||
|
||||
adap->fe_adap[0].fe = dvb_attach(it913x_fe_attach,
|
||||
&adap->dev->i2c_adap, adap_addr, adf, IT9137);
|
||||
|
||||
if (adap->id == 0 && adap->fe_adap[0].fe) {
|
||||
ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2_SW_RST, 0x1);
|
||||
ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF2_SW_RST, 0x1);
|
||||
ret = it913x_wr_reg(udev, DEV_0, EP0_TX_EN, 0x0f);
|
||||
ret = it913x_wr_reg(udev, DEV_0, EP0_TX_NAK, 0x1b);
|
||||
ret = it913x_wr_reg(udev, DEV_0, EP0_TX_EN, 0x2f);
|
||||
ret = it913x_wr_reg(udev, DEV_0, EP4_TX_LEN_LSB,
|
||||
ep_size & 0xff);
|
||||
ret = it913x_wr_reg(udev, DEV_0, EP4_TX_LEN_MSB, ep_size >> 8);
|
||||
ret = it913x_wr_reg(udev, DEV_0, EP4_MAX_PKT, 0x80);
|
||||
} else if (adap->id == 1 && adap->fe_adap[0].fe) {
|
||||
ret = it913x_wr_reg(udev, DEV_0, EP0_TX_EN, 0x6f);
|
||||
ret = it913x_wr_reg(udev, DEV_0, EP5_TX_LEN_LSB,
|
||||
ep_size & 0xff);
|
||||
ret = it913x_wr_reg(udev, DEV_0, EP5_TX_LEN_MSB, ep_size >> 8);
|
||||
ret = it913x_wr_reg(udev, DEV_0, EP5_MAX_PKT, 0x80);
|
||||
ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF2_EN, 0x1);
|
||||
ret = it913x_wr_reg(udev, DEV_1_DMOD, MP2IF_SERIAL, 0x1);
|
||||
ret = it913x_wr_reg(udev, DEV_1, TOP_HOSTB_SER_MODE, 0x1);
|
||||
ret = it913x_wr_reg(udev, DEV_0_DMOD, TSIS_ENABLE, 0x1);
|
||||
ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2_SW_RST, 0x0);
|
||||
ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF2_SW_RST, 0x0);
|
||||
ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF2_HALF_PSB, 0x0);
|
||||
ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF_STOP_EN, 0x1);
|
||||
ret = it913x_wr_reg(udev, DEV_1_DMOD, MPEG_FULL_SPEED, 0x0);
|
||||
ret = it913x_wr_reg(udev, DEV_1_DMOD, MP2IF_STOP_EN, 0x0);
|
||||
} else
|
||||
return -ENODEV;
|
||||
|
||||
ret = it913x_name(adap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* DVB USB Driver */
|
||||
static struct dvb_usb_device_properties it913x_properties;
|
||||
|
||||
static int it913x_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
cmd_counter = 0;
|
||||
if (0 == dvb_usb_device_init(intf, &it913x_properties,
|
||||
THIS_MODULE, NULL, adapter_nr)) {
|
||||
info("DEV registering device driver");
|
||||
return 0;
|
||||
}
|
||||
|
||||
info("DEV it913x Error");
|
||||
return -ENODEV;
|
||||
|
||||
}
|
||||
|
||||
static struct usb_device_id it913x_table[] = {
|
||||
{ USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB499_2T_T09) },
|
||||
{} /* Terminating entry */
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(usb, it913x_table);
|
||||
|
||||
static struct dvb_usb_device_properties it913x_properties = {
|
||||
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
|
||||
.usb_ctrl = DEVICE_SPECIFIC,
|
||||
.download_firmware = it913x_download_firmware,
|
||||
.firmware = "dvb-usb-it9137-01.fw",
|
||||
.no_reconnect = 1,
|
||||
.size_of_priv = sizeof(struct it913x_state),
|
||||
.num_adapters = 2,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.caps = DVB_USB_ADAP_HAS_PID_FILTER|
|
||||
DVB_USB_ADAP_NEED_PID_FILTERING|
|
||||
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
.streaming_ctrl = it913x_streaming_ctrl,
|
||||
.pid_filter_count = 31,
|
||||
.pid_filter = it913x_pid_filter,
|
||||
.pid_filter_ctrl = it913x_pid_filter_ctrl,
|
||||
.frontend_attach = it913x_frontend_attach,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 10,
|
||||
.endpoint = 0x04,
|
||||
.u = {/* Keep Low if PID filter on */
|
||||
.bulk = {
|
||||
.buffersize = 3584,
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}},
|
||||
},
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.caps = DVB_USB_ADAP_HAS_PID_FILTER|
|
||||
DVB_USB_ADAP_NEED_PID_FILTERING|
|
||||
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
.streaming_ctrl = it913x_streaming_ctrl,
|
||||
.pid_filter_count = 31,
|
||||
.pid_filter = it913x_pid_filter,
|
||||
.pid_filter_ctrl = it913x_pid_filter_ctrl,
|
||||
.frontend_attach = it913x_frontend_attach,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 5,
|
||||
.endpoint = 0x05,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 3584,
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}},
|
||||
}
|
||||
},
|
||||
.identify_state = it913x_identify_state,
|
||||
.rc.core = {
|
||||
.protocol = RC_TYPE_NEC,
|
||||
.module_name = "it913x",
|
||||
.rc_query = it913x_rc_query,
|
||||
.rc_interval = IT913X_POLL,
|
||||
.allowed_protos = RC_TYPE_NEC,
|
||||
.rc_codes = RC_MAP_KWORLD_315U,
|
||||
},
|
||||
.i2c_algo = &it913x_i2c_algo,
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
{ "Kworld UB499-2T T09(IT9137)",
|
||||
{ &it913x_table[0], NULL },
|
||||
},
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
static struct usb_driver it913x_driver = {
|
||||
.name = "it913x",
|
||||
.probe = it913x_probe,
|
||||
.disconnect = dvb_usb_device_exit,
|
||||
.id_table = it913x_table,
|
||||
};
|
||||
|
||||
/* module stuff */
|
||||
static int __init it913x_module_init(void)
|
||||
{
|
||||
int result = usb_register(&it913x_driver);
|
||||
if (result) {
|
||||
err("usb_register failed. Error number %d", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit it913x_module_exit(void)
|
||||
{
|
||||
/* deregister this driver from the USB subsystem */
|
||||
usb_deregister(&it913x_driver);
|
||||
}
|
||||
|
||||
module_init(it913x_module_init);
|
||||
module_exit(it913x_module_exit);
|
||||
|
||||
MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>");
|
||||
MODULE_DESCRIPTION("it913x USB 2 Driver");
|
||||
MODULE_VERSION("1.06");
|
||||
MODULE_LICENSE("GPL");
|
@ -162,7 +162,7 @@ static int lme2510_usb_talk(struct dvb_usb_device *d,
|
||||
int ret = 0;
|
||||
|
||||
if (st->usb_buffer == NULL) {
|
||||
st->usb_buffer = kmalloc(512, GFP_KERNEL);
|
||||
st->usb_buffer = kmalloc(64, GFP_KERNEL);
|
||||
if (st->usb_buffer == NULL) {
|
||||
info("MEM Error no memory");
|
||||
return -ENOMEM;
|
||||
@ -175,8 +175,8 @@ static int lme2510_usb_talk(struct dvb_usb_device *d,
|
||||
if (ret < 0)
|
||||
return -EAGAIN;
|
||||
|
||||
/* the read/write capped at 512 */
|
||||
memcpy(buff, wbuf, (wlen > 512) ? 512 : wlen);
|
||||
/* the read/write capped at 64 */
|
||||
memcpy(buff, wbuf, (wlen < 64) ? wlen : 64);
|
||||
|
||||
ret |= usb_clear_halt(d->udev, usb_sndbulkpipe(d->udev, 0x01));
|
||||
|
||||
@ -186,8 +186,8 @@ static int lme2510_usb_talk(struct dvb_usb_device *d,
|
||||
|
||||
ret |= usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, 0x01));
|
||||
|
||||
ret |= lme2510_bulk_read(d->udev, buff, (rlen > 512) ?
|
||||
512 : rlen , 0x01);
|
||||
ret |= lme2510_bulk_read(d->udev, buff, (rlen < 64) ?
|
||||
rlen : 64 , 0x01);
|
||||
|
||||
if (rlen > 0)
|
||||
memcpy(rbuf, buff, rlen);
|
||||
@ -333,7 +333,7 @@ static int lme2510_int_read(struct dvb_usb_adapter *adap)
|
||||
if (lme_int->lme_urb == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
lme_int->buffer = usb_alloc_coherent(adap->dev->udev, 5000, GFP_ATOMIC,
|
||||
lme_int->buffer = usb_alloc_coherent(adap->dev->udev, 128, GFP_ATOMIC,
|
||||
&lme_int->lme_urb->transfer_dma);
|
||||
|
||||
if (lme_int->buffer == NULL)
|
||||
@ -343,10 +343,10 @@ static int lme2510_int_read(struct dvb_usb_adapter *adap)
|
||||
adap->dev->udev,
|
||||
usb_rcvintpipe(adap->dev->udev, 0xa),
|
||||
lme_int->buffer,
|
||||
4096,
|
||||
128,
|
||||
lme2510_int_response,
|
||||
adap,
|
||||
11);
|
||||
8);
|
||||
|
||||
lme_int->lme_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
|
||||
|
||||
@ -580,7 +580,7 @@ static int lme2510_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
|
||||
{
|
||||
struct dvb_usb_device *d = i2c_get_adapdata(adap);
|
||||
struct lme2510_state *st = d->priv;
|
||||
static u8 obuf[64], ibuf[512];
|
||||
static u8 obuf[64], ibuf[64];
|
||||
int i, read, read_o;
|
||||
u16 len;
|
||||
u8 gate = st->i2c_gate;
|
||||
@ -621,7 +621,7 @@ static int lme2510_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
|
||||
len = msg[i].len+3;
|
||||
}
|
||||
|
||||
if (lme2510_msg(d, obuf, len, ibuf, 512) < 0) {
|
||||
if (lme2510_msg(d, obuf, len, ibuf, 64) < 0) {
|
||||
deb_info(1, "i2c transfer failed.");
|
||||
return -EAGAIN;
|
||||
}
|
||||
@ -941,7 +941,7 @@ static int lme_name(struct dvb_usb_adapter *adap)
|
||||
const char *desc = adap->dev->desc->name;
|
||||
char *fe_name[] = {"", " LG TDQY-P001F", " SHARP:BS2F7HZ7395",
|
||||
" SHARP:BS2F7HZ0194"};
|
||||
char *name = adap->fe->ops.info.name;
|
||||
char *name = adap->fe_adap[0].fe->ops.info.name;
|
||||
|
||||
strlcpy(name, desc, 128);
|
||||
strlcat(name, fe_name[st->tuner_config], 128);
|
||||
@ -958,10 +958,10 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
st->i2c_talk_onoff = 1;
|
||||
|
||||
st->i2c_gate = 4;
|
||||
adap->fe = dvb_attach(tda10086_attach, &tda10086_config,
|
||||
adap->fe_adap[0].fe = dvb_attach(tda10086_attach, &tda10086_config,
|
||||
&adap->dev->i2c_adap);
|
||||
|
||||
if (adap->fe) {
|
||||
if (adap->fe_adap[0].fe) {
|
||||
info("TUN Found Frontend TDA10086");
|
||||
st->i2c_tuner_gate_w = 4;
|
||||
st->i2c_tuner_gate_r = 4;
|
||||
@ -975,9 +975,9 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
}
|
||||
|
||||
st->i2c_gate = 4;
|
||||
adap->fe = dvb_attach(stv0299_attach, &sharp_z0194_config,
|
||||
adap->fe_adap[0].fe = dvb_attach(stv0299_attach, &sharp_z0194_config,
|
||||
&adap->dev->i2c_adap);
|
||||
if (adap->fe) {
|
||||
if (adap->fe_adap[0].fe) {
|
||||
info("FE Found Stv0299");
|
||||
st->i2c_tuner_gate_w = 4;
|
||||
st->i2c_tuner_gate_r = 5;
|
||||
@ -991,9 +991,9 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
}
|
||||
|
||||
st->i2c_gate = 5;
|
||||
adap->fe = dvb_attach(stv0288_attach, &lme_config,
|
||||
adap->fe_adap[0].fe = dvb_attach(stv0288_attach, &lme_config,
|
||||
&adap->dev->i2c_adap);
|
||||
if (adap->fe) {
|
||||
if (adap->fe_adap[0].fe) {
|
||||
info("FE Found Stv0288");
|
||||
st->i2c_tuner_gate_w = 4;
|
||||
st->i2c_tuner_gate_r = 5;
|
||||
@ -1010,15 +1010,15 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
|
||||
|
||||
end: if (ret) {
|
||||
if (adap->fe) {
|
||||
dvb_frontend_detach(adap->fe);
|
||||
adap->fe = NULL;
|
||||
if (adap->fe_adap[0].fe) {
|
||||
dvb_frontend_detach(adap->fe_adap[0].fe);
|
||||
adap->fe_adap[0].fe = NULL;
|
||||
}
|
||||
adap->dev->props.rc.core.rc_codes = NULL;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
adap->fe->ops.set_voltage = dm04_lme2510_set_voltage;
|
||||
adap->fe_adap[0].fe->ops.set_voltage = dm04_lme2510_set_voltage;
|
||||
ret = lme_name(adap);
|
||||
return ret;
|
||||
}
|
||||
@ -1031,17 +1031,17 @@ static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap)
|
||||
|
||||
switch (st->tuner_config) {
|
||||
case TUNER_LG:
|
||||
if (dvb_attach(tda826x_attach, adap->fe, 0xc0,
|
||||
if (dvb_attach(tda826x_attach, adap->fe_adap[0].fe, 0xc0,
|
||||
&adap->dev->i2c_adap, 1))
|
||||
ret = st->tuner_config;
|
||||
break;
|
||||
case TUNER_S7395:
|
||||
if (dvb_attach(ix2505v_attach , adap->fe, &lme_tuner,
|
||||
if (dvb_attach(ix2505v_attach , adap->fe_adap[0].fe, &lme_tuner,
|
||||
&adap->dev->i2c_adap))
|
||||
ret = st->tuner_config;
|
||||
break;
|
||||
case TUNER_S0194:
|
||||
if (dvb_attach(dvb_pll_attach , adap->fe, 0xc0,
|
||||
if (dvb_attach(dvb_pll_attach , adap->fe_adap[0].fe, 0xc0,
|
||||
&adap->dev->i2c_adap, DVB_PLL_OPERA1))
|
||||
ret = st->tuner_config;
|
||||
break;
|
||||
@ -1145,6 +1145,8 @@ static struct dvb_usb_device_properties lme2510_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.caps = DVB_USB_ADAP_HAS_PID_FILTER|
|
||||
DVB_USB_ADAP_NEED_PID_FILTERING|
|
||||
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
@ -1166,6 +1168,7 @@ static struct dvb_usb_device_properties lme2510_properties = {
|
||||
}
|
||||
}
|
||||
}
|
||||
}},
|
||||
}
|
||||
},
|
||||
.rc.core = {
|
||||
@ -1193,6 +1196,8 @@ static struct dvb_usb_device_properties lme2510c_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.caps = DVB_USB_ADAP_HAS_PID_FILTER|
|
||||
DVB_USB_ADAP_NEED_PID_FILTERING|
|
||||
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
@ -1214,6 +1219,7 @@ static struct dvb_usb_device_properties lme2510c_properties = {
|
||||
}
|
||||
}
|
||||
}
|
||||
}},
|
||||
}
|
||||
},
|
||||
.rc.core = {
|
||||
@ -1241,7 +1247,7 @@ static void *lme2510_exit_int(struct dvb_usb_device *d)
|
||||
void *buffer = NULL;
|
||||
|
||||
if (adap != NULL) {
|
||||
lme2510_kill_urb(&adap->stream);
|
||||
lme2510_kill_urb(&adap->fe_adap[0].stream);
|
||||
adap->feedcount = 0;
|
||||
}
|
||||
|
||||
@ -1255,7 +1261,7 @@ static void *lme2510_exit_int(struct dvb_usb_device *d)
|
||||
|
||||
if (st->lme_urb != NULL) {
|
||||
usb_kill_urb(st->lme_urb);
|
||||
usb_free_coherent(d->udev, 5000, st->buffer,
|
||||
usb_free_coherent(d->udev, 128, st->buffer,
|
||||
st->lme_urb->transfer_dma);
|
||||
info("Interrupt Service Stopped");
|
||||
}
|
||||
@ -1306,5 +1312,5 @@ module_exit(lme2510_module_exit);
|
||||
|
||||
MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>");
|
||||
MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0");
|
||||
MODULE_VERSION("1.88");
|
||||
MODULE_VERSION("1.90");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -86,12 +86,12 @@ static int m920x_init(struct dvb_usb_device *d, struct m920x_inits *rc_seq)
|
||||
}
|
||||
|
||||
for (i = 0; i < d->props.num_adapters; i++)
|
||||
flags |= d->adapter[i].props.caps;
|
||||
flags |= d->adapter[i].props.fe[0].caps;
|
||||
|
||||
/* Some devices(Dposh) might crash if we attempt touch at all. */
|
||||
if (flags & DVB_USB_ADAP_HAS_PID_FILTER) {
|
||||
for (i = 0; i < d->props.num_adapters; i++) {
|
||||
epi = d->adapter[i].props.stream.endpoint - 0x81;
|
||||
epi = d->adapter[i].props.fe[0].stream.endpoint - 0x81;
|
||||
|
||||
if (epi < 0 || epi >= M9206_MAX_ADAPTERS) {
|
||||
printk(KERN_INFO "m920x: Unexpected adapter endpoint!\n");
|
||||
@ -292,7 +292,7 @@ static int m920x_update_filters(struct dvb_usb_adapter *adap)
|
||||
struct m920x_state *m = adap->dev->priv;
|
||||
int enabled = m->filtering_enabled[adap->id];
|
||||
int i, ret = 0, filter = 0;
|
||||
int ep = adap->props.stream.endpoint;
|
||||
int ep = adap->props.fe[0].stream.endpoint;
|
||||
|
||||
for (i = 0; i < M9206_MAX_FILTERS; i++)
|
||||
if (m->filters[adap->id][i] == 8192)
|
||||
@ -501,9 +501,10 @@ static int m920x_mt352_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
deb("%s\n",__func__);
|
||||
|
||||
if ((adap->fe = dvb_attach(mt352_attach,
|
||||
&m920x_mt352_config,
|
||||
&adap->dev->i2c_adap)) == NULL)
|
||||
adap->fe_adap[0].fe = dvb_attach(mt352_attach,
|
||||
&m920x_mt352_config,
|
||||
&adap->dev->i2c_adap);
|
||||
if ((adap->fe_adap[0].fe) == NULL)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
@ -513,9 +514,10 @@ static int m920x_tda10046_08_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
deb("%s\n",__func__);
|
||||
|
||||
if ((adap->fe = dvb_attach(tda10046_attach,
|
||||
&m920x_tda10046_08_config,
|
||||
&adap->dev->i2c_adap)) == NULL)
|
||||
adap->fe_adap[0].fe = dvb_attach(tda10046_attach,
|
||||
&m920x_tda10046_08_config,
|
||||
&adap->dev->i2c_adap);
|
||||
if ((adap->fe_adap[0].fe) == NULL)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
@ -525,9 +527,10 @@ static int m920x_tda10046_0b_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
deb("%s\n",__func__);
|
||||
|
||||
if ((adap->fe = dvb_attach(tda10046_attach,
|
||||
&m920x_tda10046_0b_config,
|
||||
&adap->dev->i2c_adap)) == NULL)
|
||||
adap->fe_adap[0].fe = dvb_attach(tda10046_attach,
|
||||
&m920x_tda10046_0b_config,
|
||||
&adap->dev->i2c_adap);
|
||||
if ((adap->fe_adap[0].fe) == NULL)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
@ -537,7 +540,7 @@ static int m920x_qt1010_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
deb("%s\n",__func__);
|
||||
|
||||
if (dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap, &m920x_qt1010_config) == NULL)
|
||||
if (dvb_attach(qt1010_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap, &m920x_qt1010_config) == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
@ -547,7 +550,7 @@ static int m920x_tda8275_60_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
deb("%s\n",__func__);
|
||||
|
||||
if (dvb_attach(tda827x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, NULL) == NULL)
|
||||
if (dvb_attach(tda827x_attach, adap->fe_adap[0].fe, 0x60, &adap->dev->i2c_adap, NULL) == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
@ -557,7 +560,7 @@ static int m920x_tda8275_61_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
deb("%s\n",__func__);
|
||||
|
||||
if (dvb_attach(tda827x_attach, adap->fe, 0x61, &adap->dev->i2c_adap, NULL) == NULL)
|
||||
if (dvb_attach(tda827x_attach, adap->fe_adap[0].fe, 0x61, &adap->dev->i2c_adap, NULL) == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
@ -565,7 +568,7 @@ static int m920x_tda8275_61_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
|
||||
static int m920x_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
dvb_attach(simple_tuner_attach, adap->fe,
|
||||
dvb_attach(simple_tuner_attach, adap->fe_adap[0].fe,
|
||||
&adap->dev->i2c_adap, 0x61,
|
||||
TUNER_PHILIPS_FMD1216ME_MK3);
|
||||
return 0;
|
||||
@ -807,6 +810,9 @@ static struct dvb_usb_device_properties megasky_properties = {
|
||||
.identify_state = m920x_identify_state,
|
||||
.num_adapters = 1,
|
||||
.adapter = {{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
|
||||
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
|
||||
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
|
||||
@ -827,6 +833,7 @@ static struct dvb_usb_device_properties megasky_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
}},
|
||||
.i2c_algo = &m920x_i2c_algo,
|
||||
|
||||
@ -851,6 +858,9 @@ static struct dvb_usb_device_properties digivox_mini_ii_properties = {
|
||||
.identify_state = m920x_identify_state,
|
||||
.num_adapters = 1,
|
||||
.adapter = {{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
|
||||
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
|
||||
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
|
||||
@ -871,6 +881,7 @@ static struct dvb_usb_device_properties digivox_mini_ii_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
}},
|
||||
.i2c_algo = &m920x_i2c_algo,
|
||||
|
||||
@ -910,6 +921,9 @@ static struct dvb_usb_device_properties tvwalkertwin_properties = {
|
||||
.identify_state = m920x_identify_state,
|
||||
.num_adapters = 2,
|
||||
.adapter = {{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
|
||||
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
|
||||
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
|
||||
@ -929,7 +943,11 @@ static struct dvb_usb_device_properties tvwalkertwin_properties = {
|
||||
.buffersize = 512,
|
||||
}
|
||||
}
|
||||
}},
|
||||
}},{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
|
||||
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
|
||||
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
|
||||
@ -949,6 +967,7 @@ static struct dvb_usb_device_properties tvwalkertwin_properties = {
|
||||
.buffersize = 512,
|
||||
}
|
||||
}
|
||||
}},
|
||||
},
|
||||
}},
|
||||
.i2c_algo = &m920x_i2c_algo,
|
||||
@ -974,6 +993,8 @@ static struct dvb_usb_device_properties dposh_properties = {
|
||||
.identify_state = m920x_identify_state,
|
||||
.num_adapters = 1,
|
||||
.adapter = {{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
/* Hardware pid filters don't work with this device/firmware */
|
||||
|
||||
.frontend_attach = m920x_mt352_frontend_attach,
|
||||
@ -989,6 +1010,7 @@ static struct dvb_usb_device_properties dposh_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
}},
|
||||
.i2c_algo = &m920x_i2c_algo,
|
||||
|
||||
@ -1019,6 +1041,9 @@ static struct dvb_usb_device_properties pinnacle_pctv310e_properties = {
|
||||
.identify_state = m920x_identify_state,
|
||||
.num_adapters = 1,
|
||||
.adapter = {{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
|
||||
.caps = DVB_USB_ADAP_HAS_PID_FILTER |
|
||||
DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
|
||||
@ -1041,6 +1066,7 @@ static struct dvb_usb_device_properties pinnacle_pctv310e_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
} },
|
||||
.i2c_algo = &m920x_i2c_algo,
|
||||
|
||||
|
763
drivers/media/dvb/dvb-usb/mxl111sf-gpio.c
Normal file
763
drivers/media/dvb/dvb-usb/mxl111sf-gpio.c
Normal file
@ -0,0 +1,763 @@
|
||||
/*
|
||||
* mxl111sf-gpio.c - driver for the MaxLinear MXL111SF
|
||||
*
|
||||
* Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "mxl111sf-gpio.h"
|
||||
#include "mxl111sf-i2c.h"
|
||||
#include "mxl111sf.h"
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#define MXL_GPIO_MUX_REG_0 0x84
|
||||
#define MXL_GPIO_MUX_REG_1 0x89
|
||||
#define MXL_GPIO_MUX_REG_2 0x82
|
||||
|
||||
#define MXL_GPIO_DIR_INPUT 0
|
||||
#define MXL_GPIO_DIR_OUTPUT 1
|
||||
|
||||
|
||||
static int mxl111sf_set_gpo_state(struct mxl111sf_state *state, u8 pin, u8 val)
|
||||
{
|
||||
int ret;
|
||||
u8 tmp;
|
||||
|
||||
mxl_debug_adv("(%d, %d)", pin, val);
|
||||
|
||||
if ((pin > 0) && (pin < 8)) {
|
||||
ret = mxl111sf_read_reg(state, 0x19, &tmp);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
tmp &= ~(1 << (pin - 1));
|
||||
tmp |= (val << (pin - 1));
|
||||
ret = mxl111sf_write_reg(state, 0x19, tmp);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
} else if (pin <= 10) {
|
||||
if (pin == 0)
|
||||
pin += 7;
|
||||
ret = mxl111sf_read_reg(state, 0x30, &tmp);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
tmp &= ~(1 << (pin - 3));
|
||||
tmp |= (val << (pin - 3));
|
||||
ret = mxl111sf_write_reg(state, 0x30, tmp);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
} else
|
||||
ret = -EINVAL;
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mxl111sf_get_gpi_state(struct mxl111sf_state *state, u8 pin, u8 *val)
|
||||
{
|
||||
int ret;
|
||||
u8 tmp;
|
||||
|
||||
mxl_debug("(0x%02x)", pin);
|
||||
|
||||
*val = 0;
|
||||
|
||||
switch (pin) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
ret = mxl111sf_read_reg(state, 0x23, &tmp);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
*val = (tmp >> (pin + 4)) & 0x01;
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
ret = mxl111sf_read_reg(state, 0x2f, &tmp);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
*val = (tmp >> pin) & 0x01;
|
||||
break;
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
ret = mxl111sf_read_reg(state, 0x22, &tmp);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
*val = (tmp >> (pin - 3)) & 0x01;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL; /* invalid pin */
|
||||
}
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct mxl_gpio_cfg {
|
||||
u8 pin;
|
||||
u8 dir;
|
||||
u8 val;
|
||||
};
|
||||
|
||||
static int mxl111sf_config_gpio_pins(struct mxl111sf_state *state,
|
||||
struct mxl_gpio_cfg *gpio_cfg)
|
||||
{
|
||||
int ret;
|
||||
u8 tmp;
|
||||
|
||||
mxl_debug_adv("(%d, %d)", gpio_cfg->pin, gpio_cfg->dir);
|
||||
|
||||
switch (gpio_cfg->pin) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
ret = mxl111sf_read_reg(state, MXL_GPIO_MUX_REG_0, &tmp);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
tmp &= ~(1 << (gpio_cfg->pin + 4));
|
||||
tmp |= (gpio_cfg->dir << (gpio_cfg->pin + 4));
|
||||
ret = mxl111sf_write_reg(state, MXL_GPIO_MUX_REG_0, tmp);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
ret = mxl111sf_read_reg(state, MXL_GPIO_MUX_REG_1, &tmp);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
tmp &= ~(1 << gpio_cfg->pin);
|
||||
tmp |= (gpio_cfg->dir << gpio_cfg->pin);
|
||||
ret = mxl111sf_write_reg(state, MXL_GPIO_MUX_REG_1, tmp);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
break;
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
ret = mxl111sf_read_reg(state, MXL_GPIO_MUX_REG_2, &tmp);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
tmp &= ~(1 << (gpio_cfg->pin - 3));
|
||||
tmp |= (gpio_cfg->dir << (gpio_cfg->pin - 3));
|
||||
ret = mxl111sf_write_reg(state, MXL_GPIO_MUX_REG_2, tmp);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL; /* invalid pin */
|
||||
}
|
||||
|
||||
ret = (MXL_GPIO_DIR_OUTPUT == gpio_cfg->dir) ?
|
||||
mxl111sf_set_gpo_state(state,
|
||||
gpio_cfg->pin, gpio_cfg->val) :
|
||||
mxl111sf_get_gpi_state(state,
|
||||
gpio_cfg->pin, &gpio_cfg->val);
|
||||
mxl_fail(ret);
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mxl111sf_hw_do_set_gpio(struct mxl111sf_state *state,
|
||||
int gpio, int direction, int val)
|
||||
{
|
||||
struct mxl_gpio_cfg gpio_config = {
|
||||
.pin = gpio,
|
||||
.dir = direction,
|
||||
.val = val,
|
||||
};
|
||||
|
||||
mxl_debug("(%d, %d, %d)", gpio, direction, val);
|
||||
|
||||
return mxl111sf_config_gpio_pins(state, &gpio_config);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#define PIN_MUX_MPEG_MODE_MASK 0x40 /* 0x17 <6> */
|
||||
#define PIN_MUX_MPEG_PAR_EN_MASK 0x01 /* 0x18 <0> */
|
||||
#define PIN_MUX_MPEG_SER_EN_MASK 0x02 /* 0x18 <1> */
|
||||
#define PIN_MUX_MPG_IN_MUX_MASK 0x80 /* 0x3D <7> */
|
||||
#define PIN_MUX_BT656_ENABLE_MASK 0x04 /* 0x12 <2> */
|
||||
#define PIN_MUX_I2S_ENABLE_MASK 0x40 /* 0x15 <6> */
|
||||
#define PIN_MUX_SPI_MODE_MASK 0x10 /* 0x3D <4> */
|
||||
#define PIN_MUX_MCLK_EN_CTRL_MASK 0x10 /* 0x82 <4> */
|
||||
#define PIN_MUX_MPSYN_EN_CTRL_MASK 0x20 /* 0x82 <5> */
|
||||
#define PIN_MUX_MDVAL_EN_CTRL_MASK 0x40 /* 0x82 <6> */
|
||||
#define PIN_MUX_MPERR_EN_CTRL_MASK 0x80 /* 0x82 <7> */
|
||||
#define PIN_MUX_MDAT_EN_0_MASK 0x10 /* 0x84 <4> */
|
||||
#define PIN_MUX_MDAT_EN_1_MASK 0x20 /* 0x84 <5> */
|
||||
#define PIN_MUX_MDAT_EN_2_MASK 0x40 /* 0x84 <6> */
|
||||
#define PIN_MUX_MDAT_EN_3_MASK 0x80 /* 0x84 <7> */
|
||||
#define PIN_MUX_MDAT_EN_4_MASK 0x10 /* 0x89 <4> */
|
||||
#define PIN_MUX_MDAT_EN_5_MASK 0x20 /* 0x89 <5> */
|
||||
#define PIN_MUX_MDAT_EN_6_MASK 0x40 /* 0x89 <6> */
|
||||
#define PIN_MUX_MDAT_EN_7_MASK 0x80 /* 0x89 <7> */
|
||||
|
||||
int mxl111sf_config_pin_mux_modes(struct mxl111sf_state *state,
|
||||
enum mxl111sf_mux_config pin_mux_config)
|
||||
{
|
||||
u8 r12, r15, r17, r18, r3D, r82, r84, r89;
|
||||
int ret;
|
||||
|
||||
mxl_debug("(%d)", pin_mux_config);
|
||||
|
||||
ret = mxl111sf_read_reg(state, 0x17, &r17);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
ret = mxl111sf_read_reg(state, 0x18, &r18);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
ret = mxl111sf_read_reg(state, 0x12, &r12);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
ret = mxl111sf_read_reg(state, 0x15, &r15);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
ret = mxl111sf_read_reg(state, 0x82, &r82);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
ret = mxl111sf_read_reg(state, 0x84, &r84);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
ret = mxl111sf_read_reg(state, 0x89, &r89);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
ret = mxl111sf_read_reg(state, 0x3D, &r3D);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
switch (pin_mux_config) {
|
||||
case PIN_MUX_TS_OUT_PARALLEL:
|
||||
/* mpeg_mode = 1 */
|
||||
r17 |= PIN_MUX_MPEG_MODE_MASK;
|
||||
/* mpeg_par_en = 1 */
|
||||
r18 |= PIN_MUX_MPEG_PAR_EN_MASK;
|
||||
/* mpeg_ser_en = 0 */
|
||||
r18 &= ~PIN_MUX_MPEG_SER_EN_MASK;
|
||||
/* mpg_in_mux = 0 */
|
||||
r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
|
||||
/* bt656_enable = 0 */
|
||||
r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
|
||||
/* i2s_enable = 0 */
|
||||
r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
|
||||
/* spi_mode = 0 */
|
||||
r3D &= ~PIN_MUX_SPI_MODE_MASK;
|
||||
/* mclk_en_ctrl = 1 */
|
||||
r82 |= PIN_MUX_MCLK_EN_CTRL_MASK;
|
||||
/* mperr_en_ctrl = 1 */
|
||||
r82 |= PIN_MUX_MPERR_EN_CTRL_MASK;
|
||||
/* mdval_en_ctrl = 1 */
|
||||
r82 |= PIN_MUX_MDVAL_EN_CTRL_MASK;
|
||||
/* mpsyn_en_ctrl = 1 */
|
||||
r82 |= PIN_MUX_MPSYN_EN_CTRL_MASK;
|
||||
/* mdat_en_ctrl[3:0] = 0xF */
|
||||
r84 |= 0xF0;
|
||||
/* mdat_en_ctrl[7:4] = 0xF */
|
||||
r89 |= 0xF0;
|
||||
break;
|
||||
case PIN_MUX_TS_OUT_SERIAL:
|
||||
/* mpeg_mode = 1 */
|
||||
r17 |= PIN_MUX_MPEG_MODE_MASK;
|
||||
/* mpeg_par_en = 0 */
|
||||
r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
|
||||
/* mpeg_ser_en = 1 */
|
||||
r18 |= PIN_MUX_MPEG_SER_EN_MASK;
|
||||
/* mpg_in_mux = 0 */
|
||||
r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
|
||||
/* bt656_enable = 0 */
|
||||
r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
|
||||
/* i2s_enable = 0 */
|
||||
r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
|
||||
/* spi_mode = 0 */
|
||||
r3D &= ~PIN_MUX_SPI_MODE_MASK;
|
||||
/* mclk_en_ctrl = 1 */
|
||||
r82 |= PIN_MUX_MCLK_EN_CTRL_MASK;
|
||||
/* mperr_en_ctrl = 1 */
|
||||
r82 |= PIN_MUX_MPERR_EN_CTRL_MASK;
|
||||
/* mdval_en_ctrl = 1 */
|
||||
r82 |= PIN_MUX_MDVAL_EN_CTRL_MASK;
|
||||
/* mpsyn_en_ctrl = 1 */
|
||||
r82 |= PIN_MUX_MPSYN_EN_CTRL_MASK;
|
||||
/* mdat_en_ctrl[3:0] = 0xF */
|
||||
r84 |= 0xF0;
|
||||
/* mdat_en_ctrl[7:4] = 0xF */
|
||||
r89 |= 0xF0;
|
||||
break;
|
||||
case PIN_MUX_GPIO_MODE:
|
||||
/* mpeg_mode = 0 */
|
||||
r17 &= ~PIN_MUX_MPEG_MODE_MASK;
|
||||
/* mpeg_par_en = 0 */
|
||||
r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
|
||||
/* mpeg_ser_en = 0 */
|
||||
r18 &= ~PIN_MUX_MPEG_SER_EN_MASK;
|
||||
/* mpg_in_mux = 0 */
|
||||
r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
|
||||
/* bt656_enable = 0 */
|
||||
r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
|
||||
/* i2s_enable = 0 */
|
||||
r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
|
||||
/* spi_mode = 0 */
|
||||
r3D &= ~PIN_MUX_SPI_MODE_MASK;
|
||||
/* mclk_en_ctrl = 0 */
|
||||
r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
|
||||
/* mperr_en_ctrl = 0 */
|
||||
r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
|
||||
/* mdval_en_ctrl = 0 */
|
||||
r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
|
||||
/* mpsyn_en_ctrl = 0 */
|
||||
r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
|
||||
/* mdat_en_ctrl[3:0] = 0x0 */
|
||||
r84 &= 0x0F;
|
||||
/* mdat_en_ctrl[7:4] = 0x0 */
|
||||
r89 &= 0x0F;
|
||||
break;
|
||||
case PIN_MUX_TS_SERIAL_IN_MODE_0:
|
||||
/* mpeg_mode = 0 */
|
||||
r17 &= ~PIN_MUX_MPEG_MODE_MASK;
|
||||
/* mpeg_par_en = 0 */
|
||||
r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
|
||||
/* mpeg_ser_en = 1 */
|
||||
r18 |= PIN_MUX_MPEG_SER_EN_MASK;
|
||||
/* mpg_in_mux = 0 */
|
||||
r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
|
||||
/* bt656_enable = 0 */
|
||||
r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
|
||||
/* i2s_enable = 0 */
|
||||
r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
|
||||
/* spi_mode = 0 */
|
||||
r3D &= ~PIN_MUX_SPI_MODE_MASK;
|
||||
/* mclk_en_ctrl = 0 */
|
||||
r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
|
||||
/* mperr_en_ctrl = 0 */
|
||||
r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
|
||||
/* mdval_en_ctrl = 0 */
|
||||
r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
|
||||
/* mpsyn_en_ctrl = 0 */
|
||||
r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
|
||||
/* mdat_en_ctrl[3:0] = 0x0 */
|
||||
r84 &= 0x0F;
|
||||
/* mdat_en_ctrl[7:4] = 0x0 */
|
||||
r89 &= 0x0F;
|
||||
break;
|
||||
case PIN_MUX_TS_SERIAL_IN_MODE_1:
|
||||
/* mpeg_mode = 0 */
|
||||
r17 &= ~PIN_MUX_MPEG_MODE_MASK;
|
||||
/* mpeg_par_en = 0 */
|
||||
r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
|
||||
/* mpeg_ser_en = 1 */
|
||||
r18 |= PIN_MUX_MPEG_SER_EN_MASK;
|
||||
/* mpg_in_mux = 1 */
|
||||
r3D |= PIN_MUX_MPG_IN_MUX_MASK;
|
||||
/* bt656_enable = 0 */
|
||||
r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
|
||||
/* i2s_enable = 0 */
|
||||
r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
|
||||
/* spi_mode = 0 */
|
||||
r3D &= ~PIN_MUX_SPI_MODE_MASK;
|
||||
/* mclk_en_ctrl = 0 */
|
||||
r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
|
||||
/* mperr_en_ctrl = 0 */
|
||||
r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
|
||||
/* mdval_en_ctrl = 0 */
|
||||
r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
|
||||
/* mpsyn_en_ctrl = 0 */
|
||||
r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
|
||||
/* mdat_en_ctrl[3:0] = 0x0 */
|
||||
r84 &= 0x0F;
|
||||
/* mdat_en_ctrl[7:4] = 0x0 */
|
||||
r89 &= 0x0F;
|
||||
break;
|
||||
case PIN_MUX_TS_SPI_IN_MODE_1:
|
||||
/* mpeg_mode = 0 */
|
||||
r17 &= ~PIN_MUX_MPEG_MODE_MASK;
|
||||
/* mpeg_par_en = 0 */
|
||||
r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
|
||||
/* mpeg_ser_en = 1 */
|
||||
r18 |= PIN_MUX_MPEG_SER_EN_MASK;
|
||||
/* mpg_in_mux = 1 */
|
||||
r3D |= PIN_MUX_MPG_IN_MUX_MASK;
|
||||
/* bt656_enable = 0 */
|
||||
r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
|
||||
/* i2s_enable = 1 */
|
||||
r15 |= PIN_MUX_I2S_ENABLE_MASK;
|
||||
/* spi_mode = 1 */
|
||||
r3D |= PIN_MUX_SPI_MODE_MASK;
|
||||
/* mclk_en_ctrl = 0 */
|
||||
r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
|
||||
/* mperr_en_ctrl = 0 */
|
||||
r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
|
||||
/* mdval_en_ctrl = 0 */
|
||||
r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
|
||||
/* mpsyn_en_ctrl = 0 */
|
||||
r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
|
||||
/* mdat_en_ctrl[3:0] = 0x0 */
|
||||
r84 &= 0x0F;
|
||||
/* mdat_en_ctrl[7:4] = 0x0 */
|
||||
r89 &= 0x0F;
|
||||
break;
|
||||
case PIN_MUX_TS_SPI_IN_MODE_0:
|
||||
/* mpeg_mode = 0 */
|
||||
r17 &= ~PIN_MUX_MPEG_MODE_MASK;
|
||||
/* mpeg_par_en = 0 */
|
||||
r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
|
||||
/* mpeg_ser_en = 1 */
|
||||
r18 |= PIN_MUX_MPEG_SER_EN_MASK;
|
||||
/* mpg_in_mux = 0 */
|
||||
r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
|
||||
/* bt656_enable = 0 */
|
||||
r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
|
||||
/* i2s_enable = 1 */
|
||||
r15 |= PIN_MUX_I2S_ENABLE_MASK;
|
||||
/* spi_mode = 1 */
|
||||
r3D |= PIN_MUX_SPI_MODE_MASK;
|
||||
/* mclk_en_ctrl = 0 */
|
||||
r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
|
||||
/* mperr_en_ctrl = 0 */
|
||||
r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
|
||||
/* mdval_en_ctrl = 0 */
|
||||
r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
|
||||
/* mpsyn_en_ctrl = 0 */
|
||||
r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
|
||||
/* mdat_en_ctrl[3:0] = 0x0 */
|
||||
r84 &= 0x0F;
|
||||
/* mdat_en_ctrl[7:4] = 0x0 */
|
||||
r89 &= 0x0F;
|
||||
break;
|
||||
case PIN_MUX_TS_PARALLEL_IN:
|
||||
/* mpeg_mode = 0 */
|
||||
r17 &= ~PIN_MUX_MPEG_MODE_MASK;
|
||||
/* mpeg_par_en = 1 */
|
||||
r18 |= PIN_MUX_MPEG_PAR_EN_MASK;
|
||||
/* mpeg_ser_en = 0 */
|
||||
r18 &= ~PIN_MUX_MPEG_SER_EN_MASK;
|
||||
/* mpg_in_mux = 0 */
|
||||
r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
|
||||
/* bt656_enable = 0 */
|
||||
r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
|
||||
/* i2s_enable = 0 */
|
||||
r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
|
||||
/* spi_mode = 0 */
|
||||
r3D &= ~PIN_MUX_SPI_MODE_MASK;
|
||||
/* mclk_en_ctrl = 0 */
|
||||
r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
|
||||
/* mperr_en_ctrl = 0 */
|
||||
r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
|
||||
/* mdval_en_ctrl = 0 */
|
||||
r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
|
||||
/* mpsyn_en_ctrl = 0 */
|
||||
r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
|
||||
/* mdat_en_ctrl[3:0] = 0x0 */
|
||||
r84 &= 0x0F;
|
||||
/* mdat_en_ctrl[7:4] = 0x0 */
|
||||
r89 &= 0x0F;
|
||||
break;
|
||||
case PIN_MUX_BT656_I2S_MODE:
|
||||
/* mpeg_mode = 0 */
|
||||
r17 &= ~PIN_MUX_MPEG_MODE_MASK;
|
||||
/* mpeg_par_en = 0 */
|
||||
r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
|
||||
/* mpeg_ser_en = 0 */
|
||||
r18 &= ~PIN_MUX_MPEG_SER_EN_MASK;
|
||||
/* mpg_in_mux = 0 */
|
||||
r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
|
||||
/* bt656_enable = 1 */
|
||||
r12 |= PIN_MUX_BT656_ENABLE_MASK;
|
||||
/* i2s_enable = 1 */
|
||||
r15 |= PIN_MUX_I2S_ENABLE_MASK;
|
||||
/* spi_mode = 0 */
|
||||
r3D &= ~PIN_MUX_SPI_MODE_MASK;
|
||||
/* mclk_en_ctrl = 0 */
|
||||
r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
|
||||
/* mperr_en_ctrl = 0 */
|
||||
r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
|
||||
/* mdval_en_ctrl = 0 */
|
||||
r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
|
||||
/* mpsyn_en_ctrl = 0 */
|
||||
r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
|
||||
/* mdat_en_ctrl[3:0] = 0x0 */
|
||||
r84 &= 0x0F;
|
||||
/* mdat_en_ctrl[7:4] = 0x0 */
|
||||
r89 &= 0x0F;
|
||||
break;
|
||||
case PIN_MUX_DEFAULT:
|
||||
default:
|
||||
/* mpeg_mode = 1 */
|
||||
r17 |= PIN_MUX_MPEG_MODE_MASK;
|
||||
/* mpeg_par_en = 0 */
|
||||
r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
|
||||
/* mpeg_ser_en = 0 */
|
||||
r18 &= ~PIN_MUX_MPEG_SER_EN_MASK;
|
||||
/* mpg_in_mux = 0 */
|
||||
r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
|
||||
/* bt656_enable = 0 */
|
||||
r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
|
||||
/* i2s_enable = 0 */
|
||||
r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
|
||||
/* spi_mode = 0 */
|
||||
r3D &= ~PIN_MUX_SPI_MODE_MASK;
|
||||
/* mclk_en_ctrl = 0 */
|
||||
r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
|
||||
/* mperr_en_ctrl = 0 */
|
||||
r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
|
||||
/* mdval_en_ctrl = 0 */
|
||||
r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
|
||||
/* mpsyn_en_ctrl = 0 */
|
||||
r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
|
||||
/* mdat_en_ctrl[3:0] = 0x0 */
|
||||
r84 &= 0x0F;
|
||||
/* mdat_en_ctrl[7:4] = 0x0 */
|
||||
r89 &= 0x0F;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = mxl111sf_write_reg(state, 0x17, r17);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
ret = mxl111sf_write_reg(state, 0x18, r18);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
ret = mxl111sf_write_reg(state, 0x12, r12);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
ret = mxl111sf_write_reg(state, 0x15, r15);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
ret = mxl111sf_write_reg(state, 0x82, r82);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
ret = mxl111sf_write_reg(state, 0x84, r84);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
ret = mxl111sf_write_reg(state, 0x89, r89);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
ret = mxl111sf_write_reg(state, 0x3D, r3D);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static int mxl111sf_hw_set_gpio(struct mxl111sf_state *state, int gpio, int val)
|
||||
{
|
||||
return mxl111sf_hw_do_set_gpio(state, gpio, MXL_GPIO_DIR_OUTPUT, val);
|
||||
}
|
||||
|
||||
static int mxl111sf_hw_gpio_initialize(struct mxl111sf_state *state)
|
||||
{
|
||||
u8 gpioval = 0x07; /* write protect enabled, signal LEDs off */
|
||||
int i, ret;
|
||||
|
||||
mxl_debug("()");
|
||||
|
||||
for (i = 3; i < 8; i++) {
|
||||
ret = mxl111sf_hw_set_gpio(state, i, (gpioval >> i) & 0x01);
|
||||
if (mxl_fail(ret))
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define PCA9534_I2C_ADDR (0x40 >> 1)
|
||||
static int pca9534_set_gpio(struct mxl111sf_state *state, int gpio, int val)
|
||||
{
|
||||
u8 w[2] = { 1, 0 };
|
||||
u8 r = 0;
|
||||
struct i2c_msg msg[] = {
|
||||
{ .addr = PCA9534_I2C_ADDR,
|
||||
.flags = 0, .buf = w, .len = 1 },
|
||||
{ .addr = PCA9534_I2C_ADDR,
|
||||
.flags = I2C_M_RD, .buf = &r, .len = 1 },
|
||||
};
|
||||
|
||||
mxl_debug("(%d, %d)", gpio, val);
|
||||
|
||||
/* read current GPIO levels from flip-flop */
|
||||
i2c_transfer(&state->d->i2c_adap, msg, 2);
|
||||
|
||||
/* prepare write buffer with current GPIO levels */
|
||||
msg[0].len = 2;
|
||||
#if 0
|
||||
w[0] = 1;
|
||||
#endif
|
||||
w[1] = r;
|
||||
|
||||
/* clear the desired GPIO */
|
||||
w[1] &= ~(1 << gpio);
|
||||
|
||||
/* set the desired GPIO value */
|
||||
w[1] |= ((val ? 1 : 0) << gpio);
|
||||
|
||||
/* write new GPIO levels to flip-flop */
|
||||
i2c_transfer(&state->d->i2c_adap, &msg[0], 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pca9534_init_port_expander(struct mxl111sf_state *state)
|
||||
{
|
||||
u8 w[2] = { 1, 0x07 }; /* write protect enabled, signal LEDs off */
|
||||
|
||||
struct i2c_msg msg = {
|
||||
.addr = PCA9534_I2C_ADDR,
|
||||
.flags = 0, .buf = w, .len = 2
|
||||
};
|
||||
|
||||
mxl_debug("()");
|
||||
|
||||
i2c_transfer(&state->d->i2c_adap, &msg, 1);
|
||||
|
||||
/* configure all pins as outputs */
|
||||
w[0] = 3;
|
||||
w[1] = 0;
|
||||
|
||||
i2c_transfer(&state->d->i2c_adap, &msg, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mxl111sf_set_gpio(struct mxl111sf_state *state, int gpio, int val)
|
||||
{
|
||||
mxl_debug("(%d, %d)", gpio, val);
|
||||
|
||||
switch (state->gpio_port_expander) {
|
||||
default:
|
||||
mxl_printk(KERN_ERR,
|
||||
"gpio_port_expander undefined, assuming PCA9534");
|
||||
/* fall-thru */
|
||||
case mxl111sf_PCA9534:
|
||||
return pca9534_set_gpio(state, gpio, val);
|
||||
case mxl111sf_gpio_hw:
|
||||
return mxl111sf_hw_set_gpio(state, gpio, val);
|
||||
}
|
||||
}
|
||||
|
||||
static int mxl111sf_probe_port_expander(struct mxl111sf_state *state)
|
||||
{
|
||||
int ret;
|
||||
u8 w = 1;
|
||||
u8 r = 0;
|
||||
struct i2c_msg msg[] = {
|
||||
{ .flags = 0, .buf = &w, .len = 1 },
|
||||
{ .flags = I2C_M_RD, .buf = &r, .len = 1 },
|
||||
};
|
||||
|
||||
mxl_debug("()");
|
||||
|
||||
msg[0].addr = 0x70 >> 1;
|
||||
msg[1].addr = 0x70 >> 1;
|
||||
|
||||
/* read current GPIO levels from flip-flop */
|
||||
ret = i2c_transfer(&state->d->i2c_adap, msg, 2);
|
||||
if (ret == 2) {
|
||||
state->port_expander_addr = msg[0].addr;
|
||||
state->gpio_port_expander = mxl111sf_PCA9534;
|
||||
mxl_debug("found port expander at 0x%02x",
|
||||
state->port_expander_addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
msg[0].addr = 0x40 >> 1;
|
||||
msg[1].addr = 0x40 >> 1;
|
||||
|
||||
ret = i2c_transfer(&state->d->i2c_adap, msg, 2);
|
||||
if (ret == 2) {
|
||||
state->port_expander_addr = msg[0].addr;
|
||||
state->gpio_port_expander = mxl111sf_PCA9534;
|
||||
mxl_debug("found port expander at 0x%02x",
|
||||
state->port_expander_addr);
|
||||
return 0;
|
||||
}
|
||||
state->port_expander_addr = 0xff;
|
||||
state->gpio_port_expander = mxl111sf_gpio_hw;
|
||||
mxl_debug("using hardware gpio");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mxl111sf_init_port_expander(struct mxl111sf_state *state)
|
||||
{
|
||||
mxl_debug("()");
|
||||
|
||||
if (0x00 == state->port_expander_addr)
|
||||
mxl111sf_probe_port_expander(state);
|
||||
|
||||
switch (state->gpio_port_expander) {
|
||||
default:
|
||||
mxl_printk(KERN_ERR,
|
||||
"gpio_port_expander undefined, assuming PCA9534");
|
||||
/* fall-thru */
|
||||
case mxl111sf_PCA9534:
|
||||
return pca9534_init_port_expander(state);
|
||||
case mxl111sf_gpio_hw:
|
||||
return mxl111sf_hw_gpio_initialize(state);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
int mxl111sf_gpio_mode_switch(struct mxl111sf_state *state, unsigned int mode)
|
||||
{
|
||||
/* GPO:
|
||||
* 3 - ATSC/MH# | 1 = ATSC transport, 0 = MH transport | default 0
|
||||
* 4 - ATSC_RST## | 1 = ATSC enable, 0 = ATSC Reset | default 0
|
||||
* 5 - ATSC_EN | 1 = ATSC power enable, 0 = ATSC power off | default 0
|
||||
* 6 - MH_RESET# | 1 = MH enable, 0 = MH Reset | default 0
|
||||
* 7 - MH_EN | 1 = MH power enable, 0 = MH power off | default 0
|
||||
*/
|
||||
mxl_debug("(%d)", mode);
|
||||
|
||||
switch (mode) {
|
||||
case MXL111SF_GPIO_MOD_MH:
|
||||
mxl111sf_set_gpio(state, 4, 0);
|
||||
mxl111sf_set_gpio(state, 5, 0);
|
||||
msleep(50);
|
||||
mxl111sf_set_gpio(state, 7, 1);
|
||||
msleep(50);
|
||||
mxl111sf_set_gpio(state, 6, 1);
|
||||
msleep(50);
|
||||
|
||||
mxl111sf_set_gpio(state, 3, 0);
|
||||
break;
|
||||
case MXL111SF_GPIO_MOD_ATSC:
|
||||
mxl111sf_set_gpio(state, 6, 0);
|
||||
mxl111sf_set_gpio(state, 7, 0);
|
||||
msleep(50);
|
||||
mxl111sf_set_gpio(state, 5, 1);
|
||||
msleep(50);
|
||||
mxl111sf_set_gpio(state, 4, 1);
|
||||
msleep(50);
|
||||
mxl111sf_set_gpio(state, 3, 1);
|
||||
break;
|
||||
default: /* DVBT / STANDBY */
|
||||
mxl111sf_init_port_expander(state);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
* End:
|
||||
*/
|
56
drivers/media/dvb/dvb-usb/mxl111sf-gpio.h
Normal file
56
drivers/media/dvb/dvb-usb/mxl111sf-gpio.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* mxl111sf-gpio.h - driver for the MaxLinear MXL111SF
|
||||
*
|
||||
* Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef _DVB_USB_MXL111SF_GPIO_H_
|
||||
#define _DVB_USB_MXL111SF_GPIO_H_
|
||||
|
||||
#include "mxl111sf.h"
|
||||
|
||||
int mxl111sf_set_gpio(struct mxl111sf_state *state, int gpio, int val);
|
||||
int mxl111sf_init_port_expander(struct mxl111sf_state *state);
|
||||
|
||||
#define MXL111SF_GPIO_MOD_DVBT 0
|
||||
#define MXL111SF_GPIO_MOD_MH 1
|
||||
#define MXL111SF_GPIO_MOD_ATSC 2
|
||||
int mxl111sf_gpio_mode_switch(struct mxl111sf_state *state, unsigned int mode);
|
||||
|
||||
enum mxl111sf_mux_config {
|
||||
PIN_MUX_DEFAULT = 0,
|
||||
PIN_MUX_TS_OUT_PARALLEL,
|
||||
PIN_MUX_TS_OUT_SERIAL,
|
||||
PIN_MUX_GPIO_MODE,
|
||||
PIN_MUX_TS_SERIAL_IN_MODE_0,
|
||||
PIN_MUX_TS_SERIAL_IN_MODE_1,
|
||||
PIN_MUX_TS_SPI_IN_MODE_0,
|
||||
PIN_MUX_TS_SPI_IN_MODE_1,
|
||||
PIN_MUX_TS_PARALLEL_IN,
|
||||
PIN_MUX_BT656_I2S_MODE,
|
||||
};
|
||||
|
||||
int mxl111sf_config_pin_mux_modes(struct mxl111sf_state *state,
|
||||
enum mxl111sf_mux_config pin_mux_config);
|
||||
|
||||
#endif /* _DVB_USB_MXL111SF_GPIO_H_ */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
* End:
|
||||
*/
|
851
drivers/media/dvb/dvb-usb/mxl111sf-i2c.c
Normal file
851
drivers/media/dvb/dvb-usb/mxl111sf-i2c.c
Normal file
@ -0,0 +1,851 @@
|
||||
/*
|
||||
* mxl111sf-i2c.c - driver for the MaxLinear MXL111SF
|
||||
*
|
||||
* Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "mxl111sf-i2c.h"
|
||||
#include "mxl111sf.h"
|
||||
|
||||
/* SW-I2C ----------------------------------------------------------------- */
|
||||
|
||||
#define SW_I2C_ADDR 0x1a
|
||||
#define SW_I2C_EN 0x02
|
||||
#define SW_SCL_OUT 0x04
|
||||
#define SW_SDA_OUT 0x08
|
||||
#define SW_SDA_IN 0x04
|
||||
|
||||
#define SW_I2C_BUSY_ADDR 0x2f
|
||||
#define SW_I2C_BUSY 0x02
|
||||
|
||||
static int mxl111sf_i2c_bitbang_sendbyte(struct mxl111sf_state *state,
|
||||
u8 byte)
|
||||
{
|
||||
int i, ret;
|
||||
u8 data = 0;
|
||||
|
||||
mxl_i2c("(0x%02x)", byte);
|
||||
|
||||
ret = mxl111sf_read_reg(state, SW_I2C_BUSY_ADDR, &data);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
|
||||
data = (byte & (0x80 >> i)) ? SW_SDA_OUT : 0;
|
||||
|
||||
ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
|
||||
0x10 | SW_I2C_EN | data);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
|
||||
0x10 | SW_I2C_EN | data | SW_SCL_OUT);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
|
||||
0x10 | SW_I2C_EN | data);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* last bit was 0 so we need to release SDA */
|
||||
if (!(byte & 1)) {
|
||||
ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
|
||||
0x10 | SW_I2C_EN | SW_SDA_OUT);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* CLK high for ACK readback */
|
||||
ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
|
||||
0x10 | SW_I2C_EN | SW_SCL_OUT | SW_SDA_OUT);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
ret = mxl111sf_read_reg(state, SW_I2C_BUSY_ADDR, &data);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
/* drop the CLK after getting ACK, SDA will go high right away */
|
||||
ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
|
||||
0x10 | SW_I2C_EN | SW_SDA_OUT);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
if (data & SW_SDA_IN)
|
||||
ret = -EIO;
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mxl111sf_i2c_bitbang_recvbyte(struct mxl111sf_state *state,
|
||||
u8 *pbyte)
|
||||
{
|
||||
int i, ret;
|
||||
u8 byte = 0;
|
||||
u8 data = 0;
|
||||
|
||||
mxl_i2c("()");
|
||||
|
||||
*pbyte = 0;
|
||||
|
||||
ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
|
||||
0x10 | SW_I2C_EN | SW_SDA_OUT);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
|
||||
0x10 | SW_I2C_EN |
|
||||
SW_SCL_OUT | SW_SDA_OUT);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
ret = mxl111sf_read_reg(state, SW_I2C_BUSY_ADDR, &data);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
if (data & SW_SDA_IN)
|
||||
byte |= (0x80 >> i);
|
||||
|
||||
ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
|
||||
0x10 | SW_I2C_EN | SW_SDA_OUT);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
}
|
||||
*pbyte = byte;
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mxl111sf_i2c_start(struct mxl111sf_state *state)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mxl_i2c("()");
|
||||
|
||||
ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
|
||||
0x10 | SW_I2C_EN | SW_SCL_OUT | SW_SDA_OUT);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
|
||||
0x10 | SW_I2C_EN | SW_SCL_OUT);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
|
||||
0x10 | SW_I2C_EN); /* start */
|
||||
mxl_fail(ret);
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mxl111sf_i2c_stop(struct mxl111sf_state *state)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mxl_i2c("()");
|
||||
|
||||
ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
|
||||
0x10 | SW_I2C_EN); /* stop */
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
|
||||
0x10 | SW_I2C_EN | SW_SCL_OUT);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
|
||||
0x10 | SW_I2C_EN | SW_SCL_OUT | SW_SDA_OUT);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
|
||||
0x10 | SW_SCL_OUT | SW_SDA_OUT);
|
||||
mxl_fail(ret);
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mxl111sf_i2c_ack(struct mxl111sf_state *state)
|
||||
{
|
||||
int ret;
|
||||
u8 b = 0;
|
||||
|
||||
mxl_i2c("()");
|
||||
|
||||
ret = mxl111sf_read_reg(state, SW_I2C_BUSY_ADDR, &b);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
|
||||
0x10 | SW_I2C_EN);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
/* pull SDA low */
|
||||
ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
|
||||
0x10 | SW_I2C_EN | SW_SCL_OUT);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
|
||||
0x10 | SW_I2C_EN | SW_SDA_OUT);
|
||||
mxl_fail(ret);
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mxl111sf_i2c_nack(struct mxl111sf_state *state)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mxl_i2c("()");
|
||||
|
||||
/* SDA high to signal last byte read from slave */
|
||||
ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
|
||||
0x10 | SW_I2C_EN | SW_SCL_OUT | SW_SDA_OUT);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
|
||||
0x10 | SW_I2C_EN | SW_SDA_OUT);
|
||||
mxl_fail(ret);
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
static int mxl111sf_i2c_sw_xfer_msg(struct mxl111sf_state *state,
|
||||
struct i2c_msg *msg)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
mxl_i2c("()");
|
||||
|
||||
if (msg->flags & I2C_M_RD) {
|
||||
|
||||
ret = mxl111sf_i2c_start(state);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
ret = mxl111sf_i2c_bitbang_sendbyte(state,
|
||||
(msg->addr << 1) | 0x01);
|
||||
if (mxl_fail(ret)) {
|
||||
mxl111sf_i2c_stop(state);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (i = 0; i < msg->len; i++) {
|
||||
ret = mxl111sf_i2c_bitbang_recvbyte(state,
|
||||
&msg->buf[i]);
|
||||
if (mxl_fail(ret)) {
|
||||
mxl111sf_i2c_stop(state);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (i < msg->len - 1)
|
||||
mxl111sf_i2c_ack(state);
|
||||
}
|
||||
|
||||
mxl111sf_i2c_nack(state);
|
||||
|
||||
ret = mxl111sf_i2c_stop(state);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
} else {
|
||||
|
||||
ret = mxl111sf_i2c_start(state);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
ret = mxl111sf_i2c_bitbang_sendbyte(state,
|
||||
(msg->addr << 1) & 0xfe);
|
||||
if (mxl_fail(ret)) {
|
||||
mxl111sf_i2c_stop(state);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (i = 0; i < msg->len; i++) {
|
||||
ret = mxl111sf_i2c_bitbang_sendbyte(state,
|
||||
msg->buf[i]);
|
||||
if (mxl_fail(ret)) {
|
||||
mxl111sf_i2c_stop(state);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: we only want to do this on the last transaction */
|
||||
mxl111sf_i2c_stop(state);
|
||||
}
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* HW-I2C ----------------------------------------------------------------- */
|
||||
|
||||
#define USB_WRITE_I2C_CMD 0x99
|
||||
#define USB_READ_I2C_CMD 0xdd
|
||||
#define USB_END_I2C_CMD 0xfe
|
||||
|
||||
#define USB_WRITE_I2C_CMD_LEN 26
|
||||
#define USB_READ_I2C_CMD_LEN 24
|
||||
|
||||
#define I2C_MUX_REG 0x30
|
||||
#define I2C_CONTROL_REG 0x00
|
||||
#define I2C_SLAVE_ADDR_REG 0x08
|
||||
#define I2C_DATA_REG 0x0c
|
||||
#define I2C_INT_STATUS_REG 0x10
|
||||
|
||||
static int mxl111sf_i2c_send_data(struct mxl111sf_state *state,
|
||||
u8 index, u8 *wdata)
|
||||
{
|
||||
int ret = mxl111sf_ctrl_msg(state->d, wdata[0],
|
||||
&wdata[1], 25, NULL, 0);
|
||||
mxl_fail(ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mxl111sf_i2c_get_data(struct mxl111sf_state *state,
|
||||
u8 index, u8 *wdata, u8 *rdata)
|
||||
{
|
||||
int ret = mxl111sf_ctrl_msg(state->d, wdata[0],
|
||||
&wdata[1], 25, rdata, 24);
|
||||
mxl_fail(ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u8 mxl111sf_i2c_check_status(struct mxl111sf_state *state)
|
||||
{
|
||||
u8 status = 0;
|
||||
u8 buf[26];
|
||||
|
||||
mxl_i2c_adv("()");
|
||||
|
||||
buf[0] = USB_READ_I2C_CMD;
|
||||
buf[1] = 0x00;
|
||||
|
||||
buf[2] = I2C_INT_STATUS_REG;
|
||||
buf[3] = 0x00;
|
||||
buf[4] = 0x00;
|
||||
|
||||
buf[5] = USB_END_I2C_CMD;
|
||||
|
||||
mxl111sf_i2c_get_data(state, 0, buf, buf);
|
||||
|
||||
if (buf[1] & 0x04)
|
||||
status = 1;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static u8 mxl111sf_i2c_check_fifo(struct mxl111sf_state *state)
|
||||
{
|
||||
u8 status = 0;
|
||||
u8 buf[26];
|
||||
|
||||
mxl_i2c("()");
|
||||
|
||||
buf[0] = USB_READ_I2C_CMD;
|
||||
buf[1] = 0x00;
|
||||
|
||||
buf[2] = I2C_MUX_REG;
|
||||
buf[3] = 0x00;
|
||||
buf[4] = 0x00;
|
||||
|
||||
buf[5] = I2C_INT_STATUS_REG;
|
||||
buf[6] = 0x00;
|
||||
buf[7] = 0x00;
|
||||
buf[8] = USB_END_I2C_CMD;
|
||||
|
||||
mxl111sf_i2c_get_data(state, 0, buf, buf);
|
||||
|
||||
if (0x08 == (buf[1] & 0x08))
|
||||
status = 1;
|
||||
|
||||
if ((buf[5] & 0x02) == 0x02)
|
||||
mxl_i2c("(buf[5] & 0x02) == 0x02"); /* FIXME */
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int mxl111sf_i2c_readagain(struct mxl111sf_state *state,
|
||||
u8 count, u8 *rbuf)
|
||||
{
|
||||
u8 i2c_w_data[26];
|
||||
u8 i2c_r_data[24];
|
||||
u8 i = 0;
|
||||
u8 fifo_status = 0;
|
||||
int ret;
|
||||
int status = 0;
|
||||
|
||||
mxl_i2c("read %d bytes", count);
|
||||
|
||||
while ((fifo_status == 0) && (i++ < 5))
|
||||
fifo_status = mxl111sf_i2c_check_fifo(state);
|
||||
|
||||
i2c_w_data[0] = 0xDD;
|
||||
i2c_w_data[1] = 0x00;
|
||||
|
||||
for (i = 2; i < 26; i++)
|
||||
i2c_w_data[i] = 0xFE;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
i2c_w_data[2+(i*3)] = 0x0C;
|
||||
i2c_w_data[3+(i*3)] = 0x00;
|
||||
i2c_w_data[4+(i*3)] = 0x00;
|
||||
}
|
||||
|
||||
ret = mxl111sf_i2c_get_data(state, 0, i2c_w_data, i2c_r_data);
|
||||
|
||||
/* Check for I2C NACK status */
|
||||
if (mxl111sf_i2c_check_status(state) == 1) {
|
||||
mxl_i2c("error!");
|
||||
} else {
|
||||
for (i = 0; i < count; i++) {
|
||||
rbuf[i] = i2c_r_data[(i*3)+1];
|
||||
mxl_i2c("%02x\t %02x",
|
||||
i2c_r_data[(i*3)+1],
|
||||
i2c_r_data[(i*3)+2]);
|
||||
}
|
||||
|
||||
status = 1;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#define HWI2C400 1
|
||||
static int mxl111sf_i2c_hw_xfer_msg(struct mxl111sf_state *state,
|
||||
struct i2c_msg *msg)
|
||||
{
|
||||
int i, k, ret = 0;
|
||||
u16 index = 0;
|
||||
u8 buf[26];
|
||||
u8 i2c_r_data[24];
|
||||
u16 block_len;
|
||||
u16 left_over_len;
|
||||
u8 rd_status[8];
|
||||
u8 ret_status;
|
||||
u8 readbuff[26];
|
||||
|
||||
mxl_i2c("addr: 0x%02x, read buff len: %d, write buff len: %d",
|
||||
msg->addr, (msg->flags & I2C_M_RD) ? msg->len : 0,
|
||||
(!(msg->flags & I2C_M_RD)) ? msg->len : 0);
|
||||
|
||||
for (index = 0; index < 26; index++)
|
||||
buf[index] = USB_END_I2C_CMD;
|
||||
|
||||
/* command to indicate data payload is destined for I2C interface */
|
||||
buf[0] = USB_WRITE_I2C_CMD;
|
||||
buf[1] = 0x00;
|
||||
|
||||
/* enable I2C interface */
|
||||
buf[2] = I2C_MUX_REG;
|
||||
buf[3] = 0x80;
|
||||
buf[4] = 0x00;
|
||||
|
||||
/* enable I2C interface */
|
||||
buf[5] = I2C_MUX_REG;
|
||||
buf[6] = 0x81;
|
||||
buf[7] = 0x00;
|
||||
|
||||
/* set Timeout register on I2C interface */
|
||||
buf[8] = 0x14;
|
||||
buf[9] = 0xff;
|
||||
buf[10] = 0x00;
|
||||
#if 0
|
||||
/* enable Interrupts on I2C interface */
|
||||
buf[8] = 0x24;
|
||||
buf[9] = 0xF7;
|
||||
buf[10] = 0x00;
|
||||
#endif
|
||||
buf[11] = 0x24;
|
||||
buf[12] = 0xF7;
|
||||
buf[13] = 0x00;
|
||||
|
||||
ret = mxl111sf_i2c_send_data(state, 0, buf);
|
||||
|
||||
/* write data on I2C bus */
|
||||
if (!(msg->flags & I2C_M_RD) && (msg->len > 0)) {
|
||||
mxl_i2c("%d\t%02x", msg->len, msg->buf[0]);
|
||||
|
||||
/* control register on I2C interface to initialize I2C bus */
|
||||
buf[2] = I2C_CONTROL_REG;
|
||||
buf[3] = 0x5E;
|
||||
buf[4] = (HWI2C400) ? 0x03 : 0x0D;
|
||||
|
||||
/* I2C Slave device Address */
|
||||
buf[5] = I2C_SLAVE_ADDR_REG;
|
||||
buf[6] = (msg->addr);
|
||||
buf[7] = 0x00;
|
||||
buf[8] = USB_END_I2C_CMD;
|
||||
ret = mxl111sf_i2c_send_data(state, 0, buf);
|
||||
|
||||
/* check for slave device status */
|
||||
if (mxl111sf_i2c_check_status(state) == 1) {
|
||||
mxl_i2c("NACK writing slave address %02x",
|
||||
msg->addr);
|
||||
/* if NACK, stop I2C bus and exit */
|
||||
buf[2] = I2C_CONTROL_REG;
|
||||
buf[3] = 0x4E;
|
||||
buf[4] = (HWI2C400) ? 0x03 : 0x0D;
|
||||
ret = -EIO;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* I2C interface can do I2C operations in block of 8 bytes of
|
||||
I2C data. calculation to figure out number of blocks of i2c
|
||||
data required to program */
|
||||
block_len = (msg->len / 8);
|
||||
left_over_len = (msg->len % 8);
|
||||
index = 0;
|
||||
|
||||
mxl_i2c("block_len %d, left_over_len %d",
|
||||
block_len, left_over_len);
|
||||
|
||||
for (index = 0; index < block_len; index++) {
|
||||
for (i = 0; i < 8; i++) {
|
||||
/* write data on I2C interface */
|
||||
buf[2+(i*3)] = I2C_DATA_REG;
|
||||
buf[3+(i*3)] = msg->buf[(index*8)+i];
|
||||
buf[4+(i*3)] = 0x00;
|
||||
}
|
||||
|
||||
ret = mxl111sf_i2c_send_data(state, 0, buf);
|
||||
|
||||
/* check for I2C NACK status */
|
||||
if (mxl111sf_i2c_check_status(state) == 1) {
|
||||
mxl_i2c("NACK writing slave address %02x",
|
||||
msg->addr);
|
||||
|
||||
/* if NACK, stop I2C bus and exit */
|
||||
buf[2] = I2C_CONTROL_REG;
|
||||
buf[3] = 0x4E;
|
||||
buf[4] = (HWI2C400) ? 0x03 : 0x0D;
|
||||
ret = -EIO;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (left_over_len) {
|
||||
for (k = 0; k < 26; k++)
|
||||
buf[k] = USB_END_I2C_CMD;
|
||||
|
||||
buf[0] = 0x99;
|
||||
buf[1] = 0x00;
|
||||
|
||||
for (i = 0; i < left_over_len; i++) {
|
||||
buf[2+(i*3)] = I2C_DATA_REG;
|
||||
buf[3+(i*3)] = msg->buf[(index*8)+i];
|
||||
mxl_i2c("index = %d %d data %d",
|
||||
index, i, msg->buf[(index*8)+i]);
|
||||
buf[4+(i*3)] = 0x00;
|
||||
}
|
||||
ret = mxl111sf_i2c_send_data(state, 0, buf);
|
||||
|
||||
/* check for I2C NACK status */
|
||||
if (mxl111sf_i2c_check_status(state) == 1) {
|
||||
mxl_i2c("NACK writing slave address %02x",
|
||||
msg->addr);
|
||||
|
||||
/* if NACK, stop I2C bus and exit */
|
||||
buf[2] = I2C_CONTROL_REG;
|
||||
buf[3] = 0x4E;
|
||||
buf[4] = (HWI2C400) ? 0x03 : 0x0D;
|
||||
ret = -EIO;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* issue I2C STOP after write */
|
||||
buf[2] = I2C_CONTROL_REG;
|
||||
buf[3] = 0x4E;
|
||||
buf[4] = (HWI2C400) ? 0x03 : 0x0D;
|
||||
|
||||
}
|
||||
|
||||
/* read data from I2C bus */
|
||||
if ((msg->flags & I2C_M_RD) && (msg->len > 0)) {
|
||||
mxl_i2c("read buf len %d", msg->len);
|
||||
|
||||
/* command to indicate data payload is
|
||||
destined for I2C interface */
|
||||
buf[2] = I2C_CONTROL_REG;
|
||||
buf[3] = 0xDF;
|
||||
buf[4] = (HWI2C400) ? 0x03 : 0x0D;
|
||||
|
||||
/* I2C xfer length */
|
||||
buf[5] = 0x14;
|
||||
buf[6] = (msg->len & 0xFF);
|
||||
buf[7] = 0;
|
||||
|
||||
/* I2C slave device Address */
|
||||
buf[8] = I2C_SLAVE_ADDR_REG;
|
||||
buf[9] = msg->addr;
|
||||
buf[10] = 0x00;
|
||||
buf[11] = USB_END_I2C_CMD;
|
||||
ret = mxl111sf_i2c_send_data(state, 0, buf);
|
||||
|
||||
/* check for I2C NACK status */
|
||||
if (mxl111sf_i2c_check_status(state) == 1) {
|
||||
mxl_i2c("NACK reading slave address %02x",
|
||||
msg->addr);
|
||||
|
||||
/* if NACK, stop I2C bus and exit */
|
||||
buf[2] = I2C_CONTROL_REG;
|
||||
buf[3] = 0xC7;
|
||||
buf[4] = (HWI2C400) ? 0x03 : 0x0D;
|
||||
ret = -EIO;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* I2C interface can do I2C operations in block of 8 bytes of
|
||||
I2C data. calculation to figure out number of blocks of
|
||||
i2c data required to program */
|
||||
block_len = ((msg->len) / 8);
|
||||
left_over_len = ((msg->len) % 8);
|
||||
index = 0;
|
||||
|
||||
mxl_i2c("block_len %d, left_over_len %d",
|
||||
block_len, left_over_len);
|
||||
|
||||
/* command to read data from I2C interface */
|
||||
buf[0] = USB_READ_I2C_CMD;
|
||||
buf[1] = 0x00;
|
||||
|
||||
for (index = 0; index < block_len; index++) {
|
||||
/* setup I2C read request packet on I2C interface */
|
||||
for (i = 0; i < 8; i++) {
|
||||
buf[2+(i*3)] = I2C_DATA_REG;
|
||||
buf[3+(i*3)] = 0x00;
|
||||
buf[4+(i*3)] = 0x00;
|
||||
}
|
||||
|
||||
ret = mxl111sf_i2c_get_data(state, 0, buf, i2c_r_data);
|
||||
|
||||
/* check for I2C NACK status */
|
||||
if (mxl111sf_i2c_check_status(state) == 1) {
|
||||
mxl_i2c("NACK reading slave address %02x",
|
||||
msg->addr);
|
||||
|
||||
/* if NACK, stop I2C bus and exit */
|
||||
buf[2] = I2C_CONTROL_REG;
|
||||
buf[3] = 0xC7;
|
||||
buf[4] = (HWI2C400) ? 0x03 : 0x0D;
|
||||
ret = -EIO;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* copy data from i2c data payload to read buffer */
|
||||
for (i = 0; i < 8; i++) {
|
||||
rd_status[i] = i2c_r_data[(i*3)+2];
|
||||
|
||||
if (rd_status[i] == 0x04) {
|
||||
if (i < 7) {
|
||||
mxl_i2c("i2c fifo empty!"
|
||||
" @ %d", i);
|
||||
msg->buf[(index*8)+i] =
|
||||
i2c_r_data[(i*3)+1];
|
||||
/* read again */
|
||||
ret_status =
|
||||
mxl111sf_i2c_readagain(
|
||||
state, 8-(i+1),
|
||||
readbuff);
|
||||
if (ret_status == 1) {
|
||||
for (k = 0;
|
||||
k < 8-(i+1);
|
||||
k++) {
|
||||
|
||||
msg->buf[(index*8)+(k+i+1)] =
|
||||
readbuff[k];
|
||||
mxl_i2c("read data: %02x\t %02x",
|
||||
msg->buf[(index*8)+(k+i)],
|
||||
(index*8)+(k+i));
|
||||
mxl_i2c("read data: %02x\t %02x",
|
||||
msg->buf[(index*8)+(k+i+1)],
|
||||
readbuff[k]);
|
||||
|
||||
}
|
||||
goto stop_copy;
|
||||
} else {
|
||||
mxl_i2c("readagain "
|
||||
"ERROR!");
|
||||
}
|
||||
} else {
|
||||
msg->buf[(index*8)+i] =
|
||||
i2c_r_data[(i*3)+1];
|
||||
}
|
||||
} else {
|
||||
msg->buf[(index*8)+i] =
|
||||
i2c_r_data[(i*3)+1];
|
||||
}
|
||||
}
|
||||
stop_copy:
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
if (left_over_len) {
|
||||
for (k = 0; k < 26; k++)
|
||||
buf[k] = USB_END_I2C_CMD;
|
||||
|
||||
buf[0] = 0xDD;
|
||||
buf[1] = 0x00;
|
||||
|
||||
for (i = 0; i < left_over_len; i++) {
|
||||
buf[2+(i*3)] = I2C_DATA_REG;
|
||||
buf[3+(i*3)] = 0x00;
|
||||
buf[4+(i*3)] = 0x00;
|
||||
}
|
||||
ret = mxl111sf_i2c_get_data(state, 0, buf,
|
||||
i2c_r_data);
|
||||
|
||||
/* check for I2C NACK status */
|
||||
if (mxl111sf_i2c_check_status(state) == 1) {
|
||||
mxl_i2c("NACK reading slave address %02x",
|
||||
msg->addr);
|
||||
|
||||
/* if NACK, stop I2C bus and exit */
|
||||
buf[2] = I2C_CONTROL_REG;
|
||||
buf[3] = 0xC7;
|
||||
buf[4] = (HWI2C400) ? 0x03 : 0x0D;
|
||||
ret = -EIO;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
for (i = 0; i < left_over_len; i++) {
|
||||
msg->buf[(block_len*8)+i] =
|
||||
i2c_r_data[(i*3)+1];
|
||||
mxl_i2c("read data: %02x\t %02x",
|
||||
i2c_r_data[(i*3)+1],
|
||||
i2c_r_data[(i*3)+2]);
|
||||
}
|
||||
}
|
||||
|
||||
/* indicate I2C interface to issue NACK
|
||||
after next I2C read op */
|
||||
buf[0] = USB_WRITE_I2C_CMD;
|
||||
buf[1] = 0x00;
|
||||
|
||||
/* control register */
|
||||
buf[2] = I2C_CONTROL_REG;
|
||||
buf[3] = 0x17;
|
||||
buf[4] = (HWI2C400) ? 0x03 : 0x0D;
|
||||
|
||||
buf[5] = USB_END_I2C_CMD;
|
||||
ret = mxl111sf_i2c_send_data(state, 0, buf);
|
||||
|
||||
/* control register */
|
||||
buf[2] = I2C_CONTROL_REG;
|
||||
buf[3] = 0xC7;
|
||||
buf[4] = (HWI2C400) ? 0x03 : 0x0D;
|
||||
|
||||
}
|
||||
exit:
|
||||
/* STOP and disable I2C MUX */
|
||||
buf[0] = USB_WRITE_I2C_CMD;
|
||||
buf[1] = 0x00;
|
||||
|
||||
/* de-initilize I2C BUS */
|
||||
buf[5] = USB_END_I2C_CMD;
|
||||
mxl111sf_i2c_send_data(state, 0, buf);
|
||||
|
||||
/* Control Register */
|
||||
buf[2] = I2C_CONTROL_REG;
|
||||
buf[3] = 0xDF;
|
||||
buf[4] = 0x03;
|
||||
|
||||
/* disable I2C interface */
|
||||
buf[5] = I2C_MUX_REG;
|
||||
buf[6] = 0x00;
|
||||
buf[7] = 0x00;
|
||||
|
||||
/* de-initilize I2C BUS */
|
||||
buf[8] = USB_END_I2C_CMD;
|
||||
mxl111sf_i2c_send_data(state, 0, buf);
|
||||
|
||||
/* disable I2C interface */
|
||||
buf[2] = I2C_MUX_REG;
|
||||
buf[3] = 0x81;
|
||||
buf[4] = 0x00;
|
||||
|
||||
/* disable I2C interface */
|
||||
buf[5] = I2C_MUX_REG;
|
||||
buf[6] = 0x00;
|
||||
buf[7] = 0x00;
|
||||
|
||||
/* disable I2C interface */
|
||||
buf[8] = I2C_MUX_REG;
|
||||
buf[9] = 0x00;
|
||||
buf[10] = 0x00;
|
||||
|
||||
buf[11] = USB_END_I2C_CMD;
|
||||
mxl111sf_i2c_send_data(state, 0, buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
int mxl111sf_i2c_xfer(struct i2c_adapter *adap,
|
||||
struct i2c_msg msg[], int num)
|
||||
{
|
||||
struct dvb_usb_device *d = i2c_get_adapdata(adap);
|
||||
struct mxl111sf_state *state = d->priv;
|
||||
int hwi2c = (state->chip_rev > MXL111SF_V6);
|
||||
int i, ret;
|
||||
|
||||
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
|
||||
return -EAGAIN;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
ret = (hwi2c) ?
|
||||
mxl111sf_i2c_hw_xfer_msg(state, &msg[i]) :
|
||||
mxl111sf_i2c_sw_xfer_msg(state, &msg[i]);
|
||||
if (mxl_fail(ret)) {
|
||||
mxl_debug_adv("failed with error %d on i2c "
|
||||
"transaction %d of %d, %sing %d bytes "
|
||||
"to/from 0x%02x", ret, i+1, num,
|
||||
(msg[i].flags & I2C_M_RD) ?
|
||||
"read" : "writ",
|
||||
msg[i].len, msg[i].addr);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&d->i2c_mutex);
|
||||
|
||||
return i == num ? num : -EREMOTEIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
* End:
|
||||
*/
|
35
drivers/media/dvb/dvb-usb/mxl111sf-i2c.h
Normal file
35
drivers/media/dvb/dvb-usb/mxl111sf-i2c.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* mxl111sf-i2c.h - driver for the MaxLinear MXL111SF
|
||||
*
|
||||
* Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef _DVB_USB_MXL111SF_I2C_H_
|
||||
#define _DVB_USB_MXL111SF_I2C_H_
|
||||
|
||||
#include <linux/i2c.h>
|
||||
|
||||
int mxl111sf_i2c_xfer(struct i2c_adapter *adap,
|
||||
struct i2c_msg msg[], int num);
|
||||
|
||||
#endif /* _DVB_USB_MXL111SF_I2C_H_ */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
* End:
|
||||
*/
|
342
drivers/media/dvb/dvb-usb/mxl111sf-phy.c
Normal file
342
drivers/media/dvb/dvb-usb/mxl111sf-phy.c
Normal file
@ -0,0 +1,342 @@
|
||||
/*
|
||||
* mxl111sf-phy.c - driver for the MaxLinear MXL111SF
|
||||
*
|
||||
* Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "mxl111sf-phy.h"
|
||||
#include "mxl111sf-reg.h"
|
||||
|
||||
int mxl111sf_init_tuner_demod(struct mxl111sf_state *state)
|
||||
{
|
||||
struct mxl111sf_reg_ctrl_info mxl_111_overwrite_default[] = {
|
||||
{0x07, 0xff, 0x0c},
|
||||
{0x58, 0xff, 0x9d},
|
||||
{0x09, 0xff, 0x00},
|
||||
{0x06, 0xff, 0x06},
|
||||
{0xc8, 0xff, 0x40}, /* ED_LE_WIN_OLD = 0 */
|
||||
{0x8d, 0x01, 0x01}, /* NEGATE_Q */
|
||||
{0x32, 0xff, 0xac}, /* DIG_RFREFSELECT = 12 */
|
||||
{0x42, 0xff, 0x43}, /* DIG_REG_AMP = 4 */
|
||||
{0x74, 0xff, 0xc4}, /* SSPUR_FS_PRIO = 4 */
|
||||
{0x71, 0xff, 0xe6}, /* SPUR_ROT_PRIO_VAL = 1 */
|
||||
{0x83, 0xff, 0x64}, /* INF_FILT1_THD_SC = 100 */
|
||||
{0x85, 0xff, 0x64}, /* INF_FILT2_THD_SC = 100 */
|
||||
{0x88, 0xff, 0xf0}, /* INF_THD = 240 */
|
||||
{0x6f, 0xf0, 0xb0}, /* DFE_DLY = 11 */
|
||||
{0x00, 0xff, 0x01}, /* Change to page 1 */
|
||||
{0x81, 0xff, 0x11}, /* DSM_FERR_BYPASS = 1 */
|
||||
{0xf4, 0xff, 0x07}, /* DIG_FREQ_CORR = 1 */
|
||||
{0xd4, 0x1f, 0x0f}, /* SPUR_TEST_NOISE_TH = 15 */
|
||||
{0xd6, 0xff, 0x0c}, /* SPUR_TEST_NOISE_PAPR = 12 */
|
||||
{0x00, 0xff, 0x00}, /* Change to page 0 */
|
||||
{0, 0, 0}
|
||||
};
|
||||
|
||||
mxl_debug("()");
|
||||
|
||||
return mxl111sf_ctrl_program_regs(state, mxl_111_overwrite_default);
|
||||
}
|
||||
|
||||
int mxl1x1sf_soft_reset(struct mxl111sf_state *state)
|
||||
{
|
||||
int ret;
|
||||
mxl_debug("()");
|
||||
|
||||
ret = mxl111sf_write_reg(state, 0xff, 0x00); /* AIC */
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
ret = mxl111sf_write_reg(state, 0x02, 0x01); /* get out of reset */
|
||||
mxl_fail(ret);
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mxl1x1sf_set_device_mode(struct mxl111sf_state *state, int mode)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mxl_debug("(%s)", MXL_SOC_MODE == mode ?
|
||||
"MXL_SOC_MODE" : "MXL_TUNER_MODE");
|
||||
|
||||
/* set device mode */
|
||||
ret = mxl111sf_write_reg(state, 0x03,
|
||||
MXL_SOC_MODE == mode ? 0x01 : 0x00);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
ret = mxl111sf_write_reg_mask(state,
|
||||
0x7d, 0x40, MXL_SOC_MODE == mode ?
|
||||
0x00 : /* enable impulse noise filter,
|
||||
INF_BYP = 0 */
|
||||
0x40); /* disable impulse noise filter,
|
||||
INF_BYP = 1 */
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
state->device_mode = mode;
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* power up tuner */
|
||||
int mxl1x1sf_top_master_ctrl(struct mxl111sf_state *state, int onoff)
|
||||
{
|
||||
mxl_debug("(%d)", onoff);
|
||||
|
||||
return mxl111sf_write_reg(state, 0x01, onoff ? 0x01 : 0x00);
|
||||
}
|
||||
|
||||
int mxl111sf_disable_656_port(struct mxl111sf_state *state)
|
||||
{
|
||||
mxl_debug("()");
|
||||
|
||||
return mxl111sf_write_reg_mask(state, 0x12, 0x04, 0x00);
|
||||
}
|
||||
|
||||
int mxl111sf_enable_usb_output(struct mxl111sf_state *state)
|
||||
{
|
||||
mxl_debug("()");
|
||||
|
||||
return mxl111sf_write_reg_mask(state, 0x17, 0x40, 0x00);
|
||||
}
|
||||
|
||||
/* initialize TSIF as input port of MxL1X1SF for MPEG2 data transfer */
|
||||
int mxl111sf_config_mpeg_in(struct mxl111sf_state *state,
|
||||
unsigned int parallel_serial,
|
||||
unsigned int msb_lsb_1st,
|
||||
unsigned int clock_phase,
|
||||
unsigned int mpeg_valid_pol,
|
||||
unsigned int mpeg_sync_pol)
|
||||
{
|
||||
int ret;
|
||||
u8 mode, tmp;
|
||||
|
||||
mxl_debug("(%u,%u,%u,%u,%u)", parallel_serial, msb_lsb_1st,
|
||||
clock_phase, mpeg_valid_pol, mpeg_sync_pol);
|
||||
|
||||
/* Enable PIN MUX */
|
||||
ret = mxl111sf_write_reg(state, V6_PIN_MUX_MODE_REG, V6_ENABLE_PIN_MUX);
|
||||
mxl_fail(ret);
|
||||
|
||||
/* Configure MPEG Clock phase */
|
||||
mxl111sf_read_reg(state, V6_MPEG_IN_CLK_INV_REG, &mode);
|
||||
|
||||
if (clock_phase == TSIF_NORMAL)
|
||||
mode &= ~V6_INVERTED_CLK_PHASE;
|
||||
else
|
||||
mode |= V6_INVERTED_CLK_PHASE;
|
||||
|
||||
ret = mxl111sf_write_reg(state, V6_MPEG_IN_CLK_INV_REG, mode);
|
||||
mxl_fail(ret);
|
||||
|
||||
/* Configure data input mode, MPEG Valid polarity, MPEG Sync polarity
|
||||
* Get current configuration */
|
||||
ret = mxl111sf_read_reg(state, V6_MPEG_IN_CTRL_REG, &mode);
|
||||
mxl_fail(ret);
|
||||
|
||||
/* Data Input mode */
|
||||
if (parallel_serial == TSIF_INPUT_PARALLEL) {
|
||||
/* Disable serial mode */
|
||||
mode &= ~V6_MPEG_IN_DATA_SERIAL;
|
||||
|
||||
/* Enable Parallel mode */
|
||||
mode |= V6_MPEG_IN_DATA_PARALLEL;
|
||||
} else {
|
||||
/* Disable Parallel mode */
|
||||
mode &= ~V6_MPEG_IN_DATA_PARALLEL;
|
||||
|
||||
/* Enable Serial Mode */
|
||||
mode |= V6_MPEG_IN_DATA_SERIAL;
|
||||
|
||||
/* If serial interface is chosen, configure
|
||||
MSB or LSB order in transmission */
|
||||
ret = mxl111sf_read_reg(state,
|
||||
V6_MPEG_INOUT_BIT_ORDER_CTRL_REG,
|
||||
&tmp);
|
||||
mxl_fail(ret);
|
||||
|
||||
if (msb_lsb_1st == MPEG_SER_MSB_FIRST_ENABLED)
|
||||
tmp |= V6_MPEG_SER_MSB_FIRST;
|
||||
else
|
||||
tmp &= ~V6_MPEG_SER_MSB_FIRST;
|
||||
|
||||
ret = mxl111sf_write_reg(state,
|
||||
V6_MPEG_INOUT_BIT_ORDER_CTRL_REG,
|
||||
tmp);
|
||||
mxl_fail(ret);
|
||||
}
|
||||
|
||||
/* MPEG Sync polarity */
|
||||
if (mpeg_sync_pol == TSIF_NORMAL)
|
||||
mode &= ~V6_INVERTED_MPEG_SYNC;
|
||||
else
|
||||
mode |= V6_INVERTED_MPEG_SYNC;
|
||||
|
||||
/* MPEG Valid polarity */
|
||||
if (mpeg_valid_pol == 0)
|
||||
mode &= ~V6_INVERTED_MPEG_VALID;
|
||||
else
|
||||
mode |= V6_INVERTED_MPEG_VALID;
|
||||
|
||||
ret = mxl111sf_write_reg(state, V6_MPEG_IN_CTRL_REG, mode);
|
||||
mxl_fail(ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mxl111sf_init_i2s_port(struct mxl111sf_state *state, u8 sample_size)
|
||||
{
|
||||
static struct mxl111sf_reg_ctrl_info init_i2s[] = {
|
||||
{0x1b, 0xff, 0x1e}, /* pin mux mode, Choose 656/I2S input */
|
||||
{0x15, 0x60, 0x60}, /* Enable I2S */
|
||||
{0x17, 0xe0, 0x20}, /* Input, MPEG MODE USB,
|
||||
Inverted 656 Clock, I2S_SOFT_RESET,
|
||||
0 : Normal operation, 1 : Reset State */
|
||||
#if 0
|
||||
{0x12, 0x01, 0x00}, /* AUDIO_IRQ_CLR (Overflow Indicator) */
|
||||
#endif
|
||||
{0x00, 0xff, 0x02}, /* Change to Control Page */
|
||||
{0x26, 0x0d, 0x0d}, /* I2S_MODE & BT656_SRC_SEL for FPGA only */
|
||||
{0x00, 0xff, 0x00},
|
||||
{0, 0, 0}
|
||||
};
|
||||
int ret;
|
||||
|
||||
mxl_debug("(0x%02x)", sample_size);
|
||||
|
||||
ret = mxl111sf_ctrl_program_regs(state, init_i2s);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
ret = mxl111sf_write_reg(state, V6_I2S_NUM_SAMPLES_REG, sample_size);
|
||||
mxl_fail(ret);
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mxl111sf_disable_i2s_port(struct mxl111sf_state *state)
|
||||
{
|
||||
static struct mxl111sf_reg_ctrl_info disable_i2s[] = {
|
||||
{0x15, 0x40, 0x00},
|
||||
{0, 0, 0}
|
||||
};
|
||||
|
||||
mxl_debug("()");
|
||||
|
||||
return mxl111sf_ctrl_program_regs(state, disable_i2s);
|
||||
}
|
||||
|
||||
int mxl111sf_config_i2s(struct mxl111sf_state *state,
|
||||
u8 msb_start_pos, u8 data_width)
|
||||
{
|
||||
int ret;
|
||||
u8 tmp;
|
||||
|
||||
mxl_debug("(0x%02x, 0x%02x)", msb_start_pos, data_width);
|
||||
|
||||
ret = mxl111sf_read_reg(state, V6_I2S_STREAM_START_BIT_REG, &tmp);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
tmp &= 0xe0;
|
||||
tmp |= msb_start_pos;
|
||||
ret = mxl111sf_write_reg(state, V6_I2S_STREAM_START_BIT_REG, tmp);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
ret = mxl111sf_read_reg(state, V6_I2S_STREAM_END_BIT_REG, &tmp);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
tmp &= 0xe0;
|
||||
tmp |= data_width;
|
||||
ret = mxl111sf_write_reg(state, V6_I2S_STREAM_END_BIT_REG, tmp);
|
||||
mxl_fail(ret);
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mxl111sf_config_spi(struct mxl111sf_state *state, int onoff)
|
||||
{
|
||||
u8 val;
|
||||
int ret;
|
||||
|
||||
mxl_debug("(%d)", onoff);
|
||||
|
||||
ret = mxl111sf_write_reg(state, 0x00, 0x02);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
ret = mxl111sf_read_reg(state, V8_SPI_MODE_REG, &val);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
if (onoff)
|
||||
val |= 0x04;
|
||||
else
|
||||
val &= ~0x04;
|
||||
|
||||
ret = mxl111sf_write_reg(state, V8_SPI_MODE_REG, val);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
ret = mxl111sf_write_reg(state, 0x00, 0x00);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mxl111sf_idac_config(struct mxl111sf_state *state,
|
||||
u8 control_mode, u8 current_setting,
|
||||
u8 current_value, u8 hysteresis_value)
|
||||
{
|
||||
int ret;
|
||||
u8 val;
|
||||
/* current value will be set for both automatic & manual IDAC control */
|
||||
val = current_value;
|
||||
|
||||
if (control_mode == IDAC_MANUAL_CONTROL) {
|
||||
/* enable manual control of IDAC */
|
||||
val |= IDAC_MANUAL_CONTROL_BIT_MASK;
|
||||
|
||||
if (current_setting == IDAC_CURRENT_SINKING_ENABLE)
|
||||
/* enable current sinking in manual mode */
|
||||
val |= IDAC_CURRENT_SINKING_BIT_MASK;
|
||||
else
|
||||
/* disable current sinking in manual mode */
|
||||
val &= ~IDAC_CURRENT_SINKING_BIT_MASK;
|
||||
} else {
|
||||
/* disable manual control of IDAC */
|
||||
val &= ~IDAC_MANUAL_CONTROL_BIT_MASK;
|
||||
|
||||
/* set hysteresis value reg: 0x0B<5:0> */
|
||||
ret = mxl111sf_write_reg(state, V6_IDAC_HYSTERESIS_REG,
|
||||
(hysteresis_value & 0x3F));
|
||||
}
|
||||
|
||||
ret = mxl111sf_write_reg(state, V6_IDAC_SETTINGS_REG, val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
* End:
|
||||
*/
|
53
drivers/media/dvb/dvb-usb/mxl111sf-phy.h
Normal file
53
drivers/media/dvb/dvb-usb/mxl111sf-phy.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* mxl111sf-phy.h - driver for the MaxLinear MXL111SF
|
||||
*
|
||||
* Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef _DVB_USB_MXL111SF_PHY_H_
|
||||
#define _DVB_USB_MXL111SF_PHY_H_
|
||||
|
||||
#include "mxl111sf.h"
|
||||
|
||||
int mxl1x1sf_soft_reset(struct mxl111sf_state *state);
|
||||
int mxl1x1sf_set_device_mode(struct mxl111sf_state *state, int mode);
|
||||
int mxl1x1sf_top_master_ctrl(struct mxl111sf_state *state, int onoff);
|
||||
int mxl111sf_disable_656_port(struct mxl111sf_state *state);
|
||||
int mxl111sf_init_tuner_demod(struct mxl111sf_state *state);
|
||||
int mxl111sf_enable_usb_output(struct mxl111sf_state *state);
|
||||
int mxl111sf_config_mpeg_in(struct mxl111sf_state *state,
|
||||
unsigned int parallel_serial,
|
||||
unsigned int msb_lsb_1st,
|
||||
unsigned int clock_phase,
|
||||
unsigned int mpeg_valid_pol,
|
||||
unsigned int mpeg_sync_pol);
|
||||
int mxl111sf_config_i2s(struct mxl111sf_state *state,
|
||||
u8 msb_start_pos, u8 data_width);
|
||||
int mxl111sf_init_i2s_port(struct mxl111sf_state *state, u8 sample_size);
|
||||
int mxl111sf_disable_i2s_port(struct mxl111sf_state *state);
|
||||
int mxl111sf_config_spi(struct mxl111sf_state *state, int onoff);
|
||||
int mxl111sf_idac_config(struct mxl111sf_state *state,
|
||||
u8 control_mode, u8 current_setting,
|
||||
u8 current_value, u8 hysteresis_value);
|
||||
|
||||
#endif /* _DVB_USB_MXL111SF_PHY_H_ */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
* End:
|
||||
*/
|
179
drivers/media/dvb/dvb-usb/mxl111sf-reg.h
Normal file
179
drivers/media/dvb/dvb-usb/mxl111sf-reg.h
Normal file
@ -0,0 +1,179 @@
|
||||
/*
|
||||
* mxl111sf-reg.h - driver for the MaxLinear MXL111SF
|
||||
*
|
||||
* Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef _DVB_USB_MXL111SF_REG_H_
|
||||
#define _DVB_USB_MXL111SF_REG_H_
|
||||
|
||||
#define CHIP_ID_REG 0xFC
|
||||
#define TOP_CHIP_REV_ID_REG 0xFA
|
||||
|
||||
#define V6_SNR_RB_LSB_REG 0x27
|
||||
#define V6_SNR_RB_MSB_REG 0x28
|
||||
|
||||
#define V6_N_ACCUMULATE_REG 0x11
|
||||
#define V6_RS_AVG_ERRORS_LSB_REG 0x2C
|
||||
#define V6_RS_AVG_ERRORS_MSB_REG 0x2D
|
||||
|
||||
#define V6_IRQ_STATUS_REG 0x24
|
||||
#define IRQ_MASK_FEC_LOCK 0x10
|
||||
|
||||
#define V6_SYNC_LOCK_REG 0x28
|
||||
#define SYNC_LOCK_MASK 0x10
|
||||
|
||||
#define V6_RS_LOCK_DET_REG 0x28
|
||||
#define RS_LOCK_DET_MASK 0x08
|
||||
|
||||
#define V6_INITACQ_NODETECT_REG 0x20
|
||||
#define V6_FORCE_NFFT_CPSIZE_REG 0x20
|
||||
|
||||
#define V6_CODE_RATE_TPS_REG 0x29
|
||||
#define V6_CODE_RATE_TPS_MASK 0x07
|
||||
|
||||
|
||||
#define V6_CP_LOCK_DET_REG 0x28
|
||||
#define V6_CP_LOCK_DET_MASK 0x04
|
||||
|
||||
#define V6_TPS_HIERACHY_REG 0x29
|
||||
#define V6_TPS_HIERARCHY_INFO_MASK 0x40
|
||||
|
||||
#define V6_MODORDER_TPS_REG 0x2A
|
||||
#define V6_PARAM_CONSTELLATION_MASK 0x30
|
||||
|
||||
#define V6_MODE_TPS_REG 0x2A
|
||||
#define V6_PARAM_FFT_MODE_MASK 0x0C
|
||||
|
||||
|
||||
#define V6_CP_TPS_REG 0x29
|
||||
#define V6_PARAM_GI_MASK 0x30
|
||||
|
||||
#define V6_TPS_LOCK_REG 0x2A
|
||||
#define V6_PARAM_TPS_LOCK_MASK 0x40
|
||||
|
||||
#define V6_FEC_PER_COUNT_REG 0x2E
|
||||
#define V6_FEC_PER_SCALE_REG 0x2B
|
||||
#define V6_FEC_PER_SCALE_MASK 0x03
|
||||
#define V6_FEC_PER_CLR_REG 0x20
|
||||
#define V6_FEC_PER_CLR_MASK 0x01
|
||||
|
||||
#define V6_PIN_MUX_MODE_REG 0x1B
|
||||
#define V6_ENABLE_PIN_MUX 0x1E
|
||||
|
||||
#define V6_I2S_NUM_SAMPLES_REG 0x16
|
||||
|
||||
#define V6_MPEG_IN_CLK_INV_REG 0x17
|
||||
#define V6_MPEG_IN_CTRL_REG 0x18
|
||||
|
||||
#define V6_INVERTED_CLK_PHASE 0x20
|
||||
#define V6_MPEG_IN_DATA_PARALLEL 0x01
|
||||
#define V6_MPEG_IN_DATA_SERIAL 0x02
|
||||
|
||||
#define V6_INVERTED_MPEG_SYNC 0x04
|
||||
#define V6_INVERTED_MPEG_VALID 0x08
|
||||
|
||||
#define TSIF_INPUT_PARALLEL 0
|
||||
#define TSIF_INPUT_SERIAL 1
|
||||
#define TSIF_NORMAL 0
|
||||
|
||||
#define V6_MPEG_INOUT_BIT_ORDER_CTRL_REG 0x19
|
||||
#define V6_MPEG_SER_MSB_FIRST 0x80
|
||||
#define MPEG_SER_MSB_FIRST_ENABLED 0x01
|
||||
|
||||
#define V6_656_I2S_BUFF_STATUS_REG 0x2F
|
||||
#define V6_656_OVERFLOW_MASK_BIT 0x08
|
||||
#define V6_I2S_OVERFLOW_MASK_BIT 0x01
|
||||
|
||||
#define V6_I2S_STREAM_START_BIT_REG 0x14
|
||||
#define V6_I2S_STREAM_END_BIT_REG 0x15
|
||||
#define I2S_RIGHT_JUSTIFIED 0
|
||||
#define I2S_LEFT_JUSTIFIED 1
|
||||
#define I2S_DATA_FORMAT 2
|
||||
|
||||
#define V6_TUNER_LOOP_THRU_CONTROL_REG 0x09
|
||||
#define V6_ENABLE_LOOP_THRU 0x01
|
||||
|
||||
#define TOTAL_NUM_IF_OUTPUT_FREQ 16
|
||||
|
||||
#define TUNER_NORMAL_IF_SPECTRUM 0x0
|
||||
#define TUNER_INVERT_IF_SPECTRUM 0x10
|
||||
|
||||
#define V6_TUNER_IF_SEL_REG 0x06
|
||||
#define V6_TUNER_IF_FCW_REG 0x3C
|
||||
#define V6_TUNER_IF_FCW_BYP_REG 0x3D
|
||||
#define V6_RF_LOCK_STATUS_REG 0x23
|
||||
|
||||
#define NUM_DIG_TV_CHANNEL 1000
|
||||
|
||||
#define V6_DIG_CLK_FREQ_SEL_REG 0x07
|
||||
#define V6_REF_SYNTH_INT_REG 0x5C
|
||||
#define V6_REF_SYNTH_REMAIN_REG 0x58
|
||||
#define V6_DIG_RFREFSELECT_REG 0x32
|
||||
#define V6_XTAL_CLK_OUT_GAIN_REG 0x31
|
||||
#define V6_TUNER_LOOP_THRU_CTRL_REG 0x09
|
||||
#define V6_DIG_XTAL_ENABLE_REG 0x06
|
||||
#define V6_DIG_XTAL_BIAS_REG 0x66
|
||||
#define V6_XTAL_CAP_REG 0x08
|
||||
|
||||
#define V6_GPO_CTRL_REG 0x18
|
||||
#define MXL_GPO_0 0x00
|
||||
#define MXL_GPO_1 0x01
|
||||
#define V6_GPO_0_MASK 0x10
|
||||
#define V6_GPO_1_MASK 0x20
|
||||
|
||||
#define V6_111SF_GPO_CTRL_REG 0x19
|
||||
#define MXL_111SF_GPO_1 0x00
|
||||
#define MXL_111SF_GPO_2 0x01
|
||||
#define MXL_111SF_GPO_3 0x02
|
||||
#define MXL_111SF_GPO_4 0x03
|
||||
#define MXL_111SF_GPO_5 0x04
|
||||
#define MXL_111SF_GPO_6 0x05
|
||||
#define MXL_111SF_GPO_7 0x06
|
||||
|
||||
#define MXL_111SF_GPO_0_MASK 0x01
|
||||
#define MXL_111SF_GPO_1_MASK 0x02
|
||||
#define MXL_111SF_GPO_2_MASK 0x04
|
||||
#define MXL_111SF_GPO_3_MASK 0x08
|
||||
#define MXL_111SF_GPO_4_MASK 0x10
|
||||
#define MXL_111SF_GPO_5_MASK 0x20
|
||||
#define MXL_111SF_GPO_6_MASK 0x40
|
||||
|
||||
#define V6_ATSC_CONFIG_REG 0x0A
|
||||
|
||||
#define MXL_MODE_REG 0x03
|
||||
#define START_TUNE_REG 0x1C
|
||||
|
||||
#define V6_IDAC_HYSTERESIS_REG 0x0B
|
||||
#define V6_IDAC_SETTINGS_REG 0x0C
|
||||
#define IDAC_MANUAL_CONTROL 1
|
||||
#define IDAC_CURRENT_SINKING_ENABLE 1
|
||||
#define IDAC_MANUAL_CONTROL_BIT_MASK 0x80
|
||||
#define IDAC_CURRENT_SINKING_BIT_MASK 0x40
|
||||
|
||||
#define V8_SPI_MODE_REG 0xE9
|
||||
|
||||
#define V6_DIG_RF_PWR_LSB_REG 0x46
|
||||
#define V6_DIG_RF_PWR_MSB_REG 0x47
|
||||
|
||||
#endif /* _DVB_USB_MXL111SF_REG_H_ */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
* End:
|
||||
*/
|
476
drivers/media/dvb/dvb-usb/mxl111sf-tuner.c
Normal file
476
drivers/media/dvb/dvb-usb/mxl111sf-tuner.c
Normal file
@ -0,0 +1,476 @@
|
||||
/*
|
||||
* mxl111sf-tuner.c - driver for the MaxLinear MXL111SF CMOS tuner
|
||||
*
|
||||
* Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "mxl111sf-tuner.h"
|
||||
#include "mxl111sf-phy.h"
|
||||
#include "mxl111sf-reg.h"
|
||||
|
||||
/* debug */
|
||||
static int mxl111sf_tuner_debug;
|
||||
module_param_named(debug, mxl111sf_tuner_debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able)).");
|
||||
|
||||
#define mxl_dbg(fmt, arg...) \
|
||||
if (mxl111sf_tuner_debug) \
|
||||
mxl_printk(KERN_DEBUG, fmt, ##arg)
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
struct mxl111sf_tuner_state {
|
||||
struct mxl111sf_state *mxl_state;
|
||||
|
||||
struct mxl111sf_tuner_config *cfg;
|
||||
|
||||
u32 frequency;
|
||||
u32 bandwidth;
|
||||
};
|
||||
|
||||
static int mxl111sf_tuner_read_reg(struct mxl111sf_tuner_state *state,
|
||||
u8 addr, u8 *data)
|
||||
{
|
||||
return (state->cfg->read_reg) ?
|
||||
state->cfg->read_reg(state->mxl_state, addr, data) :
|
||||
-EINVAL;
|
||||
}
|
||||
|
||||
static int mxl111sf_tuner_write_reg(struct mxl111sf_tuner_state *state,
|
||||
u8 addr, u8 data)
|
||||
{
|
||||
return (state->cfg->write_reg) ?
|
||||
state->cfg->write_reg(state->mxl_state, addr, data) :
|
||||
-EINVAL;
|
||||
}
|
||||
|
||||
static int mxl111sf_tuner_program_regs(struct mxl111sf_tuner_state *state,
|
||||
struct mxl111sf_reg_ctrl_info *ctrl_reg_info)
|
||||
{
|
||||
return (state->cfg->program_regs) ?
|
||||
state->cfg->program_regs(state->mxl_state, ctrl_reg_info) :
|
||||
-EINVAL;
|
||||
}
|
||||
|
||||
static int mxl1x1sf_tuner_top_master_ctrl(struct mxl111sf_tuner_state *state,
|
||||
int onoff)
|
||||
{
|
||||
return (state->cfg->top_master_ctrl) ?
|
||||
state->cfg->top_master_ctrl(state->mxl_state, onoff) :
|
||||
-EINVAL;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
static struct mxl111sf_reg_ctrl_info mxl_phy_tune_rf[] = {
|
||||
{0x1d, 0x7f, 0x00}, /* channel bandwidth section 1/2/3,
|
||||
DIG_MODEINDEX, _A, _CSF, */
|
||||
{0x1e, 0xff, 0x00}, /* channel frequency (lo and fractional) */
|
||||
{0x1f, 0xff, 0x00}, /* channel frequency (hi for integer portion) */
|
||||
{0, 0, 0}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
static struct mxl111sf_reg_ctrl_info *mxl111sf_calc_phy_tune_regs(u32 freq,
|
||||
u8 bw)
|
||||
{
|
||||
u8 filt_bw;
|
||||
|
||||
/* set channel bandwidth */
|
||||
switch (bw) {
|
||||
case 0: /* ATSC */
|
||||
filt_bw = 25;
|
||||
break;
|
||||
case 1: /* QAM */
|
||||
filt_bw = 69;
|
||||
break;
|
||||
case 6:
|
||||
filt_bw = 21;
|
||||
break;
|
||||
case 7:
|
||||
filt_bw = 42;
|
||||
break;
|
||||
case 8:
|
||||
filt_bw = 63;
|
||||
break;
|
||||
default:
|
||||
err("%s: invalid bandwidth setting!", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* calculate RF channel */
|
||||
freq /= 1000000;
|
||||
|
||||
freq *= 64;
|
||||
#if 0
|
||||
/* do round */
|
||||
freq += 0.5;
|
||||
#endif
|
||||
/* set bandwidth */
|
||||
mxl_phy_tune_rf[0].data = filt_bw;
|
||||
|
||||
/* set RF */
|
||||
mxl_phy_tune_rf[1].data = (freq & 0xff);
|
||||
mxl_phy_tune_rf[2].data = (freq >> 8) & 0xff;
|
||||
|
||||
/* start tune */
|
||||
return mxl_phy_tune_rf;
|
||||
}
|
||||
|
||||
static int mxl1x1sf_tuner_set_if_output_freq(struct mxl111sf_tuner_state *state)
|
||||
{
|
||||
int ret;
|
||||
u8 ctrl;
|
||||
#if 0
|
||||
u16 iffcw;
|
||||
u32 if_freq;
|
||||
#endif
|
||||
mxl_dbg("(IF polarity = %d, IF freq = 0x%02x)",
|
||||
state->cfg->invert_spectrum, state->cfg->if_freq);
|
||||
|
||||
/* set IF polarity */
|
||||
ctrl = state->cfg->invert_spectrum;
|
||||
|
||||
ctrl |= state->cfg->if_freq;
|
||||
|
||||
ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_SEL_REG, ctrl);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
#if 0
|
||||
if_freq /= 1000000;
|
||||
|
||||
/* do round */
|
||||
if_freq += 0.5;
|
||||
|
||||
if (MXL_IF_LO == state->cfg->if_freq) {
|
||||
ctrl = 0x08;
|
||||
iffcw = (u16)(if_freq / (108 * 4096));
|
||||
} else if (MXL_IF_HI == state->cfg->if_freq) {
|
||||
ctrl = 0x08;
|
||||
iffcw = (u16)(if_freq / (216 * 4096));
|
||||
} else {
|
||||
ctrl = 0;
|
||||
iffcw = 0;
|
||||
}
|
||||
|
||||
ctrl |= (iffcw >> 8);
|
||||
#endif
|
||||
ret = mxl111sf_tuner_read_reg(state, V6_TUNER_IF_FCW_BYP_REG, &ctrl);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
ctrl &= 0xf0;
|
||||
ctrl |= 0x90;
|
||||
|
||||
ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_FCW_BYP_REG, ctrl);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
#if 0
|
||||
ctrl = iffcw & 0x00ff;
|
||||
#endif
|
||||
ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_FCW_REG, ctrl);
|
||||
mxl_fail(ret);
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mxl1x1sf_tune_rf(struct dvb_frontend *fe, u32 freq, u8 bw)
|
||||
{
|
||||
struct mxl111sf_tuner_state *state = fe->tuner_priv;
|
||||
static struct mxl111sf_reg_ctrl_info *reg_ctrl_array;
|
||||
int ret;
|
||||
u8 mxl_mode;
|
||||
|
||||
mxl_dbg("(freq = %d, bw = 0x%x)", freq, bw);
|
||||
|
||||
/* stop tune */
|
||||
ret = mxl111sf_tuner_write_reg(state, START_TUNE_REG, 0);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
/* check device mode */
|
||||
ret = mxl111sf_tuner_read_reg(state, MXL_MODE_REG, &mxl_mode);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
/* Fill out registers for channel tune */
|
||||
reg_ctrl_array = mxl111sf_calc_phy_tune_regs(freq, bw);
|
||||
if (!reg_ctrl_array)
|
||||
return -EINVAL;
|
||||
|
||||
ret = mxl111sf_tuner_program_regs(state, reg_ctrl_array);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
if ((mxl_mode & MXL_DEV_MODE_MASK) == MXL_TUNER_MODE) {
|
||||
/* IF tuner mode only */
|
||||
mxl1x1sf_tuner_top_master_ctrl(state, 0);
|
||||
mxl1x1sf_tuner_top_master_ctrl(state, 1);
|
||||
mxl1x1sf_tuner_set_if_output_freq(state);
|
||||
}
|
||||
|
||||
ret = mxl111sf_tuner_write_reg(state, START_TUNE_REG, 1);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
if (state->cfg->ant_hunt)
|
||||
state->cfg->ant_hunt(fe);
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mxl1x1sf_tuner_get_lock_status(struct mxl111sf_tuner_state *state,
|
||||
int *rf_synth_lock,
|
||||
int *ref_synth_lock)
|
||||
{
|
||||
int ret;
|
||||
u8 data;
|
||||
|
||||
*rf_synth_lock = 0;
|
||||
*ref_synth_lock = 0;
|
||||
|
||||
ret = mxl111sf_tuner_read_reg(state, V6_RF_LOCK_STATUS_REG, &data);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
*ref_synth_lock = ((data & 0x03) == 0x03) ? 1 : 0;
|
||||
*rf_synth_lock = ((data & 0x0c) == 0x0c) ? 1 : 0;
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int mxl1x1sf_tuner_loop_thru_ctrl(struct mxl111sf_tuner_state *state,
|
||||
int onoff)
|
||||
{
|
||||
return mxl111sf_tuner_write_reg(state, V6_TUNER_LOOP_THRU_CTRL_REG,
|
||||
onoff ? 1 : 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
static int mxl111sf_tuner_set_params(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *params)
|
||||
{
|
||||
struct mxl111sf_tuner_state *state = fe->tuner_priv;
|
||||
int ret;
|
||||
u8 bw;
|
||||
|
||||
mxl_dbg("()");
|
||||
|
||||
if (fe->ops.info.type == FE_ATSC) {
|
||||
switch (params->u.vsb.modulation) {
|
||||
case VSB_8:
|
||||
case VSB_16:
|
||||
bw = 0; /* ATSC */
|
||||
break;
|
||||
case QAM_64:
|
||||
case QAM_256:
|
||||
bw = 1; /* US CABLE */
|
||||
break;
|
||||
default:
|
||||
err("%s: modulation not set!", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (fe->ops.info.type == FE_OFDM) {
|
||||
switch (params->u.ofdm.bandwidth) {
|
||||
case BANDWIDTH_6_MHZ:
|
||||
bw = 6;
|
||||
break;
|
||||
case BANDWIDTH_7_MHZ:
|
||||
bw = 7;
|
||||
break;
|
||||
case BANDWIDTH_8_MHZ:
|
||||
bw = 8;
|
||||
break;
|
||||
default:
|
||||
err("%s: bandwidth not set!", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
err("%s: modulation type not supported!", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = mxl1x1sf_tune_rf(fe, params->frequency, bw);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
state->frequency = params->frequency;
|
||||
state->bandwidth = (fe->ops.info.type == FE_OFDM) ?
|
||||
params->u.ofdm.bandwidth : 0;
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
#if 0
|
||||
static int mxl111sf_tuner_init(struct dvb_frontend *fe)
|
||||
{
|
||||
struct mxl111sf_tuner_state *state = fe->tuner_priv;
|
||||
int ret;
|
||||
|
||||
/* wake from standby handled by usb driver */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mxl111sf_tuner_sleep(struct dvb_frontend *fe)
|
||||
{
|
||||
struct mxl111sf_tuner_state *state = fe->tuner_priv;
|
||||
int ret;
|
||||
|
||||
/* enter standby mode handled by usb driver */
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
static int mxl111sf_tuner_get_status(struct dvb_frontend *fe, u32 *status)
|
||||
{
|
||||
struct mxl111sf_tuner_state *state = fe->tuner_priv;
|
||||
int rf_locked, ref_locked, ret;
|
||||
|
||||
*status = 0;
|
||||
|
||||
ret = mxl1x1sf_tuner_get_lock_status(state, &rf_locked, &ref_locked);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
mxl_info("%s%s", rf_locked ? "rf locked " : "",
|
||||
ref_locked ? "ref locked" : "");
|
||||
|
||||
if ((rf_locked) || (ref_locked))
|
||||
*status |= TUNER_STATUS_LOCKED;
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mxl111sf_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
|
||||
{
|
||||
struct mxl111sf_tuner_state *state = fe->tuner_priv;
|
||||
u8 val1, val2;
|
||||
int ret;
|
||||
|
||||
*strength = 0;
|
||||
|
||||
ret = mxl111sf_tuner_write_reg(state, 0x00, 0x02);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
ret = mxl111sf_tuner_read_reg(state, V6_DIG_RF_PWR_LSB_REG, &val1);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
ret = mxl111sf_tuner_read_reg(state, V6_DIG_RF_PWR_MSB_REG, &val2);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
*strength = val1 | ((val2 & 0x07) << 8);
|
||||
fail:
|
||||
ret = mxl111sf_tuner_write_reg(state, 0x00, 0x00);
|
||||
mxl_fail(ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
static int mxl111sf_tuner_get_frequency(struct dvb_frontend *fe, u32 *frequency)
|
||||
{
|
||||
struct mxl111sf_tuner_state *state = fe->tuner_priv;
|
||||
*frequency = state->frequency;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mxl111sf_tuner_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
|
||||
{
|
||||
struct mxl111sf_tuner_state *state = fe->tuner_priv;
|
||||
*bandwidth = state->bandwidth;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mxl111sf_tuner_release(struct dvb_frontend *fe)
|
||||
{
|
||||
struct mxl111sf_tuner_state *state = fe->tuner_priv;
|
||||
mxl_dbg("()");
|
||||
kfree(state);
|
||||
fe->tuner_priv = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static struct dvb_tuner_ops mxl111sf_tuner_tuner_ops = {
|
||||
.info = {
|
||||
.name = "MaxLinear MxL111SF",
|
||||
#if 0
|
||||
.frequency_min = ,
|
||||
.frequency_max = ,
|
||||
.frequency_step = ,
|
||||
#endif
|
||||
},
|
||||
#if 0
|
||||
.init = mxl111sf_tuner_init,
|
||||
.sleep = mxl111sf_tuner_sleep,
|
||||
#endif
|
||||
.set_params = mxl111sf_tuner_set_params,
|
||||
.get_status = mxl111sf_tuner_get_status,
|
||||
.get_rf_strength = mxl111sf_get_rf_strength,
|
||||
.get_frequency = mxl111sf_tuner_get_frequency,
|
||||
.get_bandwidth = mxl111sf_tuner_get_bandwidth,
|
||||
.release = mxl111sf_tuner_release,
|
||||
};
|
||||
|
||||
struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe,
|
||||
struct mxl111sf_state *mxl_state,
|
||||
struct mxl111sf_tuner_config *cfg)
|
||||
{
|
||||
struct mxl111sf_tuner_state *state = NULL;
|
||||
|
||||
mxl_dbg("()");
|
||||
|
||||
state = kzalloc(sizeof(struct mxl111sf_tuner_state), GFP_KERNEL);
|
||||
if (state == NULL)
|
||||
return NULL;
|
||||
|
||||
state->mxl_state = mxl_state;
|
||||
state->cfg = cfg;
|
||||
|
||||
memcpy(&fe->ops.tuner_ops, &mxl111sf_tuner_tuner_ops,
|
||||
sizeof(struct dvb_tuner_ops));
|
||||
|
||||
fe->tuner_priv = state;
|
||||
return fe;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mxl111sf_tuner_attach);
|
||||
|
||||
MODULE_DESCRIPTION("MaxLinear MxL111SF CMOS tuner driver");
|
||||
MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION("0.1");
|
||||
|
||||
/*
|
||||
* Overrides for Emacs so that we follow Linus's tabbing style.
|
||||
* ---------------------------------------------------------------------------
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
* End:
|
||||
*/
|
89
drivers/media/dvb/dvb-usb/mxl111sf-tuner.h
Normal file
89
drivers/media/dvb/dvb-usb/mxl111sf-tuner.h
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* mxl111sf-tuner.h - driver for the MaxLinear MXL111SF CMOS tuner
|
||||
*
|
||||
* Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __MXL111SF_TUNER_H__
|
||||
#define __MXL111SF_TUNER_H__
|
||||
|
||||
#include "dvb_frontend.h"
|
||||
|
||||
#include "mxl111sf.h"
|
||||
|
||||
enum mxl_if_freq {
|
||||
#if 0
|
||||
MXL_IF_LO = 0x00, /* other IF < 9MHz */
|
||||
#endif
|
||||
MXL_IF_4_0 = 0x01, /* 4.0 MHz */
|
||||
MXL_IF_4_5 = 0x02, /* 4.5 MHz */
|
||||
MXL_IF_4_57 = 0x03, /* 4.57 MHz */
|
||||
MXL_IF_5_0 = 0x04, /* 5.0 MHz */
|
||||
MXL_IF_5_38 = 0x05, /* 5.38 MHz */
|
||||
MXL_IF_6_0 = 0x06, /* 6.0 MHz */
|
||||
MXL_IF_6_28 = 0x07, /* 6.28 MHz */
|
||||
MXL_IF_7_2 = 0x08, /* 7.2 MHz */
|
||||
MXL_IF_35_25 = 0x09, /* 35.25 MHz */
|
||||
MXL_IF_36 = 0x0a, /* 36 MHz */
|
||||
MXL_IF_36_15 = 0x0b, /* 36.15 MHz */
|
||||
MXL_IF_44 = 0x0c, /* 44 MHz */
|
||||
#if 0
|
||||
MXL_IF_HI = 0x0f, /* other IF > 35 MHz and < 45 MHz */
|
||||
#endif
|
||||
};
|
||||
|
||||
struct mxl111sf_tuner_config {
|
||||
enum mxl_if_freq if_freq;
|
||||
unsigned int invert_spectrum:1;
|
||||
|
||||
int (*read_reg)(struct mxl111sf_state *state, u8 addr, u8 *data);
|
||||
int (*write_reg)(struct mxl111sf_state *state, u8 addr, u8 data);
|
||||
int (*program_regs)(struct mxl111sf_state *state,
|
||||
struct mxl111sf_reg_ctrl_info *ctrl_reg_info);
|
||||
int (*top_master_ctrl)(struct mxl111sf_state *state, int onoff);
|
||||
int (*ant_hunt)(struct dvb_frontend *fe);
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
#if defined(CONFIG_DVB_USB_MXL111SF) || \
|
||||
(defined(CONFIG_DVB_USB_MXL111SF_MODULE) && defined(MODULE))
|
||||
extern
|
||||
struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe,
|
||||
struct mxl111sf_state *mxl_state,
|
||||
struct mxl111sf_tuner_config *cfg);
|
||||
#else
|
||||
static inline
|
||||
struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe,
|
||||
struct mxl111sf_state *mxl_state
|
||||
struct mxl111sf_tuner_config *cfg)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __MXL111SF_TUNER_H__ */
|
||||
|
||||
/*
|
||||
* Overrides for Emacs so that we follow Linus's tabbing style.
|
||||
* ---------------------------------------------------------------------------
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
* End:
|
||||
*/
|
||||
|
864
drivers/media/dvb/dvb-usb/mxl111sf.c
Normal file
864
drivers/media/dvb/dvb-usb/mxl111sf.c
Normal file
@ -0,0 +1,864 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Michael Krufky (mkrufky@kernellabs.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.
|
||||
*
|
||||
* see Documentation/dvb/README.dvb-usb for more information
|
||||
*/
|
||||
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/i2c.h>
|
||||
|
||||
#include "mxl111sf.h"
|
||||
#include "mxl111sf-reg.h"
|
||||
#include "mxl111sf-phy.h"
|
||||
#include "mxl111sf-i2c.h"
|
||||
#include "mxl111sf-gpio.h"
|
||||
|
||||
#include "mxl111sf-tuner.h"
|
||||
|
||||
#include "lgdt3305.h"
|
||||
|
||||
int dvb_usb_mxl111sf_debug;
|
||||
module_param_named(debug, dvb_usb_mxl111sf_debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "set debugging level "
|
||||
"(1=info, 2=xfer, 4=i2c, 8=reg, 16=adv (or-able)).");
|
||||
|
||||
int dvb_usb_mxl111sf_isoc;
|
||||
module_param_named(isoc, dvb_usb_mxl111sf_isoc, int, 0644);
|
||||
MODULE_PARM_DESC(isoc, "enable usb isoc xfer (0=bulk, 1=isoc).");
|
||||
|
||||
#define ANT_PATH_AUTO 0
|
||||
#define ANT_PATH_EXTERNAL 1
|
||||
#define ANT_PATH_INTERNAL 2
|
||||
|
||||
int dvb_usb_mxl111sf_rfswitch =
|
||||
#if 0
|
||||
ANT_PATH_AUTO;
|
||||
#else
|
||||
ANT_PATH_EXTERNAL;
|
||||
#endif
|
||||
|
||||
module_param_named(rfswitch, dvb_usb_mxl111sf_rfswitch, int, 0644);
|
||||
MODULE_PARM_DESC(rfswitch, "force rf switch position (0=auto, 1=ext, 2=int).");
|
||||
|
||||
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
|
||||
|
||||
#define deb_info(args...) dprintk(dvb_usb_mxl111sf_debug, 0x13, args)
|
||||
#define deb_reg(args...) dprintk(dvb_usb_mxl111sf_debug, 0x08, args)
|
||||
#define deb_adv(args...) dprintk(dvb_usb_mxl111sf_debug, MXL_ADV_DBG, args)
|
||||
|
||||
int mxl111sf_ctrl_msg(struct dvb_usb_device *d,
|
||||
u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
|
||||
{
|
||||
int wo = (rbuf == NULL || rlen == 0); /* write-only */
|
||||
int ret;
|
||||
u8 sndbuf[1+wlen];
|
||||
|
||||
deb_adv("%s(wlen = %d, rlen = %d)\n", __func__, wlen, rlen);
|
||||
|
||||
memset(sndbuf, 0, 1+wlen);
|
||||
|
||||
sndbuf[0] = cmd;
|
||||
memcpy(&sndbuf[1], wbuf, wlen);
|
||||
|
||||
ret = (wo) ? dvb_usb_generic_write(d, sndbuf, 1+wlen) :
|
||||
dvb_usb_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen, 0);
|
||||
mxl_fail(ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
#define MXL_CMD_REG_READ 0xaa
|
||||
#define MXL_CMD_REG_WRITE 0x55
|
||||
|
||||
int mxl111sf_read_reg(struct mxl111sf_state *state, u8 addr, u8 *data)
|
||||
{
|
||||
u8 buf[2];
|
||||
int ret;
|
||||
|
||||
ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_READ, &addr, 1, buf, 2);
|
||||
if (mxl_fail(ret)) {
|
||||
mxl_debug("error reading reg: 0x%02x", addr);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (buf[0] == addr)
|
||||
*data = buf[1];
|
||||
else {
|
||||
err("invalid response reading reg: 0x%02x != 0x%02x, 0x%02x",
|
||||
addr, buf[0], buf[1]);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
deb_reg("R: (0x%02x, 0x%02x)\n", addr, *data);
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mxl111sf_write_reg(struct mxl111sf_state *state, u8 addr, u8 data)
|
||||
{
|
||||
u8 buf[] = { addr, data };
|
||||
int ret;
|
||||
|
||||
deb_reg("W: (0x%02x, 0x%02x)\n", addr, data);
|
||||
|
||||
ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_WRITE, buf, 2, NULL, 0);
|
||||
if (mxl_fail(ret))
|
||||
err("error writing reg: 0x%02x, val: 0x%02x", addr, data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
int mxl111sf_write_reg_mask(struct mxl111sf_state *state,
|
||||
u8 addr, u8 mask, u8 data)
|
||||
{
|
||||
int ret;
|
||||
u8 val;
|
||||
|
||||
if (mask != 0xff) {
|
||||
ret = mxl111sf_read_reg(state, addr, &val);
|
||||
#if 1
|
||||
/* dont know why this usually errors out on the first try */
|
||||
if (mxl_fail(ret))
|
||||
err("error writing addr: 0x%02x, mask: 0x%02x, "
|
||||
"data: 0x%02x, retrying...", addr, mask, data);
|
||||
|
||||
ret = mxl111sf_read_reg(state, addr, &val);
|
||||
#endif
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
}
|
||||
val &= ~mask;
|
||||
val |= data;
|
||||
|
||||
ret = mxl111sf_write_reg(state, addr, val);
|
||||
mxl_fail(ret);
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
int mxl111sf_ctrl_program_regs(struct mxl111sf_state *state,
|
||||
struct mxl111sf_reg_ctrl_info *ctrl_reg_info)
|
||||
{
|
||||
int i, ret = 0;
|
||||
|
||||
for (i = 0; ctrl_reg_info[i].addr |
|
||||
ctrl_reg_info[i].mask |
|
||||
ctrl_reg_info[i].data; i++) {
|
||||
|
||||
ret = mxl111sf_write_reg_mask(state,
|
||||
ctrl_reg_info[i].addr,
|
||||
ctrl_reg_info[i].mask,
|
||||
ctrl_reg_info[i].data);
|
||||
if (mxl_fail(ret)) {
|
||||
err("failed on reg #%d (0x%02x)", i,
|
||||
ctrl_reg_info[i].addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
static int mxl1x1sf_get_chip_info(struct mxl111sf_state *state)
|
||||
{
|
||||
int ret;
|
||||
u8 id, ver;
|
||||
char *mxl_chip, *mxl_rev;
|
||||
|
||||
if ((state->chip_id) && (state->chip_ver))
|
||||
return 0;
|
||||
|
||||
ret = mxl111sf_read_reg(state, CHIP_ID_REG, &id);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
state->chip_id = id;
|
||||
|
||||
ret = mxl111sf_read_reg(state, TOP_CHIP_REV_ID_REG, &ver);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
state->chip_ver = ver;
|
||||
|
||||
switch (id) {
|
||||
case 0x61:
|
||||
mxl_chip = "MxL101SF";
|
||||
break;
|
||||
case 0x63:
|
||||
mxl_chip = "MxL111SF";
|
||||
break;
|
||||
default:
|
||||
mxl_chip = "UNKNOWN MxL1X1";
|
||||
break;
|
||||
}
|
||||
switch (ver) {
|
||||
case 0x36:
|
||||
state->chip_rev = MXL111SF_V6;
|
||||
mxl_rev = "v6";
|
||||
break;
|
||||
case 0x08:
|
||||
state->chip_rev = MXL111SF_V8_100;
|
||||
mxl_rev = "v8_100";
|
||||
break;
|
||||
case 0x18:
|
||||
state->chip_rev = MXL111SF_V8_200;
|
||||
mxl_rev = "v8_200";
|
||||
break;
|
||||
default:
|
||||
state->chip_rev = 0;
|
||||
mxl_rev = "UNKNOWN REVISION";
|
||||
break;
|
||||
}
|
||||
info("%s detected, %s (0x%x)", mxl_chip, mxl_rev, ver);
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define get_chip_info(state) \
|
||||
({ \
|
||||
int ___ret; \
|
||||
___ret = mxl1x1sf_get_chip_info(state); \
|
||||
if (mxl_fail(___ret)) { \
|
||||
mxl_debug("failed to get chip info" \
|
||||
" on first probe attempt"); \
|
||||
___ret = mxl1x1sf_get_chip_info(state); \
|
||||
if (mxl_fail(___ret)) \
|
||||
err("failed to get chip info during probe"); \
|
||||
else \
|
||||
mxl_debug("probe needed a retry " \
|
||||
"in order to succeed."); \
|
||||
} \
|
||||
___ret; \
|
||||
})
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
static int mxl111sf_power_ctrl(struct dvb_usb_device *d, int onoff)
|
||||
{
|
||||
/* power control depends on which adapter is being woken:
|
||||
* save this for init, instead, via mxl111sf_adap_fe_init */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mxl111sf_adap_fe_init(struct dvb_frontend *fe)
|
||||
{
|
||||
struct dvb_usb_adapter *adap = fe->dvb->priv;
|
||||
struct dvb_usb_device *d = adap->dev;
|
||||
struct mxl111sf_state *state = d->priv;
|
||||
struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe->id].priv;
|
||||
|
||||
int err;
|
||||
|
||||
/* exit if we didnt initialize the driver yet */
|
||||
if (!state->chip_id) {
|
||||
mxl_debug("driver not yet initialized, exit.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
deb_info("%s()\n", __func__);
|
||||
|
||||
mutex_lock(&state->fe_lock);
|
||||
|
||||
state->alt_mode = adap_state->alt_mode;
|
||||
|
||||
if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0)
|
||||
err("set interface failed");
|
||||
|
||||
err = mxl1x1sf_soft_reset(state);
|
||||
mxl_fail(err);
|
||||
err = mxl111sf_init_tuner_demod(state);
|
||||
mxl_fail(err);
|
||||
err = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
|
||||
|
||||
mxl_fail(err);
|
||||
mxl111sf_enable_usb_output(state);
|
||||
mxl_fail(err);
|
||||
mxl1x1sf_top_master_ctrl(state, 1);
|
||||
mxl_fail(err);
|
||||
|
||||
if ((MXL111SF_GPIO_MOD_DVBT != adap_state->gpio_mode) &&
|
||||
(state->chip_rev > MXL111SF_V6)) {
|
||||
mxl111sf_config_pin_mux_modes(state,
|
||||
PIN_MUX_TS_SPI_IN_MODE_1);
|
||||
mxl_fail(err);
|
||||
}
|
||||
err = mxl111sf_init_port_expander(state);
|
||||
if (!mxl_fail(err)) {
|
||||
state->gpio_mode = adap_state->gpio_mode;
|
||||
err = mxl111sf_gpio_mode_switch(state, state->gpio_mode);
|
||||
mxl_fail(err);
|
||||
#if 0
|
||||
err = fe->ops.init(fe);
|
||||
#endif
|
||||
msleep(100); /* add short delay after enabling
|
||||
* the demod before touching it */
|
||||
}
|
||||
|
||||
return (adap_state->fe_init) ? adap_state->fe_init(fe) : 0;
|
||||
fail:
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int mxl111sf_adap_fe_sleep(struct dvb_frontend *fe)
|
||||
{
|
||||
struct dvb_usb_adapter *adap = fe->dvb->priv;
|
||||
struct dvb_usb_device *d = adap->dev;
|
||||
struct mxl111sf_state *state = d->priv;
|
||||
struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe->id].priv;
|
||||
int err;
|
||||
|
||||
/* exit if we didnt initialize the driver yet */
|
||||
if (!state->chip_id) {
|
||||
mxl_debug("driver not yet initialized, exit.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
deb_info("%s()\n", __func__);
|
||||
|
||||
err = (adap_state->fe_sleep) ? adap_state->fe_sleep(fe) : 0;
|
||||
|
||||
mutex_unlock(&state->fe_lock);
|
||||
|
||||
return err;
|
||||
fail:
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
||||
static int mxl111sf_ep6_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
||||
{
|
||||
struct dvb_usb_device *d = adap->dev;
|
||||
struct mxl111sf_state *state = d->priv;
|
||||
struct mxl111sf_adap_state *adap_state = adap->fe_adap[adap->active_fe].priv;
|
||||
int ret = 0;
|
||||
u8 tmp;
|
||||
|
||||
deb_info("%s(%d)\n", __func__, onoff);
|
||||
|
||||
if (onoff) {
|
||||
ret = mxl111sf_enable_usb_output(state);
|
||||
mxl_fail(ret);
|
||||
ret = mxl111sf_config_mpeg_in(state, 1, 1,
|
||||
adap_state->ep6_clockphase,
|
||||
0, 0);
|
||||
mxl_fail(ret);
|
||||
} else {
|
||||
ret = mxl111sf_disable_656_port(state);
|
||||
mxl_fail(ret);
|
||||
}
|
||||
|
||||
mxl111sf_read_reg(state, 0x12, &tmp);
|
||||
tmp &= ~0x04;
|
||||
mxl111sf_write_reg(state, 0x12, tmp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
static struct lgdt3305_config hauppauge_lgdt3305_config = {
|
||||
.i2c_addr = 0xb2 >> 1,
|
||||
.mpeg_mode = LGDT3305_MPEG_SERIAL,
|
||||
.tpclk_edge = LGDT3305_TPCLK_RISING_EDGE,
|
||||
.tpvalid_polarity = LGDT3305_TP_VALID_HIGH,
|
||||
.deny_i2c_rptr = 1,
|
||||
.spectral_inversion = 0,
|
||||
.qam_if_khz = 6000,
|
||||
.vsb_if_khz = 6000,
|
||||
};
|
||||
|
||||
static int mxl111sf_lgdt3305_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
struct dvb_usb_device *d = adap->dev;
|
||||
struct mxl111sf_state *state = d->priv;
|
||||
int fe_id = adap->num_frontends_initialized;
|
||||
struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe_id].priv;
|
||||
int ret;
|
||||
|
||||
deb_adv("%s()\n", __func__);
|
||||
|
||||
/* save a pointer to the dvb_usb_device in device state */
|
||||
state->d = d;
|
||||
adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1;
|
||||
state->alt_mode = adap_state->alt_mode;
|
||||
|
||||
if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0)
|
||||
err("set interface failed");
|
||||
|
||||
state->gpio_mode = MXL111SF_GPIO_MOD_ATSC;
|
||||
adap_state->gpio_mode = state->gpio_mode;
|
||||
adap_state->device_mode = MXL_TUNER_MODE;
|
||||
adap_state->ep6_clockphase = 1;
|
||||
|
||||
ret = mxl1x1sf_soft_reset(state);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
ret = mxl111sf_init_tuner_demod(state);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
ret = mxl111sf_enable_usb_output(state);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
ret = mxl1x1sf_top_master_ctrl(state, 1);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
ret = mxl111sf_init_port_expander(state);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
ret = mxl111sf_gpio_mode_switch(state, state->gpio_mode);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
adap->fe_adap[fe_id].fe = dvb_attach(lgdt3305_attach,
|
||||
&hauppauge_lgdt3305_config,
|
||||
&adap->dev->i2c_adap);
|
||||
if (adap->fe_adap[fe_id].fe) {
|
||||
adap_state->fe_init = adap->fe_adap[fe_id].fe->ops.init;
|
||||
adap->fe_adap[fe_id].fe->ops.init = mxl111sf_adap_fe_init;
|
||||
adap_state->fe_sleep = adap->fe_adap[fe_id].fe->ops.sleep;
|
||||
adap->fe_adap[fe_id].fe->ops.sleep = mxl111sf_adap_fe_sleep;
|
||||
return 0;
|
||||
}
|
||||
ret = -EIO;
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int mxl111sf_set_ant_path(struct mxl111sf_state *state,
|
||||
int antpath)
|
||||
{
|
||||
return mxl111sf_idac_config(state, 1, 1,
|
||||
(antpath == ANT_PATH_INTERNAL) ?
|
||||
0x3f : 0x00, 0);
|
||||
}
|
||||
|
||||
#define DbgAntHunt(x, pwr0, pwr1, pwr2, pwr3) \
|
||||
err("%s(%d) FINAL input set to %s rxPwr:%d|%d|%d|%d\n", \
|
||||
__func__, __LINE__, \
|
||||
(ANT_PATH_EXTERNAL == x) ? "EXTERNAL" : "INTERNAL", \
|
||||
pwr0, pwr1, pwr2, pwr3)
|
||||
|
||||
#define ANT_HUNT_SLEEP 90
|
||||
#define ANT_EXT_TWEAK 0
|
||||
|
||||
static int mxl111sf_ant_hunt(struct dvb_frontend *fe)
|
||||
{
|
||||
struct dvb_usb_adapter *adap = fe->dvb->priv;
|
||||
struct dvb_usb_device *d = adap->dev;
|
||||
struct mxl111sf_state *state = d->priv;
|
||||
|
||||
int antctrl = dvb_usb_mxl111sf_rfswitch;
|
||||
|
||||
u16 rxPwrA, rxPwr0, rxPwr1, rxPwr2;
|
||||
|
||||
/* FIXME: must force EXTERNAL for QAM - done elsewhere */
|
||||
mxl111sf_set_ant_path(state, antctrl == ANT_PATH_AUTO ?
|
||||
ANT_PATH_EXTERNAL : antctrl);
|
||||
|
||||
if (antctrl == ANT_PATH_AUTO) {
|
||||
#if 0
|
||||
msleep(ANT_HUNT_SLEEP);
|
||||
#endif
|
||||
fe->ops.tuner_ops.get_rf_strength(fe, &rxPwrA);
|
||||
|
||||
mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL);
|
||||
msleep(ANT_HUNT_SLEEP);
|
||||
fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr0);
|
||||
|
||||
mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL);
|
||||
msleep(ANT_HUNT_SLEEP);
|
||||
fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr1);
|
||||
|
||||
mxl111sf_set_ant_path(state, ANT_PATH_INTERNAL);
|
||||
msleep(ANT_HUNT_SLEEP);
|
||||
fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr2);
|
||||
|
||||
if (rxPwr1+ANT_EXT_TWEAK >= rxPwr2) {
|
||||
/* return with EXTERNAL enabled */
|
||||
mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL);
|
||||
DbgAntHunt(ANT_PATH_EXTERNAL, rxPwrA,
|
||||
rxPwr0, rxPwr1, rxPwr2);
|
||||
} else {
|
||||
/* return with INTERNAL enabled */
|
||||
DbgAntHunt(ANT_PATH_INTERNAL, rxPwrA,
|
||||
rxPwr0, rxPwr1, rxPwr2);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct mxl111sf_tuner_config mxl_tuner_config = {
|
||||
.if_freq = MXL_IF_6_0, /* applies to external IF output, only */
|
||||
.invert_spectrum = 0,
|
||||
.read_reg = mxl111sf_read_reg,
|
||||
.write_reg = mxl111sf_write_reg,
|
||||
.program_regs = mxl111sf_ctrl_program_regs,
|
||||
.top_master_ctrl = mxl1x1sf_top_master_ctrl,
|
||||
.ant_hunt = mxl111sf_ant_hunt,
|
||||
};
|
||||
|
||||
static int mxl111sf_attach_tuner(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
struct dvb_usb_device *d = adap->dev;
|
||||
struct mxl111sf_state *state = d->priv;
|
||||
int fe_id = adap->num_frontends_initialized;
|
||||
|
||||
deb_adv("%s()\n", __func__);
|
||||
|
||||
if (NULL != dvb_attach(mxl111sf_tuner_attach,
|
||||
adap->fe_adap[fe_id].fe, state,
|
||||
&mxl_tuner_config))
|
||||
return 0;
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static int mxl111sf_fe_ioctl_override(struct dvb_frontend *fe,
|
||||
unsigned int cmd, void *parg,
|
||||
unsigned int stage)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
switch (stage) {
|
||||
case DVB_FE_IOCTL_PRE:
|
||||
|
||||
switch (cmd) {
|
||||
case FE_READ_SIGNAL_STRENGTH:
|
||||
err = fe->ops.tuner_ops.get_rf_strength(fe, parg);
|
||||
/* If no error occurs, prevent dvb-core from handling
|
||||
* this IOCTL, otherwise return the error */
|
||||
if (0 == err)
|
||||
err = 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case DVB_FE_IOCTL_POST:
|
||||
/* no post-ioctl handling required */
|
||||
break;
|
||||
}
|
||||
return err;
|
||||
};
|
||||
|
||||
static u32 mxl111sf_i2c_func(struct i2c_adapter *adapter)
|
||||
{
|
||||
return I2C_FUNC_I2C;
|
||||
}
|
||||
|
||||
struct i2c_algorithm mxl111sf_i2c_algo = {
|
||||
.master_xfer = mxl111sf_i2c_xfer,
|
||||
.functionality = mxl111sf_i2c_func,
|
||||
#ifdef NEED_ALGO_CONTROL
|
||||
.algo_control = dummy_algo_control,
|
||||
#endif
|
||||
};
|
||||
|
||||
/* DVB USB Driver stuff */
|
||||
static struct dvb_usb_device_properties mxl111sf_atsc_bulk_properties;
|
||||
static struct dvb_usb_device_properties mxl111sf_atsc_isoc_properties;
|
||||
|
||||
static int mxl111sf_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
struct dvb_usb_device *d = NULL;
|
||||
|
||||
deb_adv("%s()\n", __func__);
|
||||
|
||||
if (((dvb_usb_mxl111sf_isoc) &&
|
||||
(0 == dvb_usb_device_init(intf,
|
||||
&mxl111sf_atsc_isoc_properties,
|
||||
THIS_MODULE, &d, adapter_nr))) ||
|
||||
0 == dvb_usb_device_init(intf,
|
||||
&mxl111sf_atsc_bulk_properties,
|
||||
THIS_MODULE, &d, adapter_nr) || 0) {
|
||||
|
||||
struct mxl111sf_state *state = d->priv;
|
||||
static u8 eeprom[256];
|
||||
struct i2c_client c;
|
||||
int ret;
|
||||
|
||||
ret = get_chip_info(state);
|
||||
if (mxl_fail(ret))
|
||||
err("failed to get chip info during probe");
|
||||
|
||||
mutex_init(&state->fe_lock);
|
||||
|
||||
if (state->chip_rev > MXL111SF_V6)
|
||||
mxl111sf_config_pin_mux_modes(state,
|
||||
PIN_MUX_TS_SPI_IN_MODE_1);
|
||||
|
||||
c.adapter = &d->i2c_adap;
|
||||
c.addr = 0xa0 >> 1;
|
||||
|
||||
ret = tveeprom_read(&c, eeprom, sizeof(eeprom));
|
||||
if (mxl_fail(ret))
|
||||
return 0;
|
||||
tveeprom_hauppauge_analog(&c, &state->tv,
|
||||
(0x84 == eeprom[0xa0]) ?
|
||||
eeprom + 0xa0 : eeprom + 0x80);
|
||||
#if 0
|
||||
switch (state->tv.model) {
|
||||
case 117001:
|
||||
case 126001:
|
||||
case 138001:
|
||||
break;
|
||||
default:
|
||||
printk(KERN_WARNING "%s: warning: "
|
||||
"unknown hauppauge model #%d\n",
|
||||
__func__, state->tv.model);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
err("Your device is not yet supported by this driver. "
|
||||
"See kernellabs.com for more info");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static struct usb_device_id mxl111sf_table[] = {
|
||||
/* 0 */ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc600) }, /* ATSC+ IR */
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc601) }, /* ATSC */
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc602) }, /* + */
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc603) }, /* ATSC+ */
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc604) }, /* DVBT */
|
||||
/* 5 */ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc609) }, /* ATSC IR */
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60a) }, /* + IR */
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60b) }, /* ATSC+ IR */
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60c) }, /* DVBT IR */
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc653) }, /* ATSC+ */
|
||||
/*10 */ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc65b) }, /* ATSC+ IR */
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb700) }, /* ATSC+ sw */
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb701) }, /* ATSC sw */
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb702) }, /* + sw */
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb703) }, /* ATSC+ sw */
|
||||
/*15 */ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb704) }, /* DVBT sw */
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb753) }, /* ATSC+ sw */
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb763) }, /* ATSC+ no */
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb764) }, /* DVBT no */
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd853) }, /* ATSC+ sw */
|
||||
/*20 */ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd854) }, /* DVBT sw */
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd863) }, /* ATSC+ no */
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd864) }, /* DVBT no */
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8d3) }, /* ATSC+ sw */
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8d4) }, /* DVBT sw */
|
||||
/*25 */ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8e3) }, /* ATSC+ no */
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8e4) }, /* DVBT no */
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8ff) }, /* ATSC+ */
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc612) }, /* + */
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc613) }, /* ATSC+ */
|
||||
/*30 */ { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc61a) }, /* + IR */
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc61b) }, /* ATSC+ IR */
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb757) }, /* ATSC+DVBT sw */
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb767) }, /* ATSC+DVBT no */
|
||||
{} /* Terminating entry */
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, mxl111sf_table);
|
||||
|
||||
|
||||
#define MXL111SF_EP6_BULK_STREAMING_CONFIG \
|
||||
.streaming_ctrl = mxl111sf_ep6_streaming_ctrl, \
|
||||
.stream = { \
|
||||
.type = USB_BULK, \
|
||||
.count = 5, \
|
||||
.endpoint = 0x06, \
|
||||
.u = { \
|
||||
.bulk = { \
|
||||
.buffersize = 8192, \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
/* FIXME */
|
||||
#define MXL111SF_EP6_ISOC_STREAMING_CONFIG \
|
||||
.streaming_ctrl = mxl111sf_ep6_streaming_ctrl, \
|
||||
.stream = { \
|
||||
.type = USB_ISOC, \
|
||||
.count = 5, \
|
||||
.endpoint = 0x06, \
|
||||
.u = { \
|
||||
.isoc = { \
|
||||
.framesperurb = 24, \
|
||||
.framesize = 3072, \
|
||||
.interval = 1, \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define MXL111SF_DEFAULT_DEVICE_PROPERTIES \
|
||||
.caps = DVB_USB_IS_AN_I2C_ADAPTER, \
|
||||
.usb_ctrl = DEVICE_SPECIFIC, \
|
||||
/* use usb alt setting 1 for EP4 ISOC transfer (dvb-t), \
|
||||
EP6 BULK transfer (atsc/qam), \
|
||||
use usb alt setting 2 for EP4 BULK transfer (dvb-t), \
|
||||
EP6 ISOC transfer (atsc/qam), \
|
||||
*/ \
|
||||
.power_ctrl = mxl111sf_power_ctrl, \
|
||||
.i2c_algo = &mxl111sf_i2c_algo, \
|
||||
.generic_bulk_ctrl_endpoint = MXL_EP2_REG_WRITE, \
|
||||
.generic_bulk_ctrl_endpoint_response = MXL_EP1_REG_READ, \
|
||||
.size_of_priv = sizeof(struct mxl111sf_state)
|
||||
|
||||
static struct dvb_usb_device_properties mxl111sf_atsc_bulk_properties = {
|
||||
MXL111SF_DEFAULT_DEVICE_PROPERTIES,
|
||||
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.fe_ioctl_override = mxl111sf_fe_ioctl_override,
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.size_of_priv = sizeof(struct mxl111sf_adap_state),
|
||||
|
||||
.frontend_attach = mxl111sf_lgdt3305_frontend_attach,
|
||||
.tuner_attach = mxl111sf_attach_tuner,
|
||||
|
||||
MXL111SF_EP6_BULK_STREAMING_CONFIG,
|
||||
}},
|
||||
},
|
||||
},
|
||||
.num_device_descs = 6,
|
||||
.devices = {
|
||||
{ "Hauppauge 126xxx ATSC (bulk)",
|
||||
{ NULL },
|
||||
{ &mxl111sf_table[1], &mxl111sf_table[5],
|
||||
NULL },
|
||||
},
|
||||
{ "Hauppauge 117xxx ATSC (bulk)",
|
||||
{ NULL },
|
||||
{ &mxl111sf_table[12],
|
||||
NULL },
|
||||
},
|
||||
{ "Hauppauge 126xxx ATSC+ (bulk)",
|
||||
{ NULL },
|
||||
{ &mxl111sf_table[0], &mxl111sf_table[3],
|
||||
&mxl111sf_table[7], &mxl111sf_table[9],
|
||||
&mxl111sf_table[10], NULL },
|
||||
},
|
||||
{ "Hauppauge 117xxx ATSC+ (bulk)",
|
||||
{ NULL },
|
||||
{ &mxl111sf_table[11], &mxl111sf_table[14],
|
||||
&mxl111sf_table[16], &mxl111sf_table[17],
|
||||
&mxl111sf_table[32], &mxl111sf_table[33],
|
||||
NULL },
|
||||
},
|
||||
{ "Hauppauge Mercury (tp-bulk)",
|
||||
{ NULL },
|
||||
{ &mxl111sf_table[19], &mxl111sf_table[21],
|
||||
&mxl111sf_table[23], &mxl111sf_table[25],
|
||||
&mxl111sf_table[27], NULL },
|
||||
},
|
||||
{ "Hauppauge WinTV-Aero-M",
|
||||
{ NULL },
|
||||
{ &mxl111sf_table[29], &mxl111sf_table[31],
|
||||
NULL },
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
static struct dvb_usb_device_properties mxl111sf_atsc_isoc_properties = {
|
||||
MXL111SF_DEFAULT_DEVICE_PROPERTIES,
|
||||
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.fe_ioctl_override = mxl111sf_fe_ioctl_override,
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.size_of_priv = sizeof(struct mxl111sf_adap_state),
|
||||
|
||||
.frontend_attach = mxl111sf_lgdt3305_frontend_attach,
|
||||
.tuner_attach = mxl111sf_attach_tuner,
|
||||
|
||||
MXL111SF_EP6_ISOC_STREAMING_CONFIG,
|
||||
}},
|
||||
},
|
||||
},
|
||||
.num_device_descs = 6,
|
||||
.devices = {
|
||||
{ "Hauppauge 126xxx ATSC (isoc)",
|
||||
{ NULL },
|
||||
{ &mxl111sf_table[1], &mxl111sf_table[5],
|
||||
NULL },
|
||||
},
|
||||
{ "Hauppauge 117xxx ATSC (isoc)",
|
||||
{ NULL },
|
||||
{ &mxl111sf_table[12],
|
||||
NULL },
|
||||
},
|
||||
{ "Hauppauge 126xxx ATSC+ (isoc)",
|
||||
{ NULL },
|
||||
{ &mxl111sf_table[0], &mxl111sf_table[3],
|
||||
&mxl111sf_table[7], &mxl111sf_table[9],
|
||||
&mxl111sf_table[10], NULL },
|
||||
},
|
||||
{ "Hauppauge 117xxx ATSC+ (isoc)",
|
||||
{ NULL },
|
||||
{ &mxl111sf_table[11], &mxl111sf_table[14],
|
||||
&mxl111sf_table[16], &mxl111sf_table[17],
|
||||
&mxl111sf_table[32], &mxl111sf_table[33],
|
||||
NULL },
|
||||
},
|
||||
{ "Hauppauge Mercury (tp-isoc)",
|
||||
{ NULL },
|
||||
{ &mxl111sf_table[19], &mxl111sf_table[21],
|
||||
&mxl111sf_table[23], &mxl111sf_table[25],
|
||||
&mxl111sf_table[27], NULL },
|
||||
},
|
||||
{ "Hauppauge WinTV-Aero-M (tp-isoc)",
|
||||
{ NULL },
|
||||
{ &mxl111sf_table[29], &mxl111sf_table[31],
|
||||
NULL },
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
static struct usb_driver mxl111sf_driver = {
|
||||
.name = "dvb_usb_mxl111sf",
|
||||
.probe = mxl111sf_probe,
|
||||
.disconnect = dvb_usb_device_exit,
|
||||
.id_table = mxl111sf_table,
|
||||
};
|
||||
|
||||
static int __init mxl111sf_module_init(void)
|
||||
{
|
||||
int result = usb_register(&mxl111sf_driver);
|
||||
if (result) {
|
||||
err("usb_register failed. Error number %d", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit mxl111sf_module_exit(void)
|
||||
{
|
||||
usb_deregister(&mxl111sf_driver);
|
||||
}
|
||||
|
||||
module_init(mxl111sf_module_init);
|
||||
module_exit(mxl111sf_module_exit);
|
||||
|
||||
MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>");
|
||||
MODULE_DESCRIPTION("Driver for MaxLinear MxL111SF");
|
||||
MODULE_VERSION("1.0");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
* End:
|
||||
*/
|
158
drivers/media/dvb/dvb-usb/mxl111sf.h
Normal file
158
drivers/media/dvb/dvb-usb/mxl111sf.h
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Michael Krufky (mkrufky@kernellabs.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.
|
||||
*
|
||||
* see Documentation/dvb/README.dvb-usb for more information
|
||||
*/
|
||||
|
||||
#ifndef _DVB_USB_MXL111SF_H_
|
||||
#define _DVB_USB_MXL111SF_H_
|
||||
|
||||
#ifdef DVB_USB_LOG_PREFIX
|
||||
#undef DVB_USB_LOG_PREFIX
|
||||
#endif
|
||||
#define DVB_USB_LOG_PREFIX "mxl111sf"
|
||||
#include "dvb-usb.h"
|
||||
#include <media/tveeprom.h>
|
||||
|
||||
#define MXL_EP1_REG_READ 1
|
||||
#define MXL_EP2_REG_WRITE 2
|
||||
#define MXL_EP3_INTERRUPT 3
|
||||
#define MXL_EP4_MPEG2 4
|
||||
#define MXL_EP5_I2S 5
|
||||
#define MXL_EP6_656 6
|
||||
#define MXL_EP6_MPEG2 6
|
||||
|
||||
#ifdef USING_ENUM_mxl111sf_current_mode
|
||||
enum mxl111sf_current_mode {
|
||||
mxl_mode_dvbt = MXL_EP4_MPEG2,
|
||||
mxl_mode_mh = MXL_EP5_I2S,
|
||||
mxl_mode_atsc = MXL_EP6_MPEG2,
|
||||
};
|
||||
#endif
|
||||
|
||||
enum mxl111sf_gpio_port_expander {
|
||||
mxl111sf_gpio_hw,
|
||||
mxl111sf_PCA9534,
|
||||
};
|
||||
|
||||
struct mxl111sf_state {
|
||||
struct dvb_usb_device *d;
|
||||
|
||||
enum mxl111sf_gpio_port_expander gpio_port_expander;
|
||||
u8 port_expander_addr;
|
||||
|
||||
u8 chip_id;
|
||||
u8 chip_ver;
|
||||
#define MXL111SF_V6 1
|
||||
#define MXL111SF_V8_100 2
|
||||
#define MXL111SF_V8_200 3
|
||||
u8 chip_rev;
|
||||
|
||||
#ifdef USING_ENUM_mxl111sf_current_mode
|
||||
enum mxl111sf_current_mode current_mode;
|
||||
#endif
|
||||
|
||||
#define MXL_TUNER_MODE 0
|
||||
#define MXL_SOC_MODE 1
|
||||
#define MXL_DEV_MODE_MASK 0x01
|
||||
#if 1
|
||||
int device_mode;
|
||||
#endif
|
||||
/* use usb alt setting 1 for EP4 ISOC transfer (dvb-t),
|
||||
EP5 BULK transfer (atsc-mh),
|
||||
EP6 BULK transfer (atsc/qam),
|
||||
use usb alt setting 2 for EP4 BULK transfer (dvb-t),
|
||||
EP5 ISOC transfer (atsc-mh),
|
||||
EP6 ISOC transfer (atsc/qam),
|
||||
*/
|
||||
int alt_mode;
|
||||
int gpio_mode;
|
||||
struct tveeprom tv;
|
||||
|
||||
struct mutex fe_lock;
|
||||
};
|
||||
|
||||
struct mxl111sf_adap_state {
|
||||
int alt_mode;
|
||||
int gpio_mode;
|
||||
int device_mode;
|
||||
int ep6_clockphase;
|
||||
int (*fe_init)(struct dvb_frontend *);
|
||||
int (*fe_sleep)(struct dvb_frontend *);
|
||||
};
|
||||
|
||||
int mxl111sf_read_reg(struct mxl111sf_state *state, u8 addr, u8 *data);
|
||||
int mxl111sf_write_reg(struct mxl111sf_state *state, u8 addr, u8 data);
|
||||
|
||||
struct mxl111sf_reg_ctrl_info {
|
||||
u8 addr;
|
||||
u8 mask;
|
||||
u8 data;
|
||||
};
|
||||
|
||||
int mxl111sf_write_reg_mask(struct mxl111sf_state *state,
|
||||
u8 addr, u8 mask, u8 data);
|
||||
int mxl111sf_ctrl_program_regs(struct mxl111sf_state *state,
|
||||
struct mxl111sf_reg_ctrl_info *ctrl_reg_info);
|
||||
|
||||
/* needed for hardware i2c functions in mxl111sf-i2c.c:
|
||||
* mxl111sf_i2c_send_data / mxl111sf_i2c_get_data */
|
||||
int mxl111sf_ctrl_msg(struct dvb_usb_device *d,
|
||||
u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen);
|
||||
|
||||
#define mxl_printk(kern, fmt, arg...) \
|
||||
printk(kern "%s: " fmt "\n", __func__, ##arg)
|
||||
|
||||
#define mxl_info(fmt, arg...) \
|
||||
mxl_printk(KERN_INFO, fmt, ##arg)
|
||||
|
||||
extern int dvb_usb_mxl111sf_debug;
|
||||
#define mxl_debug(fmt, arg...) \
|
||||
if (dvb_usb_mxl111sf_debug) \
|
||||
mxl_printk(KERN_DEBUG, fmt, ##arg)
|
||||
|
||||
#define MXL_I2C_DBG 0x04
|
||||
#define MXL_ADV_DBG 0x10
|
||||
#define mxl_debug_adv(fmt, arg...) \
|
||||
if (dvb_usb_mxl111sf_debug & MXL_ADV_DBG) \
|
||||
mxl_printk(KERN_DEBUG, fmt, ##arg)
|
||||
|
||||
#define mxl_i2c(fmt, arg...) \
|
||||
if (dvb_usb_mxl111sf_debug & MXL_I2C_DBG) \
|
||||
mxl_printk(KERN_DEBUG, fmt, ##arg)
|
||||
|
||||
#define mxl_i2c_adv(fmt, arg...) \
|
||||
if ((dvb_usb_mxl111sf_debug & (MXL_I2C_DBG | MXL_ADV_DBG)) == \
|
||||
(MXL_I2C_DBG | MXL_ADV_DBG)) \
|
||||
mxl_printk(KERN_DEBUG, fmt, ##arg)
|
||||
|
||||
/* The following allows the mxl_fail() macro defined below to work
|
||||
* in externel modules, such as mxl111sf-tuner.ko, even though
|
||||
* dvb_usb_mxl111sf_debug is not defined within those modules */
|
||||
#ifdef __MXL111SF_TUNER_H__
|
||||
#define MXL_ADV_DEBUG_ENABLED MXL_ADV_DBG
|
||||
#else
|
||||
#define MXL_ADV_DEBUG_ENABLED dvb_usb_mxl111sf_debug
|
||||
#endif
|
||||
|
||||
#define mxl_fail(ret) \
|
||||
({ \
|
||||
int __ret; \
|
||||
__ret = (ret < 0); \
|
||||
if ((__ret) && (MXL_ADV_DEBUG_ENABLED & MXL_ADV_DBG)) \
|
||||
mxl_printk(KERN_ERR, "error %d on line %d", \
|
||||
ret, __LINE__); \
|
||||
__ret; \
|
||||
})
|
||||
|
||||
#endif /* _DVB_USB_MXL111SF_H_ */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
* End:
|
||||
*/
|
@ -166,6 +166,8 @@ static struct dvb_usb_device_properties nova_t_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
.pid_filter_count = 32,
|
||||
|
||||
@ -186,7 +188,7 @@ static struct dvb_usb_device_properties nova_t_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
}},
|
||||
.size_of_priv = sizeof(struct dibusb_state),
|
||||
}
|
||||
},
|
||||
|
@ -263,10 +263,10 @@ static struct stv0299_config opera1_stv0299_config = {
|
||||
|
||||
static int opera1_frontend_attach(struct dvb_usb_adapter *d)
|
||||
{
|
||||
if ((d->fe =
|
||||
dvb_attach(stv0299_attach, &opera1_stv0299_config,
|
||||
&d->dev->i2c_adap)) != NULL) {
|
||||
d->fe->ops.set_voltage = opera1_set_voltage;
|
||||
d->fe_adap[0].fe = dvb_attach(stv0299_attach, &opera1_stv0299_config,
|
||||
&d->dev->i2c_adap);
|
||||
if ((d->fe_adap[0].fe) != NULL) {
|
||||
d->fe_adap[0].fe->ops.set_voltage = opera1_set_voltage;
|
||||
return 0;
|
||||
}
|
||||
info("not attached stv0299");
|
||||
@ -276,7 +276,7 @@ static int opera1_frontend_attach(struct dvb_usb_adapter *d)
|
||||
static int opera1_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
dvb_attach(
|
||||
dvb_pll_attach, adap->fe, 0xc0>>1,
|
||||
dvb_pll_attach, adap->fe_adap[0].fe, 0xc0>>1,
|
||||
&adap->dev->i2c_adap, DVB_PLL_OPERA1
|
||||
);
|
||||
return 0;
|
||||
@ -516,6 +516,8 @@ static struct dvb_usb_device_properties opera1_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.frontend_attach = opera1_frontend_attach,
|
||||
.streaming_ctrl = opera1_streaming_ctrl,
|
||||
.tuner_attach = opera1_tuner_attach,
|
||||
@ -535,6 +537,7 @@ static struct dvb_usb_device_properties opera1_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
}
|
||||
},
|
||||
.num_device_descs = 1,
|
||||
|
1079
drivers/media/dvb/dvb-usb/pctv452e.c
Normal file
1079
drivers/media/dvb/dvb-usb/pctv452e.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -292,7 +292,7 @@ static void technisat_usb2_green_led_control(struct work_struct *work)
|
||||
{
|
||||
struct technisat_usb2_state *state =
|
||||
container_of(work, struct technisat_usb2_state, green_led_work.work);
|
||||
struct dvb_frontend *fe = state->dev->adapter[0].fe;
|
||||
struct dvb_frontend *fe = state->dev->adapter[0].fe_adap[0].fe;
|
||||
|
||||
if (state->power_state == 0)
|
||||
goto schedule;
|
||||
@ -505,14 +505,14 @@ static int technisat_usb2_frontend_attach(struct dvb_usb_adapter *a)
|
||||
struct usb_device *udev = a->dev->udev;
|
||||
int ret;
|
||||
|
||||
a->fe = dvb_attach(stv090x_attach, &technisat_usb2_stv090x_config,
|
||||
a->fe_adap[0].fe = dvb_attach(stv090x_attach, &technisat_usb2_stv090x_config,
|
||||
&a->dev->i2c_adap, STV090x_DEMODULATOR_0);
|
||||
|
||||
if (a->fe) {
|
||||
if (a->fe_adap[0].fe) {
|
||||
struct stv6110x_devctl *ctl;
|
||||
|
||||
ctl = dvb_attach(stv6110x_attach,
|
||||
a->fe,
|
||||
a->fe_adap[0].fe,
|
||||
&technisat_usb2_stv6110x_config,
|
||||
&a->dev->i2c_adap);
|
||||
|
||||
@ -532,8 +532,8 @@ static int technisat_usb2_frontend_attach(struct dvb_usb_adapter *a)
|
||||
/* call the init function once to initialize
|
||||
tuner's clock output divider and demod's
|
||||
master clock */
|
||||
if (a->fe->ops.init)
|
||||
a->fe->ops.init(a->fe);
|
||||
if (a->fe_adap[0].fe->ops.init)
|
||||
a->fe_adap[0].fe->ops.init(a->fe_adap[0].fe);
|
||||
|
||||
if (mutex_lock_interruptible(&a->dev->i2c_mutex) < 0)
|
||||
return -EAGAIN;
|
||||
@ -548,20 +548,20 @@ static int technisat_usb2_frontend_attach(struct dvb_usb_adapter *a)
|
||||
if (ret != 0)
|
||||
err("could not set IF_CLK to external");
|
||||
|
||||
a->fe->ops.set_voltage = technisat_usb2_set_voltage;
|
||||
a->fe_adap[0].fe->ops.set_voltage = technisat_usb2_set_voltage;
|
||||
|
||||
/* if everything was successful assign a nice name to the frontend */
|
||||
strlcpy(a->fe->ops.info.name, a->dev->desc->name,
|
||||
sizeof(a->fe->ops.info.name));
|
||||
strlcpy(a->fe_adap[0].fe->ops.info.name, a->dev->desc->name,
|
||||
sizeof(a->fe_adap[0].fe->ops.info.name));
|
||||
} else {
|
||||
dvb_frontend_detach(a->fe);
|
||||
a->fe = NULL;
|
||||
dvb_frontend_detach(a->fe_adap[0].fe);
|
||||
a->fe_adap[0].fe = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
technisat_usb2_set_led_timer(a->dev, 1, 1);
|
||||
|
||||
return a->fe == NULL ? -ENODEV : 0;
|
||||
return a->fe_adap[0].fe == NULL ? -ENODEV : 0;
|
||||
}
|
||||
|
||||
/* Remote control */
|
||||
@ -697,6 +697,8 @@ static struct dvb_usb_device_properties technisat_usb2_devices = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.frontend_attach = technisat_usb2_frontend_attach,
|
||||
|
||||
.stream = {
|
||||
@ -711,7 +713,7 @@ static struct dvb_usb_device_properties technisat_usb2_devices = {
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
}},
|
||||
.size_of_priv = 0,
|
||||
},
|
||||
},
|
||||
|
@ -30,18 +30,43 @@
|
||||
#include "tda826x.h"
|
||||
#include "tda10086.h"
|
||||
#include "tda1002x.h"
|
||||
#include "tda10048.h"
|
||||
#include "tda827x.h"
|
||||
#include "lnbp21.h"
|
||||
/* CA */
|
||||
#include "dvb_ca_en50221.h"
|
||||
|
||||
/* debug */
|
||||
static int dvb_usb_ttusb2_debug;
|
||||
#define deb_info(args...) dprintk(dvb_usb_ttusb2_debug,0x01,args)
|
||||
module_param_named(debug,dvb_usb_ttusb2_debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))." DVB_USB_DEBUG_STATUS);
|
||||
static int dvb_usb_ttusb2_debug_ci;
|
||||
module_param_named(debug_ci,dvb_usb_ttusb2_debug_ci, int, 0644);
|
||||
MODULE_PARM_DESC(debug_ci, "set debugging ci." DVB_USB_DEBUG_STATUS);
|
||||
|
||||
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
|
||||
|
||||
#define ci_dbg(format, arg...) \
|
||||
do { \
|
||||
if (dvb_usb_ttusb2_debug_ci) \
|
||||
printk(KERN_DEBUG DVB_USB_LOG_PREFIX \
|
||||
": %s " format "\n" , __func__, ## arg); \
|
||||
} while (0)
|
||||
|
||||
enum {
|
||||
TT3650_CMD_CI_TEST = 0x40,
|
||||
TT3650_CMD_CI_RD_CTRL,
|
||||
TT3650_CMD_CI_WR_CTRL,
|
||||
TT3650_CMD_CI_RD_ATTR,
|
||||
TT3650_CMD_CI_WR_ATTR,
|
||||
TT3650_CMD_CI_RESET,
|
||||
TT3650_CMD_CI_SET_VIDEO_PORT
|
||||
};
|
||||
|
||||
struct ttusb2_state {
|
||||
struct dvb_ca_en50221 ca;
|
||||
struct mutex ca_mutex;
|
||||
u8 id;
|
||||
u16 last_rc_key;
|
||||
};
|
||||
@ -78,11 +103,260 @@ static int ttusb2_msg(struct dvb_usb_device *d, u8 cmd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ci */
|
||||
static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data, unsigned int write_len, unsigned int read_len)
|
||||
{
|
||||
int ret;
|
||||
u8 rx[60];/* (64 -4) */
|
||||
ret = ttusb2_msg(d, cmd, data, write_len, rx, read_len);
|
||||
if (!ret)
|
||||
memcpy(data, rx, read_len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tt3650_ci_msg_locked(struct dvb_ca_en50221 *ca, u8 cmd, u8 *data, unsigned int write_len, unsigned int read_len)
|
||||
{
|
||||
struct dvb_usb_device *d = ca->data;
|
||||
struct ttusb2_state *state = d->priv;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&state->ca_mutex);
|
||||
ret = tt3650_ci_msg(d, cmd, data, write_len, read_len);
|
||||
mutex_unlock(&state->ca_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tt3650_ci_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
|
||||
{
|
||||
u8 buf[3];
|
||||
int ret = 0;
|
||||
|
||||
if (slot)
|
||||
return -EINVAL;
|
||||
|
||||
buf[0] = (address >> 8) & 0x0F;
|
||||
buf[1] = address;
|
||||
|
||||
|
||||
ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_RD_ATTR, buf, 2, 3);
|
||||
|
||||
ci_dbg("%04x -> %d 0x%02x", address, ret, buf[2]);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return buf[2];
|
||||
}
|
||||
|
||||
static int tt3650_ci_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
|
||||
{
|
||||
u8 buf[3];
|
||||
|
||||
ci_dbg("%d 0x%04x 0x%02x", slot, address, value);
|
||||
|
||||
if (slot)
|
||||
return -EINVAL;
|
||||
|
||||
buf[0] = (address >> 8) & 0x0F;
|
||||
buf[1] = address;
|
||||
buf[2] = value;
|
||||
|
||||
return tt3650_ci_msg_locked(ca, TT3650_CMD_CI_WR_ATTR, buf, 3, 3);
|
||||
}
|
||||
|
||||
static int tt3650_ci_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
|
||||
{
|
||||
u8 buf[2];
|
||||
int ret;
|
||||
|
||||
if (slot)
|
||||
return -EINVAL;
|
||||
|
||||
buf[0] = address & 3;
|
||||
|
||||
ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_RD_CTRL, buf, 1, 2);
|
||||
|
||||
ci_dbg("0x%02x -> %d 0x%02x", address, ret, buf[1]);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return buf[1];
|
||||
}
|
||||
|
||||
static int tt3650_ci_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
|
||||
{
|
||||
u8 buf[2];
|
||||
|
||||
ci_dbg("%d 0x%02x 0x%02x", slot, address, value);
|
||||
|
||||
if (slot)
|
||||
return -EINVAL;
|
||||
|
||||
buf[0] = address;
|
||||
buf[1] = value;
|
||||
|
||||
return tt3650_ci_msg_locked(ca, TT3650_CMD_CI_WR_CTRL, buf, 2, 2);
|
||||
}
|
||||
|
||||
static int tt3650_ci_set_video_port(struct dvb_ca_en50221 *ca, int slot, int enable)
|
||||
{
|
||||
u8 buf[1];
|
||||
int ret;
|
||||
|
||||
ci_dbg("%d %d", slot, enable);
|
||||
|
||||
if (slot)
|
||||
return -EINVAL;
|
||||
|
||||
buf[0] = enable;
|
||||
|
||||
ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_SET_VIDEO_PORT, buf, 1, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (enable != buf[0]) {
|
||||
err("CI not %sabled.", enable ? "en" : "dis");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tt3650_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
|
||||
{
|
||||
return tt3650_ci_set_video_port(ca, slot, 0);
|
||||
}
|
||||
|
||||
static int tt3650_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
|
||||
{
|
||||
return tt3650_ci_set_video_port(ca, slot, 1);
|
||||
}
|
||||
|
||||
static int tt3650_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot)
|
||||
{
|
||||
struct dvb_usb_device *d = ca->data;
|
||||
struct ttusb2_state *state = d->priv;
|
||||
u8 buf[1];
|
||||
int ret;
|
||||
|
||||
ci_dbg("%d", slot);
|
||||
|
||||
if (slot)
|
||||
return -EINVAL;
|
||||
|
||||
buf[0] = 0;
|
||||
|
||||
mutex_lock(&state->ca_mutex);
|
||||
|
||||
ret = tt3650_ci_msg(d, TT3650_CMD_CI_RESET, buf, 1, 1);
|
||||
if (ret)
|
||||
goto failed;
|
||||
|
||||
msleep(500);
|
||||
|
||||
buf[0] = 1;
|
||||
|
||||
ret = tt3650_ci_msg(d, TT3650_CMD_CI_RESET, buf, 1, 1);
|
||||
if (ret)
|
||||
goto failed;
|
||||
|
||||
msleep(500);
|
||||
|
||||
buf[0] = 0; /* FTA */
|
||||
|
||||
ret = tt3650_ci_msg(d, TT3650_CMD_CI_SET_VIDEO_PORT, buf, 1, 1);
|
||||
|
||||
msleep(1100);
|
||||
|
||||
failed:
|
||||
mutex_unlock(&state->ca_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tt3650_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
|
||||
{
|
||||
u8 buf[1];
|
||||
int ret;
|
||||
|
||||
if (slot)
|
||||
return -EINVAL;
|
||||
|
||||
ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_TEST, buf, 0, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (1 == buf[0]) {
|
||||
return DVB_CA_EN50221_POLL_CAM_PRESENT |
|
||||
DVB_CA_EN50221_POLL_CAM_READY;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tt3650_ci_uninit(struct dvb_usb_device *d)
|
||||
{
|
||||
struct ttusb2_state *state;
|
||||
|
||||
ci_dbg("");
|
||||
|
||||
if (NULL == d)
|
||||
return;
|
||||
|
||||
state = d->priv;
|
||||
if (NULL == state)
|
||||
return;
|
||||
|
||||
if (NULL == state->ca.data)
|
||||
return;
|
||||
|
||||
dvb_ca_en50221_release(&state->ca);
|
||||
|
||||
memset(&state->ca, 0, sizeof(state->ca));
|
||||
}
|
||||
|
||||
static int tt3650_ci_init(struct dvb_usb_adapter *a)
|
||||
{
|
||||
struct dvb_usb_device *d = a->dev;
|
||||
struct ttusb2_state *state = d->priv;
|
||||
int ret;
|
||||
|
||||
ci_dbg("");
|
||||
|
||||
mutex_init(&state->ca_mutex);
|
||||
|
||||
state->ca.owner = THIS_MODULE;
|
||||
state->ca.read_attribute_mem = tt3650_ci_read_attribute_mem;
|
||||
state->ca.write_attribute_mem = tt3650_ci_write_attribute_mem;
|
||||
state->ca.read_cam_control = tt3650_ci_read_cam_control;
|
||||
state->ca.write_cam_control = tt3650_ci_write_cam_control;
|
||||
state->ca.slot_reset = tt3650_ci_slot_reset;
|
||||
state->ca.slot_shutdown = tt3650_ci_slot_shutdown;
|
||||
state->ca.slot_ts_enable = tt3650_ci_slot_ts_enable;
|
||||
state->ca.poll_slot_status = tt3650_ci_poll_slot_status;
|
||||
state->ca.data = d;
|
||||
|
||||
ret = dvb_ca_en50221_init(&a->dvb_adap,
|
||||
&state->ca,
|
||||
/* flags */ 0,
|
||||
/* n_slots */ 1);
|
||||
if (ret) {
|
||||
err("Cannot initialize CI: Error %d.", ret);
|
||||
memset(&state->ca, 0, sizeof(state->ca));
|
||||
return ret;
|
||||
}
|
||||
|
||||
info("CI initialized.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ttusb2_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
|
||||
{
|
||||
struct dvb_usb_device *d = i2c_get_adapdata(adap);
|
||||
static u8 obuf[60], ibuf[60];
|
||||
int i,read;
|
||||
int i, write_read, read;
|
||||
|
||||
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
|
||||
return -EAGAIN;
|
||||
@ -91,28 +365,35 @@ static int ttusb2_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num
|
||||
warn("more than 2 i2c messages at a time is not handled yet. TODO.");
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
read = i+1 < num && (msg[i+1].flags & I2C_M_RD);
|
||||
write_read = i+1 < num && (msg[i+1].flags & I2C_M_RD);
|
||||
read = msg[i].flags & I2C_M_RD;
|
||||
|
||||
obuf[0] = (msg[i].addr << 1) | read;
|
||||
obuf[1] = msg[i].len;
|
||||
obuf[0] = (msg[i].addr << 1) | (write_read | read);
|
||||
if (read)
|
||||
obuf[1] = 0;
|
||||
else
|
||||
obuf[1] = msg[i].len;
|
||||
|
||||
/* read request */
|
||||
if (read)
|
||||
if (write_read)
|
||||
obuf[2] = msg[i+1].len;
|
||||
else if (read)
|
||||
obuf[2] = msg[i].len;
|
||||
else
|
||||
obuf[2] = 0;
|
||||
|
||||
memcpy(&obuf[3],msg[i].buf,msg[i].len);
|
||||
memcpy(&obuf[3], msg[i].buf, msg[i].len);
|
||||
|
||||
if (ttusb2_msg(d, CMD_I2C_XFER, obuf, msg[i].len+3, ibuf, obuf[2] + 3) < 0) {
|
||||
err("i2c transfer failed.");
|
||||
break;
|
||||
}
|
||||
|
||||
if (read) {
|
||||
memcpy(msg[i+1].buf,&ibuf[3],msg[i+1].len);
|
||||
if (write_read) {
|
||||
memcpy(msg[i+1].buf, &ibuf[3], msg[i+1].len);
|
||||
i++;
|
||||
}
|
||||
} else if (read)
|
||||
memcpy(msg[i].buf, &ibuf[3], msg[i].len);
|
||||
}
|
||||
|
||||
mutex_unlock(&d->i2c_mutex);
|
||||
@ -190,12 +471,31 @@ static struct tda10023_config tda10023_config = {
|
||||
.deltaf = 0xa511,
|
||||
};
|
||||
|
||||
static struct tda10048_config tda10048_config = {
|
||||
.demod_address = 0x10 >> 1,
|
||||
.output_mode = TDA10048_PARALLEL_OUTPUT,
|
||||
.inversion = TDA10048_INVERSION_ON,
|
||||
.dtv6_if_freq_khz = TDA10048_IF_4000,
|
||||
.dtv7_if_freq_khz = TDA10048_IF_4500,
|
||||
.dtv8_if_freq_khz = TDA10048_IF_5000,
|
||||
.clk_freq_khz = TDA10048_CLK_16000,
|
||||
.no_firmware = 1,
|
||||
.set_pll = true ,
|
||||
.pll_m = 5,
|
||||
.pll_n = 3,
|
||||
.pll_p = 0,
|
||||
};
|
||||
|
||||
static struct tda827x_config tda827x_config = {
|
||||
.config = 0,
|
||||
};
|
||||
|
||||
static int ttusb2_frontend_tda10086_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
if (usb_set_interface(adap->dev->udev,0,3) < 0)
|
||||
err("set interface to alts=3 failed");
|
||||
|
||||
if ((adap->fe = dvb_attach(tda10086_attach, &tda10086_config, &adap->dev->i2c_adap)) == NULL) {
|
||||
if ((adap->fe_adap[0].fe = dvb_attach(tda10086_attach, &tda10086_config, &adap->dev->i2c_adap)) == NULL) {
|
||||
deb_info("TDA10086 attach failed\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
@ -203,20 +503,57 @@ static int ttusb2_frontend_tda10086_attach(struct dvb_usb_adapter *adap)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ttusb2_ct3650_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
|
||||
{
|
||||
struct dvb_usb_adapter *adap = fe->dvb->priv;
|
||||
|
||||
return adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, enable);
|
||||
}
|
||||
|
||||
static int ttusb2_frontend_tda10023_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
if (usb_set_interface(adap->dev->udev, 0, 3) < 0)
|
||||
err("set interface to alts=3 failed");
|
||||
if ((adap->fe = dvb_attach(tda10023_attach, &tda10023_config, &adap->dev->i2c_adap, 0x48)) == NULL) {
|
||||
deb_info("TDA10023 attach failed\n");
|
||||
return -ENODEV;
|
||||
|
||||
if (adap->fe_adap[0].fe == NULL) {
|
||||
/* FE 0 DVB-C */
|
||||
adap->fe_adap[0].fe = dvb_attach(tda10023_attach,
|
||||
&tda10023_config, &adap->dev->i2c_adap, 0x48);
|
||||
|
||||
if (adap->fe_adap[0].fe == NULL) {
|
||||
deb_info("TDA10023 attach failed\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
tt3650_ci_init(adap);
|
||||
} else {
|
||||
adap->fe_adap[1].fe = dvb_attach(tda10048_attach,
|
||||
&tda10048_config, &adap->dev->i2c_adap);
|
||||
|
||||
if (adap->fe_adap[1].fe == NULL) {
|
||||
deb_info("TDA10048 attach failed\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* tuner is behind TDA10023 I2C-gate */
|
||||
adap->fe_adap[1].fe->ops.i2c_gate_ctrl = ttusb2_ct3650_i2c_gate_ctrl;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ttusb2_tuner_tda827x_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
if (dvb_attach(tda827x_attach, adap->fe, 0x61, &adap->dev->i2c_adap, NULL) == NULL) {
|
||||
struct dvb_frontend *fe;
|
||||
|
||||
/* MFE: select correct FE to attach tuner since that's called twice */
|
||||
if (adap->fe_adap[1].fe == NULL)
|
||||
fe = adap->fe_adap[0].fe;
|
||||
else
|
||||
fe = adap->fe_adap[1].fe;
|
||||
|
||||
/* attach tuner */
|
||||
if (dvb_attach(tda827x_attach, fe, 0x61, &adap->dev->i2c_adap, &tda827x_config) == NULL) {
|
||||
printk(KERN_ERR "%s: No tda827x found!\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
@ -225,12 +562,12 @@ static int ttusb2_tuner_tda827x_attach(struct dvb_usb_adapter *adap)
|
||||
|
||||
static int ttusb2_tuner_tda826x_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
if (dvb_attach(tda826x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, 0) == NULL) {
|
||||
if (dvb_attach(tda826x_attach, adap->fe_adap[0].fe, 0x60, &adap->dev->i2c_adap, 0) == NULL) {
|
||||
deb_info("TDA8263 attach failed\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (dvb_attach(lnbp21_attach, adap->fe, &adap->dev->i2c_adap, 0, 0) == NULL) {
|
||||
if (dvb_attach(lnbp21_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap, 0, 0) == NULL) {
|
||||
deb_info("LNBP21 attach failed\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
@ -242,6 +579,14 @@ static struct dvb_usb_device_properties ttusb2_properties;
|
||||
static struct dvb_usb_device_properties ttusb2_properties_s2400;
|
||||
static struct dvb_usb_device_properties ttusb2_properties_ct3650;
|
||||
|
||||
static void ttusb2_usb_disconnect(struct usb_interface *intf)
|
||||
{
|
||||
struct dvb_usb_device *d = usb_get_intfdata(intf);
|
||||
|
||||
tt3650_ci_uninit(d);
|
||||
dvb_usb_device_exit(intf);
|
||||
}
|
||||
|
||||
static int ttusb2_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
@ -277,6 +622,8 @@ static struct dvb_usb_device_properties ttusb2_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.streaming_ctrl = NULL, // ttusb2_streaming_ctrl,
|
||||
|
||||
.frontend_attach = ttusb2_frontend_tda10086_attach,
|
||||
@ -295,6 +642,7 @@ static struct dvb_usb_device_properties ttusb2_properties = {
|
||||
}
|
||||
}
|
||||
}
|
||||
}},
|
||||
}
|
||||
},
|
||||
|
||||
@ -329,6 +677,8 @@ static struct dvb_usb_device_properties ttusb2_properties_s2400 = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.streaming_ctrl = NULL,
|
||||
|
||||
.frontend_attach = ttusb2_frontend_tda10086_attach,
|
||||
@ -347,6 +697,7 @@ static struct dvb_usb_device_properties ttusb2_properties_s2400 = {
|
||||
}
|
||||
}
|
||||
}
|
||||
}},
|
||||
}
|
||||
},
|
||||
|
||||
@ -383,6 +734,8 @@ static struct dvb_usb_device_properties ttusb2_properties_ct3650 = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 2,
|
||||
.fe = {{
|
||||
.streaming_ctrl = NULL,
|
||||
|
||||
.frontend_attach = ttusb2_frontend_tda10023_attach,
|
||||
@ -401,6 +754,26 @@ static struct dvb_usb_device_properties ttusb2_properties_ct3650 = {
|
||||
}
|
||||
}
|
||||
}
|
||||
}, {
|
||||
.streaming_ctrl = NULL,
|
||||
|
||||
.frontend_attach = ttusb2_frontend_tda10023_attach,
|
||||
.tuner_attach = ttusb2_tuner_tda827x_attach,
|
||||
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.stream = {
|
||||
.type = USB_ISOC,
|
||||
.count = 5,
|
||||
.endpoint = 0x02,
|
||||
.u = {
|
||||
.isoc = {
|
||||
.framesperurb = 4,
|
||||
.framesize = 940,
|
||||
.interval = 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
}},
|
||||
},
|
||||
},
|
||||
|
||||
@ -422,7 +795,7 @@ static struct dvb_usb_device_properties ttusb2_properties_ct3650 = {
|
||||
static struct usb_driver ttusb2_driver = {
|
||||
.name = "dvb_usb_ttusb2",
|
||||
.probe = ttusb2_probe,
|
||||
.disconnect = dvb_usb_device_exit,
|
||||
.disconnect = ttusb2_usb_disconnect,
|
||||
.id_table = ttusb2_table,
|
||||
};
|
||||
|
||||
|
@ -60,14 +60,14 @@ static int umt_mt352_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
umt_config.demod_init = umt_mt352_demod_init;
|
||||
umt_config.demod_address = 0xf;
|
||||
|
||||
adap->fe = dvb_attach(mt352_attach, &umt_config, &adap->dev->i2c_adap);
|
||||
adap->fe_adap[0].fe = dvb_attach(mt352_attach, &umt_config, &adap->dev->i2c_adap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int umt_tuner_attach (struct dvb_usb_adapter *adap)
|
||||
{
|
||||
dvb_attach(dvb_pll_attach, adap->fe, 0x61, NULL, DVB_PLL_TUA6034);
|
||||
dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x61, NULL, DVB_PLL_TUA6034);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -100,6 +100,8 @@ static struct dvb_usb_device_properties umt_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.streaming_ctrl = dibusb2_0_streaming_ctrl,
|
||||
.frontend_attach = umt_mt352_frontend_attach,
|
||||
.tuner_attach = umt_tuner_attach,
|
||||
@ -115,7 +117,7 @@ static struct dvb_usb_device_properties umt_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
}},
|
||||
.size_of_priv = sizeof(struct dibusb_state),
|
||||
}
|
||||
},
|
||||
|
@ -148,7 +148,7 @@ static int usb_bulk_urb_init(struct usb_data_stream *stream)
|
||||
if (!stream->urb_list[i]) {
|
||||
deb_mem("not enough memory for urb_alloc_urb!.\n");
|
||||
for (j = 0; j < i; j++)
|
||||
usb_free_urb(stream->urb_list[i]);
|
||||
usb_free_urb(stream->urb_list[j]);
|
||||
return -ENOMEM;
|
||||
}
|
||||
usb_fill_bulk_urb( stream->urb_list[i], stream->udev,
|
||||
@ -181,7 +181,7 @@ static int usb_isoc_urb_init(struct usb_data_stream *stream)
|
||||
if (!stream->urb_list[i]) {
|
||||
deb_mem("not enough memory for urb_alloc_urb!\n");
|
||||
for (j = 0; j < i; j++)
|
||||
usb_free_urb(stream->urb_list[i]);
|
||||
usb_free_urb(stream->urb_list[j]);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
@ -320,7 +320,7 @@ static int vp702x_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
|
||||
vp702x_init_pid_filter(adap);
|
||||
|
||||
adap->fe = vp702x_fe_attach(adap->dev);
|
||||
adap->fe_adap[0].fe = vp702x_fe_attach(adap->dev);
|
||||
vp702x_usb_out_op(adap->dev, SET_TUNER_POWER_REQ, 1, 7, NULL, 0);
|
||||
|
||||
return 0;
|
||||
@ -383,6 +383,8 @@ static struct dvb_usb_device_properties vp702x_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.caps = DVB_USB_ADAP_RECEIVES_204_BYTE_TS,
|
||||
|
||||
.streaming_ctrl = vp702x_streaming_ctrl,
|
||||
@ -399,6 +401,7 @@ static struct dvb_usb_device_properties vp702x_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
.size_of_priv = sizeof(struct vp702x_adapter_state),
|
||||
}
|
||||
},
|
||||
|
@ -214,7 +214,7 @@ static int vp7045_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
/* Dump the EEPROM */
|
||||
/* vp7045_read_eeprom(d,buf, 255, FX2_ID_ADDR); */
|
||||
|
||||
adap->fe = vp7045_fe_attach(adap->dev);
|
||||
adap->fe_adap[0].fe = vp7045_fe_attach(adap->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -245,6 +245,8 @@ static struct dvb_usb_device_properties vp7045_properties = {
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.frontend_attach = vp7045_frontend_attach,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.stream = {
|
||||
@ -257,6 +259,7 @@ static struct dvb_usb_device_properties vp7045_properties = {
|
||||
}
|
||||
}
|
||||
},
|
||||
}},
|
||||
}
|
||||
},
|
||||
.power_ctrl = vp7045_power_ctrl,
|
||||
|
@ -236,6 +236,13 @@ config DVB_MB86A16
|
||||
A DVB-S/DSS Direct Conversion reveiver.
|
||||
Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_TDA10071
|
||||
tristate "NXP TDA10071"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
Say Y when you want to support this frontend.
|
||||
|
||||
comment "DVB-T (terrestrial) frontends"
|
||||
depends on DVB_CORE
|
||||
|
||||
@ -600,6 +607,16 @@ config DVB_LNBP21
|
||||
help
|
||||
An SEC control chips.
|
||||
|
||||
config DVB_LNBP22
|
||||
tristate "LNBP22 SEC controllers"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
LNB power supply and control voltage
|
||||
regulator chip with step-up converter
|
||||
and I2C interface.
|
||||
Say Y when you want to support this chip.
|
||||
|
||||
config DVB_ISL6405
|
||||
tristate "ISL6405 SEC controller"
|
||||
depends on DVB_CORE && I2C
|
||||
@ -621,6 +638,11 @@ config DVB_ISL6423
|
||||
help
|
||||
A SEC controller chip from Intersil
|
||||
|
||||
config DVB_A8293
|
||||
tristate "Allegro A8293"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
|
||||
config DVB_LGS8GL5
|
||||
tristate "Silicon Legend LGS-8GL5 demodulator (OFDM)"
|
||||
depends on DVB_CORE && I2C
|
||||
@ -661,6 +683,14 @@ config DVB_IX2505V
|
||||
help
|
||||
A DVB-S tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_IT913X_FE
|
||||
tristate "it913x frontend and it9137 tuner"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
A DVB-T tuner module.
|
||||
Say Y when you want to support this frontend.
|
||||
|
||||
comment "Tools to develop new frontends"
|
||||
|
||||
config DVB_DUMMY_FE
|
||||
|
@ -2,8 +2,8 @@
|
||||
# Makefile for the kernel DVB frontend device drivers.
|
||||
#
|
||||
|
||||
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
|
||||
EXTRA_CFLAGS += -Idrivers/media/common/tuners/
|
||||
ccflags-y += -Idrivers/media/dvb/dvb-core/
|
||||
ccflags-y += -Idrivers/media/common/tuners/
|
||||
|
||||
stb0899-objs = stb0899_drv.o stb0899_algo.o
|
||||
stv0900-objs = stv0900_core.o stv0900_sw.o
|
||||
@ -52,6 +52,7 @@ obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
|
||||
obj-$(CONFIG_DVB_LGDT3305) += lgdt3305.o
|
||||
obj-$(CONFIG_DVB_CX24123) += cx24123.o
|
||||
obj-$(CONFIG_DVB_LNBP21) += lnbp21.o
|
||||
obj-$(CONFIG_DVB_LNBP22) += lnbp22.o
|
||||
obj-$(CONFIG_DVB_ISL6405) += isl6405.o
|
||||
obj-$(CONFIG_DVB_ISL6421) += isl6421.o
|
||||
obj-$(CONFIG_DVB_TDA10086) += tda10086.o
|
||||
@ -91,4 +92,7 @@ obj-$(CONFIG_DVB_STV0367) += stv0367.o
|
||||
obj-$(CONFIG_DVB_CXD2820R) += cxd2820r.o
|
||||
obj-$(CONFIG_DVB_DRXK) += drxk.o
|
||||
obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o
|
||||
obj-$(CONFIG_DVB_IT913X_FE) += it913x-fe.o
|
||||
obj-$(CONFIG_DVB_A8293) += a8293.o
|
||||
obj-$(CONFIG_DVB_TDA10071) += tda10071.o
|
||||
|
||||
|
184
drivers/media/dvb/frontends/a8293.c
Normal file
184
drivers/media/dvb/frontends/a8293.c
Normal file
@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Allegro A8293 SEC driver
|
||||
*
|
||||
* Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
|
||||
*
|
||||
* 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 "dvb_frontend.h"
|
||||
#include "a8293.h"
|
||||
|
||||
static int debug;
|
||||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
|
||||
|
||||
#define LOG_PREFIX "a8293"
|
||||
|
||||
#undef dbg
|
||||
#define dbg(f, arg...) \
|
||||
if (debug) \
|
||||
printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg)
|
||||
#undef err
|
||||
#define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg)
|
||||
#undef info
|
||||
#define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg)
|
||||
#undef warn
|
||||
#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
|
||||
|
||||
|
||||
struct a8293_priv {
|
||||
struct i2c_adapter *i2c;
|
||||
const struct a8293_config *cfg;
|
||||
u8 reg[2];
|
||||
};
|
||||
|
||||
static int a8293_i2c(struct a8293_priv *priv, u8 *val, int len, bool rd)
|
||||
{
|
||||
int ret;
|
||||
struct i2c_msg msg[1] = {
|
||||
{
|
||||
.addr = priv->cfg->i2c_addr,
|
||||
.len = len,
|
||||
.buf = val,
|
||||
}
|
||||
};
|
||||
|
||||
if (rd)
|
||||
msg[0].flags = I2C_M_RD;
|
||||
else
|
||||
msg[0].flags = 0;
|
||||
|
||||
ret = i2c_transfer(priv->i2c, msg, 1);
|
||||
if (ret == 1) {
|
||||
ret = 0;
|
||||
} else {
|
||||
warn("i2c failed=%d rd=%d", ret, rd);
|
||||
ret = -EREMOTEIO;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int a8293_wr(struct a8293_priv *priv, u8 *val, int len)
|
||||
{
|
||||
return a8293_i2c(priv, val, len, 0);
|
||||
}
|
||||
|
||||
static int a8293_rd(struct a8293_priv *priv, u8 *val, int len)
|
||||
{
|
||||
return a8293_i2c(priv, val, len, 1);
|
||||
}
|
||||
|
||||
static int a8293_set_voltage(struct dvb_frontend *fe,
|
||||
fe_sec_voltage_t fe_sec_voltage)
|
||||
{
|
||||
struct a8293_priv *priv = fe->sec_priv;
|
||||
int ret;
|
||||
|
||||
dbg("%s: fe_sec_voltage=%d", __func__, fe_sec_voltage);
|
||||
|
||||
switch (fe_sec_voltage) {
|
||||
case SEC_VOLTAGE_OFF:
|
||||
/* ENB=0 */
|
||||
priv->reg[0] = 0x10;
|
||||
break;
|
||||
case SEC_VOLTAGE_13:
|
||||
/* VSEL0=1, VSEL1=0, VSEL2=0, VSEL3=0, ENB=1*/
|
||||
priv->reg[0] = 0x31;
|
||||
break;
|
||||
case SEC_VOLTAGE_18:
|
||||
/* VSEL0=0, VSEL1=0, VSEL2=0, VSEL3=1, ENB=1*/
|
||||
priv->reg[0] = 0x38;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
};
|
||||
|
||||
ret = a8293_wr(priv, &priv->reg[0], 1);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
return ret;
|
||||
err:
|
||||
dbg("%s: failed=%d", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void a8293_release_sec(struct dvb_frontend *fe)
|
||||
{
|
||||
dbg("%s:", __func__);
|
||||
|
||||
a8293_set_voltage(fe, SEC_VOLTAGE_OFF);
|
||||
|
||||
kfree(fe->sec_priv);
|
||||
fe->sec_priv = NULL;
|
||||
}
|
||||
|
||||
struct dvb_frontend *a8293_attach(struct dvb_frontend *fe,
|
||||
struct i2c_adapter *i2c, const struct a8293_config *cfg)
|
||||
{
|
||||
int ret;
|
||||
struct a8293_priv *priv = NULL;
|
||||
u8 buf[2];
|
||||
|
||||
/* allocate memory for the internal priv */
|
||||
priv = kzalloc(sizeof(struct a8293_priv), GFP_KERNEL);
|
||||
if (priv == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* setup the priv */
|
||||
priv->i2c = i2c;
|
||||
priv->cfg = cfg;
|
||||
fe->sec_priv = priv;
|
||||
|
||||
/* check if the SEC is there */
|
||||
ret = a8293_rd(priv, buf, 2);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
/* ENB=0 */
|
||||
priv->reg[0] = 0x10;
|
||||
ret = a8293_wr(priv, &priv->reg[1], 1);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
/* TMODE=0, TGATE=1 */
|
||||
priv->reg[1] = 0x82;
|
||||
ret = a8293_wr(priv, &priv->reg[1], 1);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
info("Allegro A8293 SEC attached.");
|
||||
|
||||
fe->ops.release_sec = a8293_release_sec;
|
||||
|
||||
/* override frontend ops */
|
||||
fe->ops.set_voltage = a8293_set_voltage;
|
||||
|
||||
return fe;
|
||||
err:
|
||||
dbg("%s: failed=%d", __func__, ret);
|
||||
kfree(priv);
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(a8293_attach);
|
||||
|
||||
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
|
||||
MODULE_DESCRIPTION("Allegro A8293 SEC driver");
|
||||
MODULE_LICENSE("GPL");
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* NXP TDA18212HN silicon tuner driver
|
||||
* Allegro A8293 SEC driver
|
||||
*
|
||||
* Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
|
||||
*
|
||||
@ -18,27 +18,24 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef TDA18212_PRIV_H
|
||||
#define TDA18212_PRIV_H
|
||||
#ifndef A8293_H
|
||||
#define A8293_H
|
||||
|
||||
#include "tda18212.h"
|
||||
|
||||
#define LOG_PREFIX "tda18212"
|
||||
|
||||
#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 tda18212_priv {
|
||||
struct tda18212_config *cfg;
|
||||
struct i2c_adapter *i2c;
|
||||
struct a8293_config {
|
||||
u8 i2c_addr;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_A8293) || \
|
||||
(defined(CONFIG_DVB_A8293_MODULE) && defined(MODULE))
|
||||
extern struct dvb_frontend *a8293_attach(struct dvb_frontend *fe,
|
||||
struct i2c_adapter *i2c, const struct a8293_config *cfg);
|
||||
#else
|
||||
static inline struct dvb_frontend *a8293_attach(struct dvb_frontend *fe,
|
||||
struct i2c_adapter *i2c, const struct a8293_config *cfg)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* A8293_H */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user